mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-20 09:25:45 +00:00
Compare commits
6 commits
53b93b8954
...
f2e352822e
Author | SHA1 | Date | |
---|---|---|---|
|
f2e352822e | ||
|
f414ebdf34 | ||
|
ab631e6b28 | ||
|
fc6f9de3fa | ||
|
9dfe3cece0 | ||
|
d125994270 |
67 changed files with 617 additions and 586 deletions
|
@ -53,8 +53,6 @@ add_library(dynarmic
|
|||
common/lut_from_list.h
|
||||
common/math_util.cpp
|
||||
common/math_util.h
|
||||
common/memory_pool.cpp
|
||||
common/memory_pool.h
|
||||
common/safe_ops.h
|
||||
common/spin_lock.h
|
||||
common/string_util.h
|
||||
|
@ -153,6 +151,7 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS)
|
|||
ir/opt/a64_callback_config_pass.cpp
|
||||
ir/opt/a64_get_set_elimination_pass.cpp
|
||||
ir/opt/a64_merge_interpret_blocks.cpp
|
||||
ir/opt/x64_peepholes.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -344,6 +344,8 @@ IR::Block A64AddressSpace::GenerateIR(IR::LocationDescriptor descriptor) const {
|
|||
}
|
||||
if (conf.HasOptimization(OptimizationFlag::MiscIROpt)) {
|
||||
Optimization::A64MergeInterpretBlocksPass(ir_block, conf.callbacks);
|
||||
Optimization::X64Peepholes(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
}
|
||||
Optimization::VerificationPass(ir_block);
|
||||
|
||||
|
|
|
@ -285,6 +285,8 @@ private:
|
|||
}
|
||||
if (conf.HasOptimization(OptimizationFlag::MiscIROpt)) {
|
||||
Optimization::A64MergeInterpretBlocksPass(ir_block, conf.callbacks);
|
||||
Optimization::X64Peepholes(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
}
|
||||
Optimization::VerificationPass(ir_block);
|
||||
return emitter.Emit(ir_block).entrypoint;
|
||||
|
|
|
@ -364,10 +364,10 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
|||
return_from_run_code[0] = getCurr<const void*>();
|
||||
|
||||
cmp(dword[r15 + jsi.offsetof_halt_reason], 0);
|
||||
jne(return_to_caller);
|
||||
jne(return_to_caller, T_NEAR);
|
||||
if (cb.enable_cycle_counting) {
|
||||
cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0);
|
||||
jng(return_to_caller);
|
||||
jng(return_to_caller, T_NEAR);
|
||||
}
|
||||
cb.LookupBlock->EmitCall(*this);
|
||||
jmp(ABI_RETURN);
|
||||
|
@ -376,10 +376,10 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
|||
return_from_run_code[MXCSR_ALREADY_EXITED] = getCurr<const void*>();
|
||||
|
||||
cmp(dword[r15 + jsi.offsetof_halt_reason], 0);
|
||||
jne(return_to_caller_mxcsr_already_exited);
|
||||
jne(return_to_caller_mxcsr_already_exited, T_NEAR);
|
||||
if (cb.enable_cycle_counting) {
|
||||
cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0);
|
||||
jng(return_to_caller_mxcsr_already_exited);
|
||||
jng(return_to_caller_mxcsr_already_exited, T_NEAR);
|
||||
}
|
||||
SwitchMxcsrOnEntry();
|
||||
cb.LookupBlock->EmitCall(*this);
|
||||
|
@ -403,8 +403,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
|
|||
}
|
||||
|
||||
xor_(eax, eax);
|
||||
lock();
|
||||
xchg(dword[r15 + jsi.offsetof_halt_reason], eax);
|
||||
/* implicit LOCK */ xchg(dword[r15 + jsi.offsetof_halt_reason], eax);
|
||||
|
||||
ABI_PopCalleeSaveRegistersAndAdjustStack(*this, sizeof(StackLayout));
|
||||
ret();
|
||||
|
|
|
@ -35,11 +35,6 @@ EmitContext::EmitContext(RegAlloc& reg_alloc, IR::Block& block)
|
|||
|
||||
EmitContext::~EmitContext() = default;
|
||||
|
||||
void EmitContext::EraseInstruction(IR::Inst* inst) {
|
||||
block.Instructions().erase(inst);
|
||||
inst->ClearArgs();
|
||||
}
|
||||
|
||||
EmitX64::EmitX64(BlockOfCode& code)
|
||||
: code(code) {
|
||||
exception_handler.Register(code);
|
||||
|
|
|
@ -54,10 +54,7 @@ struct EmitContext {
|
|||
EmitContext(RegAlloc& reg_alloc, IR::Block& block);
|
||||
virtual ~EmitContext();
|
||||
|
||||
void EraseInstruction(IR::Inst* inst);
|
||||
|
||||
virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0;
|
||||
|
||||
virtual bool HasOptimization(OptimizationFlag flag) const = 0;
|
||||
|
||||
RegAlloc& reg_alloc;
|
||||
|
|
|
@ -40,7 +40,6 @@ static void EmitCRC32Castagnoli(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
|||
|
||||
static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, const int data_size) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size < 32) {
|
||||
const Xbyak::Reg32 crc = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
|
||||
const Xbyak::Reg64 value = ctx.reg_alloc.UseScratchGpr(args[1]);
|
||||
|
@ -69,10 +68,7 @@ static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, co
|
|||
code.pextrd(crc, xmm_value, 2);
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, crc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 32) {
|
||||
} else if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 32) {
|
||||
const Xbyak::Reg32 crc = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
|
||||
const Xbyak::Reg32 value = ctx.reg_alloc.UseGpr(args[1]).cvt32();
|
||||
const Xbyak::Xmm xmm_value = ctx.reg_alloc.ScratchXmm();
|
||||
|
@ -90,10 +86,7 @@ static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, co
|
|||
code.pextrd(crc, xmm_value, 2);
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, crc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 64) {
|
||||
} else if (code.HasHostFeature(HostFeature::PCLMULQDQ) && data_size == 64) {
|
||||
const Xbyak::Reg32 crc = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
|
||||
const Xbyak::Reg64 value = ctx.reg_alloc.UseGpr(args[1]);
|
||||
const Xbyak::Xmm xmm_value = ctx.reg_alloc.ScratchXmm();
|
||||
|
@ -111,12 +104,11 @@ static void EmitCRC32ISO(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, co
|
|||
code.pextrd(crc, xmm_value, 2);
|
||||
|
||||
ctx.reg_alloc.DefineValue(inst, crc);
|
||||
return;
|
||||
} else {
|
||||
ctx.reg_alloc.HostCall(inst, args[0], args[1], {});
|
||||
code.mov(code.ABI_PARAM3, data_size / CHAR_BIT);
|
||||
code.CallFunction(&CRC32::ComputeCRC32ISO);
|
||||
}
|
||||
|
||||
ctx.reg_alloc.HostCall(inst, args[0], args[1], {});
|
||||
code.mov(code.ABI_PARAM3, data_size / CHAR_BIT);
|
||||
code.CallFunction(&CRC32::ComputeCRC32ISO);
|
||||
}
|
||||
|
||||
void EmitX64::EmitCRC32Castagnoli8(EmitContext& ctx, IR::Inst* inst) {
|
||||
|
|
|
@ -236,23 +236,19 @@ void DenormalsAreZero(BlockOfCode& code, FP::FPCR fpcr, std::initializer_list<Xb
|
|||
FpFixup::Norm_Src,
|
||||
FpFixup::Norm_Src,
|
||||
FpFixup::Norm_Src,
|
||||
FpFixup::Norm_Src);
|
||||
|
||||
FpFixup::Norm_Src
|
||||
);
|
||||
FCODE(vmovap)(tmp, code.BConst<fsize>(xword, denormal_to_zero));
|
||||
|
||||
for (const Xbyak::Xmm& xmm : to_daz) {
|
||||
for (const Xbyak::Xmm& xmm : to_daz)
|
||||
FCODE(vfixupimmp)(xmm, xmm, tmp, u8(0));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (fpcr.RMode() != FP::RoundingMode::TowardsMinusInfinity) {
|
||||
code.movaps(tmp, GetNegativeZeroVector<fsize>(code));
|
||||
} else {
|
||||
code.xorps(tmp, tmp);
|
||||
}
|
||||
for (const Xbyak::Xmm& xmm : to_daz) {
|
||||
FCODE(addp)(xmm, tmp);
|
||||
if (fpcr.RMode() != FP::RoundingMode::TowardsMinusInfinity) {
|
||||
code.movaps(tmp, GetNegativeZeroVector<fsize>(code));
|
||||
} else {
|
||||
code.xorps(tmp, tmp);
|
||||
}
|
||||
for (const Xbyak::Xmm& xmm : to_daz)
|
||||
FCODE(addp)(xmm, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -415,21 +415,48 @@ void RegAlloc::ReleaseStackSpace(const size_t stack_space) noexcept {
|
|||
}
|
||||
|
||||
HostLoc RegAlloc::SelectARegister(const boost::container::static_vector<HostLoc, 28>& desired_locations) const noexcept {
|
||||
boost::container::static_vector<HostLoc, 28> candidates = desired_locations; //Who let someone copy an ENTIRE VECTOR here?
|
||||
|
||||
// Find all locations that have not been allocated..
|
||||
const auto allocated_locs = std::partition(candidates.begin(), candidates.end(), [this](auto loc) noexcept {
|
||||
return !this->LocInfo(loc).IsLocked();
|
||||
});
|
||||
candidates.erase(allocated_locs, candidates.end());
|
||||
ASSERT_MSG(!candidates.empty(), "All candidate registers have already been allocated");
|
||||
|
||||
// Selects the best location out of the available locations.
|
||||
// NOTE: Using last is BAD because new REX prefix for each insn using the last regs
|
||||
// TODO: Actually do LRU or something. Currently we just try to pick something without a value if possible.
|
||||
auto const it = std::find_if(candidates.begin(), candidates.end(), [this](auto const loc) noexcept {
|
||||
return this->LocInfo(loc).IsEmpty();
|
||||
});
|
||||
return it != candidates.end() ? *it : candidates.front();
|
||||
auto min_lru_counter = size_t(-1);
|
||||
auto it_candidate = desired_locations.cend(); //default fallback if everything fails
|
||||
auto it_rex_candidate = desired_locations.cend();
|
||||
auto it_empty_candidate = desired_locations.cend();
|
||||
for (auto it = desired_locations.cbegin(); it != desired_locations.cend(); it++) {
|
||||
auto const& loc_info = LocInfo(*it);
|
||||
// Abstain from using upper registers unless absolutely nescesary
|
||||
if (loc_info.IsLocked()) {
|
||||
// skip, not suitable for allocation
|
||||
} else {
|
||||
// idempotency, only assign once
|
||||
if (it_empty_candidate == desired_locations.cend() && loc_info.IsEmpty())
|
||||
it_empty_candidate = it;
|
||||
if (loc_info.lru_counter < min_lru_counter) {
|
||||
// Otherwise a "quasi"-LRU
|
||||
min_lru_counter = loc_info.lru_counter;
|
||||
if (*it >= HostLoc::R8 && *it <= HostLoc::R15) {
|
||||
it_rex_candidate = it;
|
||||
} else {
|
||||
it_candidate = it;
|
||||
}
|
||||
if (min_lru_counter == 0)
|
||||
break; //early exit
|
||||
}
|
||||
}
|
||||
}
|
||||
// Final resolution goes as follows:
|
||||
// 1 => Try normal candidate (no REX prefix)
|
||||
// 2 => Try an empty candidate
|
||||
// 3 => Try using a REX prefixed one
|
||||
// We avoid using REX-addressable registers because they add +1 REX prefix which
|
||||
// do we really need? The trade-off may not be worth it.
|
||||
auto const it_final = it_candidate != desired_locations.cend()
|
||||
? it_candidate : it_empty_candidate != desired_locations.cend()
|
||||
? it_empty_candidate : it_rex_candidate;
|
||||
ASSERT_MSG(it_final != desired_locations.cend(), "All candidate registers have already been allocated");
|
||||
// Evil magic - increment LRU counter (will wrap at 256)
|
||||
const_cast<RegAlloc*>(this)->LocInfo(*it_final).lru_counter++;
|
||||
return *it_final;
|
||||
}
|
||||
|
||||
void RegAlloc::DefineValueImpl(IR::Inst* def_inst, HostLoc host_loc) noexcept {
|
||||
|
|
|
@ -92,8 +92,8 @@ private:
|
|||
uint8_t max_bit_width = 0; //Valid values: 1,2,4,8,16,32,128
|
||||
bool is_scratch : 1 = false; //1
|
||||
bool is_set_last_use : 1 = false; //1
|
||||
|
||||
alignas(16) char padding;
|
||||
alignas(16) uint8_t lru_counter = 0; //1
|
||||
friend class RegAlloc;
|
||||
};
|
||||
static_assert(sizeof(HostLocInfo) == 64);
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include "dynarmic/common/memory_pool.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace Dynarmic::Common {
|
||||
|
||||
|
||||
} // namespace Dynarmic::Common
|
|
@ -1,61 +0,0 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2016 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace Dynarmic::Common {
|
||||
|
||||
/// @tparam object_size Byte-size of objects to construct
|
||||
/// @tparam slab_size Number of objects to have per slab
|
||||
template<size_t object_size, size_t slab_size>
|
||||
class Pool {
|
||||
public:
|
||||
inline Pool() noexcept {
|
||||
AllocateNewSlab();
|
||||
}
|
||||
inline ~Pool() noexcept {
|
||||
std::free(current_slab);
|
||||
for (char* slab : slabs) {
|
||||
std::free(slab);
|
||||
}
|
||||
}
|
||||
|
||||
Pool(const Pool&) = delete;
|
||||
Pool(Pool&&) = delete;
|
||||
|
||||
Pool& operator=(const Pool&) = delete;
|
||||
Pool& operator=(Pool&&) = delete;
|
||||
|
||||
/// @brief Returns a pointer to an `object_size`-bytes block of memory.
|
||||
[[nodiscard]] void* Alloc() noexcept {
|
||||
if (remaining == 0) {
|
||||
slabs.push_back(current_slab);
|
||||
AllocateNewSlab();
|
||||
}
|
||||
void* ret = static_cast<void*>(current_ptr);
|
||||
current_ptr += object_size;
|
||||
remaining--;
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
/// @brief Allocates a completely new memory slab.
|
||||
/// Used when an entirely new slab is needed
|
||||
/// due the current one running out of usable space.
|
||||
void AllocateNewSlab() noexcept {
|
||||
current_slab = static_cast<char*>(std::malloc(object_size * slab_size));
|
||||
current_ptr = current_slab;
|
||||
remaining = slab_size;
|
||||
}
|
||||
|
||||
std::vector<char*> slabs;
|
||||
char* current_slab = nullptr;
|
||||
char* current_ptr = nullptr;
|
||||
size_t remaining = 0;
|
||||
};
|
||||
|
||||
} // namespace Dynarmic::Common
|
|
@ -58,46 +58,51 @@ static bool SharedDecodeAndOperation(TranslatorVisitor& v, bool wback, IR::MemOp
|
|||
address = v.X(64, Rn);
|
||||
}
|
||||
|
||||
IR::U64 offs = v.ir.Imm64(0);
|
||||
if (replicate) {
|
||||
for (size_t s = 0; s < selem; s++) {
|
||||
// CPU likes when we read first and then we do operations; Sure, OOO, but might as well
|
||||
IR::UAnyU128 p_elements[4] = {}; //max upper bound=4 elements
|
||||
for (size_t s = 0; s < selem; ++s) {
|
||||
p_elements[s] = v.Mem(v.ir.Add(address, v.ir.Imm64(ebytes * s)), ebytes, IR::AccType::VEC);
|
||||
}
|
||||
// schedule ops after
|
||||
for (size_t s = 0; s < selem; ++s) {
|
||||
const Vec tt = static_cast<Vec>((VecNumber(Vt) + s) % 32);
|
||||
const IR::UAnyU128 element = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC);
|
||||
const IR::U128 broadcasted_element = v.ir.VectorBroadcast(esize, element);
|
||||
|
||||
const IR::U128 broadcasted_element = v.ir.VectorBroadcast(esize, p_elements[s]);
|
||||
v.V(datasize, tt, broadcasted_element);
|
||||
|
||||
offs = v.ir.Add(offs, v.ir.Imm64(ebytes));
|
||||
}
|
||||
} else {
|
||||
for (size_t s = 0; s < selem; s++) {
|
||||
const Vec tt = static_cast<Vec>((VecNumber(Vt) + s) % 32);
|
||||
const IR::U128 rval = v.V(128, tt);
|
||||
|
||||
if (memop == IR::MemOp::LOAD) {
|
||||
const IR::UAny elem = v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC);
|
||||
const IR::U128 vec = v.ir.VectorSetElement(esize, rval, index, elem);
|
||||
v.V(128, tt, vec);
|
||||
} else {
|
||||
const IR::UAny elem = v.ir.VectorGetElement(esize, rval, index);
|
||||
v.Mem(v.ir.Add(address, offs), ebytes, IR::AccType::VEC, elem);
|
||||
if (memop == IR::MemOp::LOAD) {
|
||||
IR::UAny p_elements[4] = {}; //max upper bound=4 elements
|
||||
for (size_t s = 0; s < selem; ++s) {
|
||||
p_elements[s] = v.Mem(v.ir.Add(address, v.ir.Imm64(ebytes * s)), ebytes, IR::AccType::VEC);
|
||||
}
|
||||
for (size_t s = 0; s < selem; ++s) {
|
||||
const Vec tt = static_cast<Vec>((VecNumber(Vt) + s) % 32);
|
||||
const IR::U128 rval = v.V(128, tt);
|
||||
const IR::U128 vec = v.ir.VectorSetElement(esize, rval, index, p_elements[s]);
|
||||
v.V(128, tt, vec);
|
||||
}
|
||||
} else {
|
||||
for (size_t s = 0; s < selem; ++s) {
|
||||
const Vec tt = static_cast<Vec>((VecNumber(Vt) + s) % 32);
|
||||
const IR::U128 rval = v.V(128, tt);
|
||||
const IR::UAny elem = v.ir.VectorGetElement(esize, rval, index);
|
||||
v.Mem(v.ir.Add(address, v.ir.Imm64(ebytes * s)), ebytes, IR::AccType::VEC, elem);
|
||||
}
|
||||
offs = v.ir.Add(offs, v.ir.Imm64(ebytes));
|
||||
}
|
||||
}
|
||||
|
||||
IR::U64 offs = v.ir.Imm64(ebytes * selem);
|
||||
if (wback) {
|
||||
if (*Rm != Reg::SP) {
|
||||
offs = v.X(64, *Rm);
|
||||
}
|
||||
|
||||
if (Rn == Reg::SP) {
|
||||
v.SP(64, v.ir.Add(address, offs));
|
||||
} else {
|
||||
v.X(64, Rn, v.ir.Add(address, offs));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,16 +25,18 @@ bool AbsoluteDifferenceLong(TranslatorVisitor& v, bool Q, Imm<2> size, Vec Vm, V
|
|||
const size_t esize = 8 << size.ZeroExtend();
|
||||
const size_t datasize = 64;
|
||||
|
||||
const IR::U128 operand1 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vn, Q));
|
||||
const IR::U128 operand2 = v.ir.VectorZeroExtend(esize, v.Vpart(datasize, Vm, Q));
|
||||
IR::U128 result = sign == SignednessSTD::Signed ? v.ir.VectorSignedAbsoluteDifference(esize, operand1, operand2)
|
||||
: v.ir.VectorUnsignedAbsoluteDifference(esize, operand1, operand2);
|
||||
|
||||
// Loads first, then operations
|
||||
auto const s_operand1 = v.Vpart(datasize, Vn, Q);
|
||||
auto const s_operand2 = v.Vpart(datasize, Vm, Q);
|
||||
const IR::U128 operand1 = v.ir.VectorZeroExtend(esize, s_operand1);
|
||||
const IR::U128 operand2 = v.ir.VectorZeroExtend(esize, s_operand2);
|
||||
IR::U128 result = sign == SignednessSTD::Signed
|
||||
? v.ir.VectorSignedAbsoluteDifference(esize, operand1, operand2)
|
||||
: v.ir.VectorUnsignedAbsoluteDifference(esize, operand1, operand2);
|
||||
if (behavior == AbsoluteDifferenceBehavior::Accumulate) {
|
||||
const IR::U128 data = v.V(2 * datasize, Vd);
|
||||
result = v.ir.VectorAdd(2 * esize, result, data);
|
||||
}
|
||||
|
||||
v.V(2 * datasize, Vd, result);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -134,10 +134,8 @@ bool FPCompareRegister(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Ve
|
|||
if (sz && !Q) {
|
||||
return v.ReservedValue();
|
||||
}
|
||||
|
||||
const size_t esize = sz ? 64 : 32;
|
||||
const size_t datasize = Q ? 128 : 64;
|
||||
|
||||
const IR::U128 operand1 = v.V(datasize, Vn);
|
||||
const IR::U128 operand2 = v.V(datasize, Vm);
|
||||
const IR::U128 result = [&] {
|
||||
|
@ -146,21 +144,22 @@ bool FPCompareRegister(TranslatorVisitor& v, bool Q, bool sz, Vec Vm, Vec Vn, Ve
|
|||
return v.ir.FPVectorEqual(esize, operand1, operand2);
|
||||
case ComparisonTypeSTS::GE:
|
||||
return v.ir.FPVectorGreaterEqual(esize, operand1, operand2);
|
||||
case ComparisonTypeSTS::AbsoluteGE:
|
||||
return v.ir.FPVectorGreaterEqual(esize,
|
||||
v.ir.FPVectorAbs(esize, operand1),
|
||||
v.ir.FPVectorAbs(esize, operand2));
|
||||
case ComparisonTypeSTS::AbsoluteGE: {
|
||||
auto const tmp1 = v.ir.FPVectorAbs(esize, operand1);
|
||||
auto const tmp2 = v.ir.FPVectorAbs(esize, operand2);
|
||||
return v.ir.FPVectorGreaterEqual(esize, tmp1, tmp2);
|
||||
}
|
||||
case ComparisonTypeSTS::GT:
|
||||
return v.ir.FPVectorGreater(esize, operand1, operand2);
|
||||
case ComparisonTypeSTS::AbsoluteGT:
|
||||
return v.ir.FPVectorGreater(esize,
|
||||
v.ir.FPVectorAbs(esize, operand1),
|
||||
v.ir.FPVectorAbs(esize, operand2));
|
||||
case ComparisonTypeSTS::AbsoluteGT: {
|
||||
auto const tmp1 = v.ir.FPVectorAbs(esize, operand1);
|
||||
auto const tmp2 = v.ir.FPVectorAbs(esize, operand2);
|
||||
return v.ir.FPVectorGreater(esize, tmp1, tmp2);
|
||||
}
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
}();
|
||||
|
||||
v.V(datasize, Vd, result);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <fmt/format.h>
|
||||
#include <mcl/assert.hpp>
|
||||
|
||||
#include "dynarmic/common/memory_pool.h"
|
||||
#include "dynarmic/frontend/A32/a32_types.h"
|
||||
#include "dynarmic/frontend/A64/a64_types.h"
|
||||
#include "dynarmic/ir/cond.h"
|
||||
|
@ -24,8 +23,7 @@ namespace Dynarmic::IR {
|
|||
Block::Block(const LocationDescriptor& location)
|
||||
: location{location},
|
||||
end_location{location},
|
||||
cond{Cond::AL},
|
||||
instruction_alloc_pool{std::make_unique<std::remove_reference_t<decltype(*instruction_alloc_pool)>>()}
|
||||
cond{Cond::AL}
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -37,7 +35,7 @@ Block::Block(const LocationDescriptor& location)
|
|||
/// @param args A sequence of Value instances used as arguments for the instruction.
|
||||
/// @returns Iterator to the newly created instruction.
|
||||
Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode opcode, std::initializer_list<Value> args) noexcept {
|
||||
IR::Inst* inst = new (instruction_alloc_pool->Alloc()) IR::Inst(opcode);
|
||||
IR::Inst* inst = new IR::Inst(opcode);
|
||||
DEBUG_ASSERT(args.size() == inst->NumArgs());
|
||||
std::for_each(args.begin(), args.end(), [&inst, index = size_t(0)](const auto& arg) mutable {
|
||||
inst->SetArg(index, arg);
|
||||
|
@ -83,9 +81,7 @@ static std::string TerminalToString(const Terminal& terminal_variant) noexcept {
|
|||
}
|
||||
|
||||
std::string DumpBlock(const IR::Block& block) noexcept {
|
||||
std::string ret;
|
||||
|
||||
ret += fmt::format("Block: location={}\n", block.Location());
|
||||
std::string ret = fmt::format("Block: location={}\n", block.Location());
|
||||
ret += fmt::format("cycles={}", block.CycleCount());
|
||||
ret += fmt::format(", entry_cond={}", A64::CondToString(block.GetCondition()));
|
||||
if (block.GetCondition() != Cond::AL) {
|
||||
|
@ -113,6 +109,8 @@ std::string DumpBlock(const IR::Block& block) noexcept {
|
|||
return fmt::format("#{:#x}", arg.GetU32());
|
||||
case Type::U64:
|
||||
return fmt::format("#{:#x}", arg.GetU64());
|
||||
case Type::U128:
|
||||
return fmt::format("#<u128>");
|
||||
case Type::A32Reg:
|
||||
return A32::RegToString(arg.GetA32RegRef());
|
||||
case Type::A32ExtReg:
|
||||
|
@ -155,14 +153,9 @@ std::string DumpBlock(const IR::Block& block) noexcept {
|
|||
ret += fmt::format("<type error: {} != {}>", GetNameOf(actual_type), GetNameOf(expected_type));
|
||||
}
|
||||
}
|
||||
|
||||
ret += fmt::format(" (uses: {})", inst.UseCount());
|
||||
|
||||
ret += '\n';
|
||||
ret += fmt::format(" (uses: {})\n", inst.UseCount());
|
||||
}
|
||||
|
||||
ret += "terminal = " + TerminalToString(block.GetTerminal()) + '\n';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/terminal.h"
|
||||
#include "dynarmic/ir/value.h"
|
||||
#include "dynarmic/ir/dense_list.h"
|
||||
#include "dynarmic/common/memory_pool.h"
|
||||
|
||||
namespace Dynarmic::IR {
|
||||
|
||||
|
@ -76,7 +74,7 @@ public:
|
|||
/// @param op Opcode representing the instruction to add.
|
||||
/// @param args A sequence of Value instances used as arguments for the instruction.
|
||||
inline void AppendNewInst(const Opcode opcode, const std::initializer_list<IR::Value> args) noexcept {
|
||||
PrependNewInst(end(), opcode, args);
|
||||
PrependNewInst(instructions.end(), opcode, args);
|
||||
}
|
||||
iterator PrependNewInst(iterator insertion_point, Opcode op, std::initializer_list<Value> args) noexcept;
|
||||
|
||||
|
@ -171,8 +169,6 @@ private:
|
|||
LocationDescriptor end_location;
|
||||
/// Conditional to pass in order to execute this block
|
||||
Cond cond;
|
||||
/// Memory pool for instruction list
|
||||
std::unique_ptr<Common::Pool<sizeof(Inst), 2097152UL / sizeof(Inst)>> instruction_alloc_pool;
|
||||
/// Terminal instruction of this block.
|
||||
Terminal terminal = Term::Invalid{};
|
||||
/// Number of cycles this block takes to execute if the conditional fails.
|
||||
|
|
58
externals/dynarmic/src/dynarmic/ir/dense_list.h
vendored
58
externals/dynarmic/src/dynarmic/ir/dense_list.h
vendored
|
@ -1,58 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
|
||||
namespace Dynarmic {
|
||||
template<typename T> struct dense_list {
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using size_type = std::size_t;
|
||||
using value_type = T;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using iterator = std::deque<value_type>::iterator;
|
||||
using const_iterator = std::deque<value_type>::const_iterator;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
inline bool empty() const noexcept { return list.empty(); }
|
||||
inline size_type size() const noexcept { return list.size(); }
|
||||
|
||||
inline value_type& front() noexcept { return list.front(); }
|
||||
inline const value_type& front() const noexcept { return list.front(); }
|
||||
|
||||
inline value_type& back() noexcept { return list.back(); }
|
||||
inline const value_type& back() const noexcept { return list.back(); }
|
||||
|
||||
inline iterator begin() noexcept { return list.begin(); }
|
||||
inline const_iterator begin() const noexcept { return list.begin(); }
|
||||
inline iterator end() noexcept { return list.end(); }
|
||||
inline const_iterator end() const noexcept { return list.end(); }
|
||||
|
||||
inline reverse_iterator rbegin() noexcept { return list.rbegin(); }
|
||||
inline const_reverse_iterator rbegin() const noexcept { return list.rbegin(); }
|
||||
inline reverse_iterator rend() noexcept { return list.rend(); }
|
||||
inline const_reverse_iterator rend() const noexcept { return list.rend(); }
|
||||
|
||||
inline const_iterator cbegin() const noexcept { return list.cbegin(); }
|
||||
inline const_iterator cend() const noexcept { return list.cend(); }
|
||||
|
||||
inline const_reverse_iterator crbegin() const noexcept { return list.crbegin(); }
|
||||
inline const_reverse_iterator crend() const noexcept { return list.crend(); }
|
||||
|
||||
inline iterator insert_before(iterator it, value_type& value) noexcept {
|
||||
if (it == list.begin()) {
|
||||
list.push_front(value);
|
||||
return list.begin();
|
||||
}
|
||||
auto const index = std::distance(list.begin(), it - 1);
|
||||
list.insert(it - 1, value);
|
||||
return list.begin() + index;
|
||||
}
|
||||
|
||||
std::deque<value_type> list;
|
||||
};
|
||||
}
|
|
@ -2947,19 +2947,10 @@ public:
|
|||
block.SetTerminal(terminal);
|
||||
}
|
||||
|
||||
void SetInsertionPointBefore(IR::Inst* new_insertion_point) {
|
||||
insertion_point = IR::Block::iterator{*new_insertion_point};
|
||||
}
|
||||
|
||||
void SetInsertionPointBefore(IR::Block::iterator new_insertion_point) {
|
||||
insertion_point = new_insertion_point;
|
||||
}
|
||||
|
||||
void SetInsertionPointAfter(IR::Inst* new_insertion_point) {
|
||||
insertion_point = IR::Block::iterator{*new_insertion_point};
|
||||
++insertion_point;
|
||||
}
|
||||
|
||||
void SetInsertionPointAfter(IR::Block::iterator new_insertion_point) {
|
||||
insertion_point = new_insertion_point;
|
||||
++insertion_point;
|
||||
|
|
|
@ -22,8 +22,7 @@ namespace Dynarmic::Optimization {
|
|||
namespace {
|
||||
|
||||
void FlagsPass(IR::Block& block) {
|
||||
using Iterator = std::reverse_iterator<IR::Block::iterator>;
|
||||
|
||||
using Iterator = IR::Block::reverse_iterator;
|
||||
struct FlagInfo {
|
||||
bool set_not_required = false;
|
||||
bool has_value_request = false;
|
||||
|
@ -185,10 +184,10 @@ void RegisterPass(IR::Block& block) {
|
|||
using Iterator = IR::Block::iterator;
|
||||
|
||||
struct RegInfo {
|
||||
IR::Value register_value;
|
||||
std::optional<Iterator> last_set_instruction;
|
||||
IR::Value register_value;
|
||||
};
|
||||
std::array<RegInfo, 15> reg_info;
|
||||
alignas(64) std::array<RegInfo, 15> reg_info;
|
||||
|
||||
const auto do_get = [](RegInfo& info, Iterator get_inst) {
|
||||
if (info.register_value.IsEmpty()) {
|
||||
|
@ -203,12 +202,12 @@ void RegisterPass(IR::Block& block) {
|
|||
(*info.last_set_instruction)->Invalidate();
|
||||
}
|
||||
info = {
|
||||
.register_value = value,
|
||||
.last_set_instruction = set_inst,
|
||||
.register_value = value,
|
||||
};
|
||||
};
|
||||
|
||||
enum class ExtValueType {
|
||||
enum class ExtValueType : std::uint8_t {
|
||||
Empty,
|
||||
Single,
|
||||
Double,
|
||||
|
@ -216,19 +215,20 @@ void RegisterPass(IR::Block& block) {
|
|||
VectorQuad,
|
||||
};
|
||||
struct ExtRegInfo {
|
||||
ExtValueType value_type = {};
|
||||
IR::Value register_value;
|
||||
std::optional<Iterator> last_set_instruction;
|
||||
ExtValueType value_type = {};
|
||||
};
|
||||
std::array<ExtRegInfo, 64> ext_reg_info;
|
||||
// Max returned by RegNumber = 31 (but multiplied by 4 in some cases)
|
||||
alignas(64) std::array<ExtRegInfo, 128> ext_reg_info;
|
||||
|
||||
const auto do_ext_get = [](ExtValueType type, std::initializer_list<std::reference_wrapper<ExtRegInfo>> infos, Iterator get_inst) {
|
||||
if (!std::all_of(infos.begin(), infos.end(), [type](const auto& info) { return info.get().value_type == type; })) {
|
||||
for (auto& info : infos) {
|
||||
info.get() = {
|
||||
.value_type = type,
|
||||
.register_value = IR::Value(&*get_inst),
|
||||
.last_set_instruction = std::nullopt,
|
||||
.value_type = type,
|
||||
};
|
||||
}
|
||||
return;
|
||||
|
@ -244,9 +244,9 @@ void RegisterPass(IR::Block& block) {
|
|||
}
|
||||
for (auto& info : infos) {
|
||||
info.get() = {
|
||||
.value_type = type,
|
||||
.register_value = value,
|
||||
.last_set_instruction = set_inst,
|
||||
.value_type = type,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,7 +17,8 @@ void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf) {
|
|||
return;
|
||||
}
|
||||
|
||||
for (auto& inst : block) {
|
||||
for (auto iter = block.begin(); iter != block.end(); iter++) {
|
||||
auto& inst = *iter;
|
||||
if (inst.GetOpcode() != IR::Opcode::A64DataCacheOperationRaised) {
|
||||
continue;
|
||||
}
|
||||
|
@ -26,7 +27,7 @@ void A64CallbackConfigPass(IR::Block& block, const A64::UserConfig& conf) {
|
|||
if (op == A64::DataCacheOperation::ZeroByVA) {
|
||||
A64::IREmitter ir{block};
|
||||
ir.current_location = A64::LocationDescriptor{IR::LocationDescriptor{inst.GetArg(0).GetU64()}};
|
||||
ir.SetInsertionPointBefore(&inst);
|
||||
ir.SetInsertionPointBefore(iter);
|
||||
|
||||
size_t bytes = 4 << static_cast<size_t>(conf.dczid_el0 & 0b1111);
|
||||
IR::U64 addr{inst.GetArg(2)};
|
||||
|
|
|
@ -22,9 +22,9 @@ using Op = Dynarmic::IR::Opcode;
|
|||
|
||||
namespace {
|
||||
|
||||
// Tiny helper to avoid the need to store based off the opcode
|
||||
// bit size all over the place within folding functions.
|
||||
void ReplaceUsesWith(IR::Inst& inst, bool is_32_bit, u64 value) {
|
||||
/// Tiny helper to avoid the need to store based off the opcode
|
||||
/// bit size all over the place within folding functions.
|
||||
static void ReplaceUsesWith(IR::Inst& inst, bool is_32_bit, u64 value) {
|
||||
if (is_32_bit) {
|
||||
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(value)});
|
||||
} else {
|
||||
|
@ -32,12 +32,12 @@ void ReplaceUsesWith(IR::Inst& inst, bool is_32_bit, u64 value) {
|
|||
}
|
||||
}
|
||||
|
||||
IR::Value Value(bool is_32_bit, u64 value) {
|
||||
static IR::Value Value(bool is_32_bit, u64 value) {
|
||||
return is_32_bit ? IR::Value{static_cast<u32>(value)} : IR::Value{value};
|
||||
}
|
||||
|
||||
template<typename ImmFn>
|
||||
bool FoldCommutative(IR::Inst& inst, bool is_32_bit, ImmFn imm_fn) {
|
||||
static bool FoldCommutative(IR::Inst& inst, bool is_32_bit, ImmFn imm_fn) {
|
||||
const auto lhs = inst.GetArg(0);
|
||||
const auto rhs = inst.GetArg(1);
|
||||
|
||||
|
@ -75,7 +75,7 @@ bool FoldCommutative(IR::Inst& inst, bool is_32_bit, ImmFn imm_fn) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void FoldAdd(IR::Inst& inst, bool is_32_bit) {
|
||||
static void FoldAdd(IR::Inst& inst, bool is_32_bit) {
|
||||
const auto lhs = inst.GetArg(0);
|
||||
const auto rhs = inst.GetArg(1);
|
||||
const auto carry = inst.GetArg(2);
|
||||
|
@ -125,7 +125,7 @@ void FoldAdd(IR::Inst& inst, bool is_32_bit) {
|
|||
/// 4. x & y -> y (where x has all bits set to 1)
|
||||
/// 5. x & y -> x (where y has all bits set to 1)
|
||||
///
|
||||
void FoldAND(IR::Inst& inst, bool is_32_bit) {
|
||||
static void FoldAND(IR::Inst& inst, bool is_32_bit) {
|
||||
if (FoldCommutative(inst, is_32_bit, [](u64 a, u64 b) { return a & b; })) {
|
||||
const auto rhs = inst.GetArg(1);
|
||||
if (rhs.IsZero()) {
|
||||
|
@ -140,7 +140,7 @@ void FoldAND(IR::Inst& inst, bool is_32_bit) {
|
|||
///
|
||||
/// 1. imm -> swap(imm)
|
||||
///
|
||||
void FoldByteReverse(IR::Inst& inst, Op op) {
|
||||
static void FoldByteReverse(IR::Inst& inst, Op op) {
|
||||
const auto operand = inst.GetArg(0);
|
||||
|
||||
if (!operand.IsImmediate()) {
|
||||
|
@ -165,7 +165,7 @@ void FoldByteReverse(IR::Inst& inst, Op op) {
|
|||
/// 2. imm_x / imm_y -> result
|
||||
/// 3. x / 1 -> x
|
||||
///
|
||||
void FoldDivide(IR::Inst& inst, bool is_32_bit, bool is_signed) {
|
||||
static void FoldDivide(IR::Inst& inst, bool is_32_bit, bool is_signed) {
|
||||
const auto rhs = inst.GetArg(1);
|
||||
|
||||
if (rhs.IsZero()) {
|
||||
|
@ -193,7 +193,7 @@ void FoldDivide(IR::Inst& inst, bool is_32_bit, bool is_signed) {
|
|||
// 2. x ^ 0 -> x
|
||||
// 3. 0 ^ y -> y
|
||||
//
|
||||
void FoldEOR(IR::Inst& inst, bool is_32_bit) {
|
||||
static void FoldEOR(IR::Inst& inst, bool is_32_bit) {
|
||||
if (FoldCommutative(inst, is_32_bit, [](u64 a, u64 b) { return a ^ b; })) {
|
||||
const auto rhs = inst.GetArg(1);
|
||||
if (rhs.IsZero()) {
|
||||
|
@ -202,7 +202,7 @@ void FoldEOR(IR::Inst& inst, bool is_32_bit) {
|
|||
}
|
||||
}
|
||||
|
||||
void FoldLeastSignificantByte(IR::Inst& inst) {
|
||||
static void FoldLeastSignificantByte(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ void FoldLeastSignificantByte(IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(IR::Value{static_cast<u8>(operand.GetImmediateAsU64())});
|
||||
}
|
||||
|
||||
void FoldLeastSignificantHalf(IR::Inst& inst) {
|
||||
static void FoldLeastSignificantHalf(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ void FoldLeastSignificantHalf(IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(IR::Value{static_cast<u16>(operand.GetImmediateAsU64())});
|
||||
}
|
||||
|
||||
void FoldLeastSignificantWord(IR::Inst& inst) {
|
||||
static void FoldLeastSignificantWord(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
@ -229,7 +229,7 @@ void FoldLeastSignificantWord(IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(operand.GetImmediateAsU64())});
|
||||
}
|
||||
|
||||
void FoldMostSignificantBit(IR::Inst& inst) {
|
||||
static void FoldMostSignificantBit(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ void FoldMostSignificantBit(IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(IR::Value{(operand.GetImmediateAsU64() >> 31) != 0});
|
||||
}
|
||||
|
||||
void FoldMostSignificantWord(IR::Inst& inst) {
|
||||
static void FoldMostSignificantWord(IR::Inst& inst) {
|
||||
IR::Inst* carry_inst = inst.GetAssociatedPseudoOperation(Op::GetCarryFromOp);
|
||||
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
|
@ -260,7 +260,7 @@ void FoldMostSignificantWord(IR::Inst& inst) {
|
|||
// 4. x * 1 -> x
|
||||
// 5. 1 * y -> y
|
||||
//
|
||||
void FoldMultiply(IR::Inst& inst, bool is_32_bit) {
|
||||
static void FoldMultiply(IR::Inst& inst, bool is_32_bit) {
|
||||
if (FoldCommutative(inst, is_32_bit, [](u64 a, u64 b) { return a * b; })) {
|
||||
const auto rhs = inst.GetArg(1);
|
||||
if (rhs.IsZero()) {
|
||||
|
@ -272,7 +272,7 @@ void FoldMultiply(IR::Inst& inst, bool is_32_bit) {
|
|||
}
|
||||
|
||||
// Folds NOT operations if the contained value is an immediate.
|
||||
void FoldNOT(IR::Inst& inst, bool is_32_bit) {
|
||||
static void FoldNOT(IR::Inst& inst, bool is_32_bit) {
|
||||
const auto operand = inst.GetArg(0);
|
||||
|
||||
if (!operand.IsImmediate()) {
|
||||
|
@ -289,7 +289,7 @@ void FoldNOT(IR::Inst& inst, bool is_32_bit) {
|
|||
// 2. x | 0 -> x
|
||||
// 3. 0 | y -> y
|
||||
//
|
||||
void FoldOR(IR::Inst& inst, bool is_32_bit) {
|
||||
static void FoldOR(IR::Inst& inst, bool is_32_bit) {
|
||||
if (FoldCommutative(inst, is_32_bit, [](u64 a, u64 b) { return a | b; })) {
|
||||
const auto rhs = inst.GetArg(1);
|
||||
if (rhs.IsZero()) {
|
||||
|
@ -298,7 +298,7 @@ void FoldOR(IR::Inst& inst, bool is_32_bit) {
|
|||
}
|
||||
}
|
||||
|
||||
bool FoldShifts(IR::Inst& inst) {
|
||||
static bool FoldShifts(IR::Inst& inst) {
|
||||
IR::Inst* carry_inst = inst.GetAssociatedPseudoOperation(Op::GetCarryFromOp);
|
||||
|
||||
// The 32-bit variants can contain 3 arguments, while the
|
||||
|
@ -328,7 +328,7 @@ bool FoldShifts(IR::Inst& inst) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void FoldSignExtendXToWord(IR::Inst& inst) {
|
||||
static void FoldSignExtendXToWord(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ void FoldSignExtendXToWord(IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(value)});
|
||||
}
|
||||
|
||||
void FoldSignExtendXToLong(IR::Inst& inst) {
|
||||
static void FoldSignExtendXToLong(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
@ -346,7 +346,7 @@ void FoldSignExtendXToLong(IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(IR::Value{static_cast<u64>(value)});
|
||||
}
|
||||
|
||||
void FoldSub(IR::Inst& inst, bool is_32_bit) {
|
||||
static void FoldSub(IR::Inst& inst, bool is_32_bit) {
|
||||
if (!inst.AreAllArgsImmediates() || inst.HasAssociatedPseudoOperation()) {
|
||||
return;
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ void FoldSub(IR::Inst& inst, bool is_32_bit) {
|
|||
ReplaceUsesWith(inst, is_32_bit, result);
|
||||
}
|
||||
|
||||
void FoldZeroExtendXToWord(IR::Inst& inst) {
|
||||
static void FoldZeroExtendXToWord(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ void FoldZeroExtendXToWord(IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(IR::Value{static_cast<u32>(value)});
|
||||
}
|
||||
|
||||
void FoldZeroExtendXToLong(IR::Inst& inst) {
|
||||
static void FoldZeroExtendXToLong(IR::Inst& inst) {
|
||||
if (!inst.AreAllArgsImmediates()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -13,11 +13,8 @@ namespace Dynarmic::Optimization {
|
|||
|
||||
void IdentityRemovalPass(IR::Block& block) {
|
||||
std::vector<IR::Inst*> to_invalidate;
|
||||
|
||||
auto iter = block.begin();
|
||||
while (iter != block.end()) {
|
||||
for (auto iter = block.begin(); iter != block.end(); ) {
|
||||
IR::Inst& inst = *iter;
|
||||
|
||||
const size_t num_args = inst.NumArgs();
|
||||
for (size_t i = 0; i < num_args; i++) {
|
||||
while (true) {
|
||||
|
@ -27,18 +24,15 @@ void IdentityRemovalPass(IR::Block& block) {
|
|||
inst.SetArg(i, arg.GetInst()->GetArg(0));
|
||||
}
|
||||
}
|
||||
|
||||
if (inst.GetOpcode() == IR::Opcode::Identity || inst.GetOpcode() == IR::Opcode::Void) {
|
||||
iter = block.Instructions().erase(inst);
|
||||
iter = block.Instructions().erase(iter);
|
||||
to_invalidate.push_back(&inst);
|
||||
} else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
for (IR::Inst* inst : to_invalidate) {
|
||||
for (auto* inst : to_invalidate)
|
||||
inst->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Optimization
|
||||
|
|
|
@ -43,5 +43,6 @@ void DeadCodeElimination(IR::Block& block);
|
|||
void IdentityRemovalPass(IR::Block& block);
|
||||
void VerificationPass(const IR::Block& block);
|
||||
void NamingPass(IR::Block& block);
|
||||
void X64Peepholes(IR::Block& block);
|
||||
|
||||
} // namespace Dynarmic::Optimization
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace Dynarmic::Optimization {
|
|||
|
||||
namespace {
|
||||
|
||||
void PolyfillSHA256MessageSchedule0(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
static void PolyfillSHA256MessageSchedule0(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
const IR::U128 x = (IR::U128)inst.GetArg(0);
|
||||
const IR::U128 y = (IR::U128)inst.GetArg(1);
|
||||
|
||||
|
@ -37,13 +37,14 @@ void PolyfillSHA256MessageSchedule0(IR::IREmitter& ir, IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(result);
|
||||
}
|
||||
|
||||
void PolyfillSHA256MessageSchedule1(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
static void PolyfillSHA256MessageSchedule1(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
const IR::U128 x = (IR::U128)inst.GetArg(0);
|
||||
const IR::U128 y = (IR::U128)inst.GetArg(1);
|
||||
const IR::U128 z = (IR::U128)inst.GetArg(2);
|
||||
|
||||
const IR::U128 T0 = ir.VectorExtract(y, z, 32);
|
||||
|
||||
// TODO: this can use better pipelining m8
|
||||
const IR::U128 lower_half = [&] {
|
||||
const IR::U128 T = ir.VectorRotateWholeVectorRight(z, 64);
|
||||
const IR::U128 tmp1 = ir.VectorRotateRight(32, T, 17);
|
||||
|
@ -73,15 +74,15 @@ void PolyfillSHA256MessageSchedule1(IR::IREmitter& ir, IR::Inst& inst) {
|
|||
inst.ReplaceUsesWith(result);
|
||||
}
|
||||
|
||||
IR::U32 SHAchoose(IR::IREmitter& ir, IR::U32 x, IR::U32 y, IR::U32 z) {
|
||||
static IR::U32 SHAchoose(IR::IREmitter& ir, IR::U32 x, IR::U32 y, IR::U32 z) {
|
||||
return ir.Eor(ir.And(ir.Eor(y, z), x), z);
|
||||
}
|
||||
|
||||
IR::U32 SHAmajority(IR::IREmitter& ir, IR::U32 x, IR::U32 y, IR::U32 z) {
|
||||
static IR::U32 SHAmajority(IR::IREmitter& ir, IR::U32 x, IR::U32 y, IR::U32 z) {
|
||||
return ir.Or(ir.And(x, y), ir.And(ir.Or(x, y), z));
|
||||
}
|
||||
|
||||
IR::U32 SHAhashSIGMA0(IR::IREmitter& ir, IR::U32 x) {
|
||||
static IR::U32 SHAhashSIGMA0(IR::IREmitter& ir, IR::U32 x) {
|
||||
const IR::U32 tmp1 = ir.RotateRight(x, ir.Imm8(2));
|
||||
const IR::U32 tmp2 = ir.RotateRight(x, ir.Imm8(13));
|
||||
const IR::U32 tmp3 = ir.RotateRight(x, ir.Imm8(22));
|
||||
|
@ -89,7 +90,7 @@ IR::U32 SHAhashSIGMA0(IR::IREmitter& ir, IR::U32 x) {
|
|||
return ir.Eor(tmp1, ir.Eor(tmp2, tmp3));
|
||||
}
|
||||
|
||||
IR::U32 SHAhashSIGMA1(IR::IREmitter& ir, IR::U32 x) {
|
||||
static IR::U32 SHAhashSIGMA1(IR::IREmitter& ir, IR::U32 x) {
|
||||
const IR::U32 tmp1 = ir.RotateRight(x, ir.Imm8(6));
|
||||
const IR::U32 tmp2 = ir.RotateRight(x, ir.Imm8(11));
|
||||
const IR::U32 tmp3 = ir.RotateRight(x, ir.Imm8(25));
|
||||
|
@ -97,7 +98,7 @@ IR::U32 SHAhashSIGMA1(IR::IREmitter& ir, IR::U32 x) {
|
|||
return ir.Eor(tmp1, ir.Eor(tmp2, tmp3));
|
||||
}
|
||||
|
||||
void PolyfillSHA256Hash(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
static void PolyfillSHA256Hash(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
IR::U128 x = (IR::U128)inst.GetArg(0);
|
||||
IR::U128 y = (IR::U128)inst.GetArg(1);
|
||||
const IR::U128 w = (IR::U128)inst.GetArg(2);
|
||||
|
@ -139,7 +140,7 @@ void PolyfillSHA256Hash(IR::IREmitter& ir, IR::Inst& inst) {
|
|||
}
|
||||
|
||||
template<size_t esize, bool is_signed>
|
||||
void PolyfillVectorMultiplyWiden(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
static void PolyfillVectorMultiplyWiden(IR::IREmitter& ir, IR::Inst& inst) {
|
||||
IR::U128 n = (IR::U128)inst.GetArg(0);
|
||||
IR::U128 m = (IR::U128)inst.GetArg(1);
|
||||
|
||||
|
@ -159,54 +160,52 @@ void PolyfillPass(IR::Block& block, const PolyfillOptions& polyfill) {
|
|||
}
|
||||
|
||||
IR::IREmitter ir{block};
|
||||
|
||||
for (auto& inst : block) {
|
||||
ir.SetInsertionPointBefore(&inst);
|
||||
|
||||
switch (inst.GetOpcode()) {
|
||||
for (auto iter = block.begin(); iter != block.end(); iter++) {
|
||||
ir.SetInsertionPointBefore(iter);
|
||||
switch (iter->GetOpcode()) {
|
||||
case IR::Opcode::SHA256MessageSchedule0:
|
||||
if (polyfill.sha256) {
|
||||
PolyfillSHA256MessageSchedule0(ir, inst);
|
||||
PolyfillSHA256MessageSchedule0(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::SHA256MessageSchedule1:
|
||||
if (polyfill.sha256) {
|
||||
PolyfillSHA256MessageSchedule1(ir, inst);
|
||||
PolyfillSHA256MessageSchedule1(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::SHA256Hash:
|
||||
if (polyfill.sha256) {
|
||||
PolyfillSHA256Hash(ir, inst);
|
||||
PolyfillSHA256Hash(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::VectorMultiplySignedWiden8:
|
||||
if (polyfill.vector_multiply_widen) {
|
||||
PolyfillVectorMultiplyWiden<8, true>(ir, inst);
|
||||
PolyfillVectorMultiplyWiden<8, true>(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::VectorMultiplySignedWiden16:
|
||||
if (polyfill.vector_multiply_widen) {
|
||||
PolyfillVectorMultiplyWiden<16, true>(ir, inst);
|
||||
PolyfillVectorMultiplyWiden<16, true>(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::VectorMultiplySignedWiden32:
|
||||
if (polyfill.vector_multiply_widen) {
|
||||
PolyfillVectorMultiplyWiden<32, true>(ir, inst);
|
||||
PolyfillVectorMultiplyWiden<32, true>(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::VectorMultiplyUnsignedWiden8:
|
||||
if (polyfill.vector_multiply_widen) {
|
||||
PolyfillVectorMultiplyWiden<8, false>(ir, inst);
|
||||
PolyfillVectorMultiplyWiden<8, false>(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::VectorMultiplyUnsignedWiden16:
|
||||
if (polyfill.vector_multiply_widen) {
|
||||
PolyfillVectorMultiplyWiden<16, false>(ir, inst);
|
||||
PolyfillVectorMultiplyWiden<16, false>(ir, *iter);
|
||||
}
|
||||
break;
|
||||
case IR::Opcode::VectorMultiplyUnsignedWiden32:
|
||||
if (polyfill.vector_multiply_widen) {
|
||||
PolyfillVectorMultiplyWiden<32, false>(ir, inst);
|
||||
PolyfillVectorMultiplyWiden<32, false>(ir, *iter);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
24
externals/dynarmic/src/dynarmic/ir/opt/x64_peepholes.cpp
vendored
Normal file
24
externals/dynarmic/src/dynarmic/ir/opt/x64_peepholes.cpp
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* This file is part of the dynarmic project.
|
||||
* Copyright (c) 2018 MerryMage
|
||||
* SPDX-License-Identifier: 0BSD
|
||||
*/
|
||||
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <mcl/stdint.hpp>
|
||||
|
||||
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||
#include "dynarmic/interface/A64/config.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/opt/passes.h"
|
||||
|
||||
namespace Dynarmic::Optimization {
|
||||
|
||||
// blind peepholes
|
||||
void X64Peepholes(IR::Block& block) {
|
||||
for (auto iter = block.begin(); iter != block.end(); iter++) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Optimization
|
|
@ -539,7 +539,8 @@ TEST_CASE("arm: Memory access (fastmem)", "[arm][A32]") {
|
|||
char* backing_memory = reinterpret_cast<char*>(std::align(page_size, memory_size, buffer_ptr, buffer_size_nconst));
|
||||
|
||||
A32FastmemTestEnv env{backing_memory};
|
||||
Dynarmic::A32::UserConfig config{&env};
|
||||
Dynarmic::A32::UserConfig config{};
|
||||
config.callbacks = &env;
|
||||
config.fastmem_pointer = reinterpret_cast<uintptr_t>(backing_memory);
|
||||
config.recompile_on_fastmem_failure = false;
|
||||
config.processor_id = 0;
|
||||
|
|
250
externals/dynarmic/tests/A64/a64.cpp
vendored
250
externals/dynarmic/tests/A64/a64.cpp
vendored
File diff suppressed because one or more lines are too long
4
externals/dynarmic/tests/A64/fp_min_max.cpp
vendored
4
externals/dynarmic/tests/A64/fp_min_max.cpp
vendored
|
@ -64,7 +64,9 @@ u32 force_default_nan(u32 value) {
|
|||
template<typename Fn>
|
||||
void run_test(u32 instruction, Fn fn) {
|
||||
A64TestEnv env;
|
||||
A64::Jit jit{A64::UserConfig{&env}};
|
||||
A64::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &env;
|
||||
A64::Jit jit{jit_user_config};
|
||||
|
||||
env.code_mem.emplace_back(instruction); // FMAX S0, S1, S2
|
||||
env.code_mem.emplace_back(0x14000000); // B .
|
||||
|
|
|
@ -154,7 +154,8 @@ static u32 GenFloatInst(u64 pc, bool is_last_inst) {
|
|||
}
|
||||
|
||||
static Dynarmic::A64::UserConfig GetUserConfig(A64TestEnv& jit_env) {
|
||||
Dynarmic::A64::UserConfig jit_user_config{&jit_env};
|
||||
Dynarmic::A64::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &jit_env;
|
||||
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
||||
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
||||
jit_user_config.dczid_el0 = 7;
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_access_via_page_table is set", "[a64]") {
|
||||
A64TestEnv env;
|
||||
Dynarmic::A64::UserConfig conf{&env};
|
||||
Dynarmic::A64::UserConfig conf{};
|
||||
conf.callbacks = &env;
|
||||
conf.page_table = nullptr;
|
||||
conf.detect_misaligned_access_via_page_table = 128;
|
||||
conf.only_detect_misalignment_via_page_table_on_page_boundary = true;
|
||||
|
|
|
@ -12,8 +12,8 @@ using namespace Dynarmic;
|
|||
|
||||
TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have any patching requirements", "[a64]") {
|
||||
A64TestEnv env;
|
||||
|
||||
A64::UserConfig conf{&env};
|
||||
A64::UserConfig conf{};
|
||||
conf.callbacks = &env;
|
||||
A64::Jit jit{conf};
|
||||
|
||||
REQUIRE(conf.HasOptimization(OptimizationFlag::FastDispatch));
|
||||
|
@ -64,8 +64,8 @@ TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have
|
|||
|
||||
TEST_CASE("ensure fast dispatch entry is cleared even when a block does not have any patching requirements 2", "[a64]") {
|
||||
A64TestEnv env;
|
||||
|
||||
A64::UserConfig conf{&env};
|
||||
A64::UserConfig conf{};
|
||||
conf.callbacks = &env;
|
||||
A64::Jit jit{conf};
|
||||
|
||||
REQUIRE(conf.HasOptimization(OptimizationFlag::FastDispatch));
|
||||
|
|
232
externals/dynarmic/tests/test_generator.cpp
vendored
232
externals/dynarmic/tests/test_generator.cpp
vendored
|
@ -23,6 +23,7 @@
|
|||
#include "./rand_int.h"
|
||||
#include "dynarmic/common/fp/fpcr.h"
|
||||
#include "dynarmic/common/fp/fpsr.h"
|
||||
#include "dynarmic/common/llvm_disassemble.h"
|
||||
#include "dynarmic/frontend/A32/ITState.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A32/a32_types.h"
|
||||
|
@ -396,39 +397,41 @@ Dynarmic::A32::UserConfig GetA32UserConfig(TestEnv& testenv, bool noopt) {
|
|||
|
||||
template<size_t num_jit_reruns = 1, typename TestEnv>
|
||||
void RunTestInstance(Dynarmic::A32::Jit& jit,
|
||||
TestEnv& jit_env,
|
||||
const std::array<u32, 16>& regs,
|
||||
const std::array<u32, 64>& vecs,
|
||||
const std::vector<typename TestEnv::InstructionType>& instructions,
|
||||
const u32 cpsr,
|
||||
const u32 fpscr,
|
||||
const size_t ticks_left) {
|
||||
TestEnv& jit_env,
|
||||
const std::array<u32, 16>& regs,
|
||||
const std::array<u32, 64>& vecs,
|
||||
const std::vector<typename TestEnv::InstructionType>& instructions,
|
||||
const u32 cpsr,
|
||||
const u32 fpscr,
|
||||
const size_t ticks_left,
|
||||
const bool show_disas) {
|
||||
const u32 initial_pc = regs[15];
|
||||
const u32 num_words = initial_pc / sizeof(typename TestEnv::InstructionType);
|
||||
const u32 code_mem_size = num_words + static_cast<u32>(instructions.size());
|
||||
|
||||
fmt::print("instructions:");
|
||||
for (auto instruction : instructions) {
|
||||
if constexpr (sizeof(decltype(instruction)) == 2) {
|
||||
fmt::print(" {:04x}", instruction);
|
||||
} else {
|
||||
fmt::print(" {:08x}", instruction);
|
||||
if (show_disas) {
|
||||
fmt::print("instructions:\n");
|
||||
auto current_pc = initial_pc;
|
||||
for (auto instruction : instructions) {
|
||||
if constexpr (sizeof(decltype(instruction)) == 2) {
|
||||
fmt::print("{:04x} ?\n", instruction);
|
||||
} else {
|
||||
fmt::print("{}", Dynarmic::Common::DisassembleAArch64(instruction, current_pc));
|
||||
}
|
||||
current_pc += sizeof(decltype(instruction));
|
||||
}
|
||||
}
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print("initial_regs:");
|
||||
for (u32 i : regs) {
|
||||
fmt::print(" {:08x}", i);
|
||||
fmt::print("initial_regs:");
|
||||
for (u32 i : regs)
|
||||
fmt::print(" {:08x}", i);
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_vecs:");
|
||||
for (u32 i : vecs)
|
||||
fmt::print(" {:08x}", i);
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_cpsr: {:08x}\n", cpsr);
|
||||
fmt::print("initial_fpcr: {:08x}\n", fpscr);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_vecs:");
|
||||
for (u32 i : vecs) {
|
||||
fmt::print(" {:08x}", i);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_cpsr: {:08x}\n", cpsr);
|
||||
fmt::print("initial_fpcr: {:08x}\n", fpscr);
|
||||
|
||||
jit.ClearCache();
|
||||
|
||||
|
@ -450,36 +453,37 @@ void RunTestInstance(Dynarmic::A32::Jit& jit,
|
|||
jit.Run();
|
||||
}
|
||||
|
||||
fmt::print("final_regs:");
|
||||
for (u32 i : jit.Regs()) {
|
||||
fmt::print(" {:08x}", i);
|
||||
if (show_disas) {
|
||||
fmt::print("final_regs:");
|
||||
for (u32 i : jit.Regs()) {
|
||||
fmt::print(" {:08x}", i);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("final_vecs:");
|
||||
for (u32 i : jit.ExtRegs()) {
|
||||
fmt::print(" {:08x}", i);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("final_cpsr: {:08x}\n", jit.Cpsr());
|
||||
fmt::print("final_fpsr: {:08x}\n", mask_fpsr_cum_bits ? jit.Fpscr() & 0xffffff00 : jit.Fpscr());
|
||||
fmt::print("mod_mem: ");
|
||||
for (auto [addr, value] : jit_env.modified_memory) {
|
||||
fmt::print("{:08x}:{:02x} ", addr, value);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("interrupts:\n");
|
||||
for (const auto& i : jit_env.interrupts) {
|
||||
std::puts(i.c_str());
|
||||
}
|
||||
fmt::print("===\n");
|
||||
jit.DumpDisassembly();
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("final_vecs:");
|
||||
for (u32 i : jit.ExtRegs()) {
|
||||
fmt::print(" {:08x}", i);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("final_cpsr: {:08x}\n", jit.Cpsr());
|
||||
fmt::print("final_fpsr: {:08x}\n", mask_fpsr_cum_bits ? jit.Fpscr() & 0xffffff00 : jit.Fpscr());
|
||||
|
||||
fmt::print("mod_mem: ");
|
||||
for (auto [addr, value] : jit_env.modified_memory) {
|
||||
fmt::print("{:08x}:{:02x} ", addr, value);
|
||||
}
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print("interrupts:\n");
|
||||
for (const auto& i : jit_env.interrupts) {
|
||||
std::puts(i.c_str());
|
||||
}
|
||||
|
||||
fmt::print("===\n");
|
||||
}
|
||||
|
||||
Dynarmic::A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
||||
Dynarmic::A64::UserConfig jit_user_config{&jit_env};
|
||||
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
||||
Dynarmic::A64::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &jit_env;
|
||||
jit_user_config.optimizations = all_safe_optimizations;
|
||||
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
||||
jit_user_config.dczid_el0 = 7;
|
||||
jit_user_config.ctr_el0 = 0x80038003;
|
||||
|
@ -491,15 +495,16 @@ Dynarmic::A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
|||
|
||||
template<size_t num_jit_reruns = 2>
|
||||
void RunTestInstance(Dynarmic::A64::Jit& jit,
|
||||
A64TestEnv& jit_env,
|
||||
const std::array<u64, 31>& regs,
|
||||
const std::array<std::array<u64, 2>, 32>& vecs,
|
||||
const std::vector<u32>& instructions,
|
||||
const u32 pstate,
|
||||
const u32 fpcr,
|
||||
const u64 initial_sp,
|
||||
const u64 start_address,
|
||||
const size_t ticks_left) {
|
||||
A64TestEnv& jit_env,
|
||||
const std::array<u64, 31>& regs,
|
||||
const std::array<std::array<u64, 2>, 32>& vecs,
|
||||
const std::vector<u32>& instructions,
|
||||
const u32 pstate,
|
||||
const u32 fpcr,
|
||||
const u64 initial_sp,
|
||||
const u64 start_address,
|
||||
const size_t ticks_left,
|
||||
const bool show_disas) {
|
||||
jit.ClearCache();
|
||||
|
||||
for (size_t jit_rerun_count = 0; jit_rerun_count < num_jit_reruns; ++jit_rerun_count) {
|
||||
|
@ -522,59 +527,53 @@ void RunTestInstance(Dynarmic::A64::Jit& jit,
|
|||
jit.Run();
|
||||
}
|
||||
|
||||
fmt::print("instructions:");
|
||||
for (u32 instruction : instructions) {
|
||||
fmt::print(" {:08x}", instruction);
|
||||
}
|
||||
fmt::print("\n");
|
||||
if (show_disas) {
|
||||
fmt::print("instructions:\n");
|
||||
auto current_pc = start_address;
|
||||
for (u32 instruction : instructions) {
|
||||
fmt::print("{}", Dynarmic::Common::DisassembleAArch64(instruction, current_pc));
|
||||
current_pc += 4;
|
||||
}
|
||||
|
||||
fmt::print("initial_regs:");
|
||||
for (u64 i : regs) {
|
||||
fmt::print(" {:016x}", i);
|
||||
fmt::print("initial_regs:");
|
||||
for (u64 i : regs)
|
||||
fmt::print(" {:016x}", i);
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_vecs:");
|
||||
for (auto i : vecs)
|
||||
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_sp: {:016x}\n", initial_sp);
|
||||
fmt::print("initial_pstate: {:08x}\n", pstate);
|
||||
fmt::print("initial_fpcr: {:08x}\n", fpcr);
|
||||
fmt::print("final_regs:");
|
||||
for (u64 i : jit.GetRegisters())
|
||||
fmt::print(" {:016x}", i);
|
||||
fmt::print("\n");
|
||||
fmt::print("final_vecs:");
|
||||
for (auto i : jit.GetVectors())
|
||||
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
||||
fmt::print("\n");
|
||||
fmt::print("final_sp: {:016x}\n", jit.GetSP());
|
||||
fmt::print("final_pc: {:016x}\n", jit.GetPC());
|
||||
fmt::print("final_pstate: {:08x}\n", jit.GetPstate());
|
||||
fmt::print("final_fpcr: {:08x}\n", jit.GetFpcr());
|
||||
fmt::print("final_qc : {}\n", FP::FPSR{jit.GetFpsr()}.QC());
|
||||
fmt::print("mod_mem:");
|
||||
for (auto [addr, value] : jit_env.modified_memory)
|
||||
fmt::print(" {:08x}:{:02x}", addr, value);
|
||||
fmt::print("\n");
|
||||
fmt::print("interrupts:\n");
|
||||
for (const auto& i : jit_env.interrupts)
|
||||
std::puts(i.c_str());
|
||||
fmt::print("===\n");
|
||||
jit.DumpDisassembly();
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_vecs:");
|
||||
for (auto i : vecs) {
|
||||
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("initial_sp: {:016x}\n", initial_sp);
|
||||
fmt::print("initial_pstate: {:08x}\n", pstate);
|
||||
fmt::print("initial_fpcr: {:08x}\n", fpcr);
|
||||
|
||||
fmt::print("final_regs:");
|
||||
for (u64 i : jit.GetRegisters()) {
|
||||
fmt::print(" {:016x}", i);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("final_vecs:");
|
||||
for (auto i : jit.GetVectors()) {
|
||||
fmt::print(" {:016x}:{:016x}", i[0], i[1]);
|
||||
}
|
||||
fmt::print("\n");
|
||||
fmt::print("final_sp: {:016x}\n", jit.GetSP());
|
||||
fmt::print("final_pc: {:016x}\n", jit.GetPC());
|
||||
fmt::print("final_pstate: {:08x}\n", jit.GetPstate());
|
||||
fmt::print("final_fpcr: {:08x}\n", jit.GetFpcr());
|
||||
fmt::print("final_qc : {}\n", FP::FPSR{jit.GetFpsr()}.QC());
|
||||
|
||||
fmt::print("mod_mem:");
|
||||
for (auto [addr, value] : jit_env.modified_memory) {
|
||||
fmt::print(" {:08x}:{:02x}", addr, value);
|
||||
}
|
||||
fmt::print("\n");
|
||||
|
||||
fmt::print("interrupts:\n");
|
||||
for (const auto& i : jit_env.interrupts) {
|
||||
std::puts(i.c_str());
|
||||
}
|
||||
|
||||
fmt::print("===\n");
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
void TestThumb(size_t num_instructions, size_t num_iterations, bool noopt) {
|
||||
void TestThumb(size_t num_instructions, size_t num_iterations, bool noopt, bool show_disas) {
|
||||
ThumbTestEnv jit_env{};
|
||||
Dynarmic::A32::Jit jit{GetA32UserConfig(jit_env, noopt)};
|
||||
|
||||
|
@ -597,11 +596,11 @@ void TestThumb(size_t num_instructions, size_t num_iterations, bool noopt) {
|
|||
}
|
||||
|
||||
regs[15] = start_address;
|
||||
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions);
|
||||
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions, show_disas);
|
||||
}
|
||||
}
|
||||
|
||||
void TestArm(size_t num_instructions, size_t num_iterations, bool noopt) {
|
||||
void TestArm(size_t num_instructions, size_t num_iterations, bool noopt, bool show_disas) {
|
||||
ArmTestEnv jit_env{};
|
||||
Dynarmic::A32::Jit jit{GetA32UserConfig(jit_env, noopt)};
|
||||
|
||||
|
@ -623,11 +622,11 @@ void TestArm(size_t num_instructions, size_t num_iterations, bool noopt) {
|
|||
}
|
||||
|
||||
regs[15] = start_address;
|
||||
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions);
|
||||
RunTestInstance(jit, jit_env, regs, ext_reg, instructions, cpsr, fpcr, num_instructions, show_disas);
|
||||
}
|
||||
}
|
||||
|
||||
void TestA64(size_t num_instructions, size_t num_iterations, bool noopt) {
|
||||
void TestA64(size_t num_instructions, size_t num_iterations, bool noopt, bool show_disas) {
|
||||
A64TestEnv jit_env{};
|
||||
Dynarmic::A64::Jit jit{GetA64UserConfig(jit_env, noopt)};
|
||||
|
||||
|
@ -649,7 +648,7 @@ void TestA64(size_t num_instructions, size_t num_iterations, bool noopt) {
|
|||
instructions.emplace_back(GenRandomA64Inst(static_cast<u32>(start_address + 4 * instructions.size()), i == num_instructions - 1));
|
||||
}
|
||||
|
||||
RunTestInstance(jit, jit_env, regs, vecs, instructions, pstate, fpcr, initial_sp, start_address, num_instructions);
|
||||
RunTestInstance(jit, jit_env, regs, vecs, instructions, pstate, fpcr, initial_sp, start_address, num_instructions, show_disas);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -677,6 +676,7 @@ int main(int argc, char* argv[]) {
|
|||
const auto instruction_count = str2sz(argv[3]);
|
||||
const auto iterator_count = str2sz(argv[4]);
|
||||
const bool noopt = argc == 6 && (strcmp(argv[5], "noopt") == 0);
|
||||
const bool show_disas = argc == 6 && (strcmp(argv[5], "disas") == 0);
|
||||
|
||||
if (!seed || !instruction_count || !iterator_count) {
|
||||
fmt::print("invalid numeric arguments\n");
|
||||
|
@ -686,11 +686,11 @@ int main(int argc, char* argv[]) {
|
|||
detail::g_rand_int_generator.seed(static_cast<std::mt19937::result_type>(*seed));
|
||||
|
||||
if (strcmp(argv[1], "thumb") == 0) {
|
||||
TestThumb(*instruction_count, *iterator_count, noopt);
|
||||
TestThumb(*instruction_count, *iterator_count, noopt, show_disas);
|
||||
} else if (strcmp(argv[1], "arm") == 0) {
|
||||
TestArm(*instruction_count, *iterator_count, noopt);
|
||||
TestArm(*instruction_count, *iterator_count, noopt, show_disas);
|
||||
} else if (strcmp(argv[1], "a64") == 0) {
|
||||
TestA64(*instruction_count, *iterator_count, noopt);
|
||||
TestA64(*instruction_count, *iterator_count, noopt, show_disas);
|
||||
} else {
|
||||
fmt::print("unrecognized instruction class\n");
|
||||
return 1;
|
||||
|
|
3
externals/dynarmic/tests/test_reader.cpp
vendored
3
externals/dynarmic/tests/test_reader.cpp
vendored
|
@ -158,7 +158,8 @@ void RunTestInstance(Dynarmic::A32::Jit& jit,
|
|||
}
|
||||
|
||||
A64::UserConfig GetA64UserConfig(A64TestEnv& jit_env, bool noopt) {
|
||||
A64::UserConfig jit_user_config{&jit_env};
|
||||
A64::UserConfig jit_user_config{};
|
||||
jit_user_config.callbacks = &jit_env;
|
||||
jit_user_config.optimizations &= ~OptimizationFlag::FastDispatch;
|
||||
// The below corresponds to the settings for qemu's aarch64_max_initfn
|
||||
jit_user_config.dczid_el0 = 7;
|
||||
|
|
|
@ -208,7 +208,7 @@ CubebSink::CubebSink(std::string_view target_device_name) {
|
|||
com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
#endif
|
||||
|
||||
if (cubeb_init(&ctx, "yuzu", nullptr) != CUBEB_OK) {
|
||||
if (cubeb_init(&ctx, "Eden", nullptr) != CUBEB_OK) {
|
||||
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
|
||||
return;
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
|
|||
auto com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
#endif
|
||||
|
||||
if (cubeb_init(&ctx, "yuzu Device Enumerator", nullptr) != CUBEB_OK) {
|
||||
if (cubeb_init(&ctx, "Eden Device Enumerator", nullptr) != CUBEB_OK) {
|
||||
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
|
||||
return {};
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ bool IsCubebSuitable() {
|
|||
#endif
|
||||
|
||||
// Init cubeb
|
||||
if (cubeb_init(&ctx, "yuzu Latency Getter", nullptr) != CUBEB_OK) {
|
||||
if (cubeb_init(&ctx, "Eden Latency Getter", nullptr) != CUBEB_OK) {
|
||||
LOG_ERROR(Audio_Sink, "Cubeb failed to init, it is not suitable.");
|
||||
return false;
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ bool IsCubebSuitable() {
|
|||
// Test opening a device with standard parameters
|
||||
cubeb_devid output_device{0};
|
||||
cubeb_devid input_device{0};
|
||||
std::string name{"Yuzu test"};
|
||||
std::string name{"Eden test"};
|
||||
cubeb_stream* stream{nullptr};
|
||||
|
||||
if (cubeb_stream_init(ctx, &stream, name.c_str(), input_device, nullptr, output_device, ¶ms,
|
||||
|
|
|
@ -118,7 +118,7 @@ void LogSettings() {
|
|||
LOG_INFO(Config, "{}: {}", name, Common::FS::PathToUTF8String(path));
|
||||
};
|
||||
|
||||
LOG_INFO(Config, "yuzu Configuration:");
|
||||
LOG_INFO(Config, "Eden Configuration:");
|
||||
for (auto& [category, settings] : values.linkage.by_category) {
|
||||
for (const auto& setting : settings) {
|
||||
if (setting->Id() == values.eden_token.Id()) {
|
||||
|
|
|
@ -564,7 +564,7 @@ struct Values {
|
|||
linkage, 0, "rng_seed", Category::System, Specialization::Hex,
|
||||
true, true, &rng_seed_enabled};
|
||||
Setting<std::string> device_name{
|
||||
linkage, "eden", "device_name", Category::System, Specialization::Default, true, true};
|
||||
linkage, "Eden", "device_name", Category::System, Specialization::Default, true, true};
|
||||
|
||||
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
||||
|
||||
|
|
|
@ -76,13 +76,13 @@ struct UUID {
|
|||
u128 AsU128() const;
|
||||
|
||||
/**
|
||||
* Creates a default UUID "yuzu Default UID".
|
||||
* Creates a default UUID "Eden Default UID".
|
||||
*
|
||||
* @returns A UUID with its bytes set to the ASCII values of "yuzu Default UID".
|
||||
* @returns A UUID with its bytes set to the ASCII values of "Eden Default UID".
|
||||
*/
|
||||
static constexpr UUID MakeDefault() {
|
||||
return UUID{
|
||||
{'y', 'u', 'z', 'u', ' ', 'D', 'e', 'f', 'a', 'u', 'l', 't', ' ', 'U', 'I', 'D'},
|
||||
{'E', 'd', 'e', 'n', ' ', 'D', 'e', 'f', 'a', 'u', 'l', 't', ' ', 'U', 'I', 'D'},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ void DefaultSoftwareKeyboardApplet::ShowNormalKeyboard() const {
|
|||
LOG_WARNING(Service_AM,
|
||||
"(STUBBED) called, backend requested to show the normal software keyboard.");
|
||||
|
||||
SubmitNormalText(u"yuzu");
|
||||
SubmitNormalText(u"Eden");
|
||||
}
|
||||
|
||||
void DefaultSoftwareKeyboardApplet::ShowTextCheckDialog(
|
||||
|
@ -100,7 +100,7 @@ void DefaultSoftwareKeyboardApplet::ShowInlineKeyboard(
|
|||
appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button,
|
||||
appear_parameters.enable_return_button, appear_parameters.disable_cancel_button);
|
||||
|
||||
std::thread([this] { SubmitInlineText(u"yuzu"); }).detach();
|
||||
std::thread([this] { SubmitInlineText(u"Eden"); }).detach();
|
||||
}
|
||||
|
||||
void DefaultSoftwareKeyboardApplet::HideInlineKeyboard() const {
|
||||
|
|
|
@ -969,7 +969,7 @@ void Module::Interface::InitializeApplicationInfoV2(HLERequestContext& ctx) {
|
|||
|
||||
void Module::Interface::BeginUserRegistration(HLERequestContext& ctx) {
|
||||
const auto user_id = Common::UUID::MakeRandom();
|
||||
profile_manager->CreateNewUser(user_id, "yuzu");
|
||||
profile_manager->CreateNewUser(user_id, "Eden");
|
||||
|
||||
LOG_INFO(Service_ACC, "called, uuid={}", user_id.FormattedString());
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ ProfileManager::ProfileManager() {
|
|||
|
||||
// Create an user if none are present
|
||||
if (user_count == 0) {
|
||||
CreateNewUser(UUID::MakeRandom(), "eden");
|
||||
CreateNewUser(UUID::MakeRandom(), "Eden");
|
||||
WriteUserSaveFile();
|
||||
}
|
||||
|
||||
|
|
|
@ -68,14 +68,13 @@ static void PrintHelp(const char* argv0) {
|
|||
"-a, --web-api-url yuzu Web API url\n"
|
||||
"-b, --ban-list-file The file for storing the room ban list\n"
|
||||
"-l, --log-file The file for storing the room log\n"
|
||||
"-e, --enable-mods Allow Community Moderators to moderate on your room\n"
|
||||
"-h, --help Display this help and exit\n"
|
||||
"-v, --version Output version information and exit\n",
|
||||
argv0);
|
||||
}
|
||||
|
||||
static void PrintVersion() {
|
||||
LOG_INFO(Network, "yuzu dedicated room {} {} Libnetwork: {}", Common::g_scm_branch,
|
||||
LOG_INFO(Network, "Eden dedicated room {} {} Libnetwork: {}", Common::g_scm_branch,
|
||||
Common::g_scm_desc, Network::network_version);
|
||||
}
|
||||
|
||||
|
@ -229,7 +228,6 @@ void LaunchRoom(int argc, char** argv, bool called_by_option)
|
|||
{"web-api-url", required_argument, 0, 'a'},
|
||||
{"ban-list-file", required_argument, 0, 'b'},
|
||||
{"log-file", required_argument, 0, 'l'},
|
||||
{"enable-mods", no_argument, 0, 'e'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
// Entry option
|
||||
|
@ -369,7 +367,7 @@ void LaunchRoom(int argc, char** argv, bool called_by_option)
|
|||
std::make_unique<WebService::VerifyUserJWT>(Settings::values.web_api_url.GetValue());
|
||||
#else
|
||||
LOG_INFO(Network,
|
||||
"yuzu Web Services is not available with this build: validation is disabled.");
|
||||
"Eden Web Services is not available with this build: validation is disabled.");
|
||||
verify_backend = std::make_unique<Network::VerifyUser::NullBackend>();
|
||||
#endif
|
||||
} else {
|
||||
|
|
|
@ -489,7 +489,7 @@ void SDLDriver::CloseJoysticks() {
|
|||
SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
|
||||
// Set our application name. Currently passed to DBus by SDL and visible to the user through
|
||||
// their desktop environment.
|
||||
SDL_SetHint(SDL_HINT_APP_NAME, "yuzu");
|
||||
SDL_SetHint(SDL_HINT_APP_NAME, "Eden");
|
||||
|
||||
if (!Settings::values.enable_raw_input) {
|
||||
// Disable raw input. When enabled this setting causes SDL to die when a web applet opens
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
@ -73,15 +76,27 @@ public:
|
|||
|
||||
void SignalFence(std::function<void()>&& func) {
|
||||
bool delay_fence = Settings::IsGPULevelHigh();
|
||||
#ifdef __ANDROID__
|
||||
if (!delay_fence) {
|
||||
TryReleasePendingFences<false>();
|
||||
}
|
||||
#else
|
||||
if constexpr (!can_async_check) {
|
||||
TryReleasePendingFences<false>();
|
||||
}
|
||||
#endif
|
||||
const bool should_flush = ShouldFlush();
|
||||
CommitAsyncFlushes();
|
||||
TFence new_fence = CreateFence(!should_flush);
|
||||
#ifdef __ANDROID__
|
||||
if (delay_fence) {
|
||||
guard.lock();
|
||||
}
|
||||
#else
|
||||
if constexpr (can_async_check) {
|
||||
guard.lock();
|
||||
}
|
||||
#endif
|
||||
if (delay_fence) {
|
||||
uncommitted_operations.emplace_back(std::move(func));
|
||||
}
|
||||
|
@ -94,10 +109,17 @@ public:
|
|||
if (should_flush) {
|
||||
rasterizer.FlushCommands();
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
if (delay_fence) {
|
||||
guard.unlock();
|
||||
cv.notify_all();
|
||||
}
|
||||
#else
|
||||
if constexpr (can_async_check) {
|
||||
guard.unlock();
|
||||
cv.notify_all();
|
||||
}
|
||||
#endif
|
||||
rasterizer.InvalidateGPUCache();
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ void NsightAftermathTracker::OnShaderDebugInfoCallback(const void* shader_debug_
|
|||
|
||||
void NsightAftermathTracker::OnCrashDumpDescriptionCallback(
|
||||
PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription add_description) {
|
||||
add_description(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "yuzu");
|
||||
add_description(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "Eden");
|
||||
}
|
||||
|
||||
void NsightAftermathTracker::GpuCrashDumpCallback(const void* gpu_crash_dump,
|
||||
|
|
|
@ -437,9 +437,9 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char
|
|||
const VkApplicationInfo application_info{
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
.pNext = nullptr,
|
||||
.pApplicationName = "yuzu Emulator",
|
||||
.pApplicationName = "Eden Emulator",
|
||||
.applicationVersion = VK_MAKE_VERSION(0, 1, 0),
|
||||
.pEngineName = "yuzu Emulator",
|
||||
.pEngineName = "Eden Emulator",
|
||||
.engineVersion = VK_MAKE_VERSION(0, 1, 0),
|
||||
.apiVersion = VK_API_VERSION_1_3,
|
||||
};
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-size:28pt;">eden</span></p></body></html></string>
|
||||
<string><html><head/><body><p><span style=" font-size:28pt;">Eden</span></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -101,8 +101,8 @@ p, li { white-space: pre-wrap; }
|
|||
hr { height: 1px; border-width: 0; }
|
||||
li.unchecked::marker { content: "\2610"; }
|
||||
li.checked::marker { content: "\2612"; }
|
||||
</style></head><body style=" font-family:'Adwaita Sans'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">eden is an experimental open-source emulator for the Nintendo Switch licensed under GPLv3.0+ which is based on the yuzu emulator which ended development back in March 2024. <br /><br />This software should not be used to play games you have not legally obtained.</span></p></body></html></string>
|
||||
</style></head><body style=" font-family:'Noto Sans'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">Eden is an experimental open-source emulator for the Nintendo Switch licensed under GPLv3.0+ which is based on the yuzu emulator which ended development back in March 2024. <br /><br />This software should not be used to play games you have not legally obtained.</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
|
@ -165,7 +165,6 @@ li.checked::marker { content: "\2612"; }
|
|||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../dist/qt_themes_default/default/default.qrc"/>
|
||||
<include location="../../dist/qt_themes/default/default.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
|
|
|
@ -286,7 +286,7 @@ GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,
|
|||
Core::System& system_)
|
||||
: QWidget(parent),
|
||||
emu_thread(emu_thread_), input_subsystem{std::move(input_subsystem_)}, system{system_} {
|
||||
setWindowTitle(QStringLiteral("eden %1 | %2-%3")
|
||||
setWindowTitle(QStringLiteral("Eden %1 | %2-%3")
|
||||
.arg(QString::fromUtf8(Common::g_build_name),
|
||||
QString::fromUtf8(Common::g_scm_branch),
|
||||
QString::fromUtf8(Common::g_scm_desc)));
|
||||
|
@ -1034,7 +1034,7 @@ bool GRenderWindow::InitializeOpenGL() {
|
|||
return true;
|
||||
#else
|
||||
QMessageBox::warning(this, tr("OpenGL not available!"),
|
||||
tr("eden has not been compiled with OpenGL support."));
|
||||
tr("Eden has not been compiled with OpenGL support."));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -560,7 +560,7 @@
|
|||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>**This will be reset automatically when eden closes.</string>
|
||||
<string>**This will be reset automatically when Eden closes.</string>
|
||||
</property>
|
||||
<property name="indent">
|
||||
<number>20</number>
|
||||
|
|
|
@ -96,7 +96,7 @@ void ConfigureGeneral::SetResetCallback(std::function<void()> callback) {
|
|||
|
||||
void ConfigureGeneral::ResetDefaults() {
|
||||
QMessageBox::StandardButton answer = QMessageBox::question(
|
||||
this, tr("eden"),
|
||||
this, tr("Eden"),
|
||||
tr("This reset all settings and remove all per-game configurations. This will not delete "
|
||||
"game directories, profiles, or input profiles. Proceed?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
|
|
|
@ -2656,7 +2656,7 @@
|
|||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="enable_raw_input">
|
||||
<property name="toolTip">
|
||||
<string>Requires restarting eden</string>
|
||||
<string>Requires restarting Eden</string>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
@ -2698,7 +2698,7 @@
|
|||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="enable_joycon_driver">
|
||||
<property name="toolTip">
|
||||
<string>Requires restarting eden</string>
|
||||
<string>Requires restarting Eden</string>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
@ -2714,7 +2714,7 @@
|
|||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="enable_procon_driver">
|
||||
<property name="toolTip">
|
||||
<string>Requires restarting eden</string>
|
||||
<string>Requires restarting Eden</string>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
|
|
|
@ -170,27 +170,27 @@ void ConfigureMotionTouch::OnUDPAddServer() {
|
|||
const int row = udp_server_list_model->rowCount();
|
||||
|
||||
if (!ok) {
|
||||
QMessageBox::warning(this, tr("eden"), tr("Port number has invalid characters"));
|
||||
QMessageBox::warning(this, tr("Eden"), tr("Port number has invalid characters"));
|
||||
return;
|
||||
}
|
||||
if (port_number < 0 || port_number > 65353) {
|
||||
QMessageBox::warning(this, tr("eden"), tr("Port has to be in range 0 and 65353"));
|
||||
QMessageBox::warning(this, tr("Eden"), tr("Port has to be in range 0 and 65353"));
|
||||
return;
|
||||
}
|
||||
if (!re.match(server_text).hasMatch()) {
|
||||
QMessageBox::warning(this, tr("eden"), tr("IP address is not valid"));
|
||||
QMessageBox::warning(this, tr("Eden"), tr("IP address is not valid"));
|
||||
return;
|
||||
}
|
||||
// Search for duplicates
|
||||
for (const auto& item : udp_server_list_model->stringList()) {
|
||||
if (item == server_string) {
|
||||
QMessageBox::warning(this, tr("eden"), tr("This UDP server already exists"));
|
||||
QMessageBox::warning(this, tr("Eden"), tr("This UDP server already exists"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Limit server count to 8
|
||||
if (row == 8) {
|
||||
QMessageBox::warning(this, tr("eden"), tr("Unable to add more than 8 servers"));
|
||||
QMessageBox::warning(this, tr("Eden"), tr("Unable to add more than 8 servers"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ void ConfigureMotionTouch::OnConfigureTouchFromButton() {
|
|||
|
||||
bool ConfigureMotionTouch::CanCloseDialog() {
|
||||
if (udp_test_in_progress) {
|
||||
QMessageBox::warning(this, tr("eden"),
|
||||
QMessageBox::warning(this, tr("Eden"),
|
||||
tr("UDP Test or calibration configuration is in progress.<br>Please "
|
||||
"wait for them to finish."));
|
||||
return false;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QLabel" name="label_1">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>Reads controller input from scripts in the same format as TAS-nx scripts.<br/>For a more detailed explanation, please consult the <a href="https://eden-emulator.github.io/help/feature/tas/"><span style=" text-decoration: underline; color:#039be5;">help page</span></a> on the eden website.</p></body></html></string>
|
||||
<string><html><head/><body><p>Reads controller input from scripts in the same format as TAS-nx scripts.<br/>For a more detailed explanation, please consult the <a href="https://eden-emulator.github.io/help/feature/tas/"><span style=" text-decoration: underline; color:#039be5;">help page</span></a> on the Eden website.</p></body></html></string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Warning: The settings in this page affect the inner workings of eden's emulated touchscreen. Changing them may result in undesirable behavior, such as the touchscreen partially or not working. You should only use this page if you know what you are doing.</string>
|
||||
<string>Warning: The settings in this page affect the inner workings of Eden's emulated touchscreen. Changing them may result in undesirable behavior, such as the touchscreen partially or not working. You should only use this page if you know what you are doing.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxWebConfig">
|
||||
<property name="title">
|
||||
<string>eden Web Service</string>
|
||||
<string>Eden Web Service</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayoutYuzuWebService">
|
||||
<item>
|
||||
|
|
|
@ -420,12 +420,12 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent)
|
|||
INSERT(UISettings,
|
||||
select_user_on_boot,
|
||||
tr("Prompt for user on game boot"),
|
||||
tr("Ask to select a user profile on each boot, useful if multiple people use eden on "
|
||||
tr("Ask to select a user profile on each boot, useful if multiple people use Eden on "
|
||||
"the same PC."));
|
||||
INSERT(UISettings,
|
||||
pause_when_in_background,
|
||||
tr("Pause emulation when in background"),
|
||||
tr("This setting pauses eden when focusing other windows."));
|
||||
tr("This setting pauses Eden when focusing other windows."));
|
||||
INSERT(UISettings,
|
||||
confirm_before_stopping,
|
||||
tr("Confirm before stopping emulation"),
|
||||
|
|
|
@ -390,13 +390,13 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
|||
const auto description = std::string(Common::g_scm_desc);
|
||||
const auto build_id = std::string(Common::g_build_id);
|
||||
|
||||
const auto yuzu_build = fmt::format("eden Development Build | {}-{}", branch_name, description);
|
||||
const auto yuzu_build = fmt::format("Eden Development Build | {}-{}", branch_name, description);
|
||||
const auto override_build =
|
||||
fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id);
|
||||
const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build;
|
||||
const auto processor_count = std::thread::hardware_concurrency();
|
||||
|
||||
LOG_INFO(Frontend, "eden Version: {}", yuzu_build_version);
|
||||
LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version);
|
||||
LogRuntimes();
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
const auto& caps = Common::GetCPUCaps();
|
||||
|
@ -1410,7 +1410,7 @@ void GMainWindow::InitializeHotkeys() {
|
|||
|
||||
LinkActionShortcut(ui->action_Load_File, QStringLiteral("Load File"));
|
||||
LinkActionShortcut(ui->action_Load_Amiibo, QStringLiteral("Load/Remove Amiibo"));
|
||||
LinkActionShortcut(ui->action_Exit, QStringLiteral("Exit eden"));
|
||||
LinkActionShortcut(ui->action_Exit, QStringLiteral("Exit Eden"));
|
||||
LinkActionShortcut(ui->action_Restart, QStringLiteral("Restart Emulation"));
|
||||
LinkActionShortcut(ui->action_Pause, QStringLiteral("Continue/Pause Emulation"));
|
||||
LinkActionShortcut(ui->action_Stop, QStringLiteral("Stop Emulation"));
|
||||
|
@ -1969,7 +1969,7 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
|
|||
tr("You are using the deconstructed ROM directory format for this game, which is an "
|
||||
"outdated format that has been superseded by others such as NCA, NAX, XCI, or "
|
||||
"NSP. Deconstructed ROM directories lack icons, metadata, and update "
|
||||
"support.<br><br>For an explanation of the various Switch formats eden supports, <a "
|
||||
"support.<br><br>For an explanation of the various Switch formats Eden supports, <a "
|
||||
"href='https://eden-emulator.github.io/wiki/overview-of-switch-game-formats'>check out our "
|
||||
"wiki</a>. This message will not be shown again."));
|
||||
}
|
||||
|
@ -1984,7 +1984,7 @@ bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletPa
|
|||
case Core::SystemResultStatus::ErrorVideoCore:
|
||||
QMessageBox::critical(
|
||||
this, tr("An error occurred initializing the video core."),
|
||||
tr("eden has encountered an error while running the video core. "
|
||||
tr("Eden has encountered an error while running the video core. "
|
||||
"This is usually caused by outdated GPU drivers, including integrated ones. "
|
||||
"Please see the log for more details. "
|
||||
"For more information on accessing the log, please see the following page: "
|
||||
|
@ -2076,7 +2076,7 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
|
|||
|
||||
void GMainWindow::BootGame(const QString& filename, Service::AM::FrontendAppletParameters params,
|
||||
StartGameType type) {
|
||||
LOG_INFO(Frontend, "eden starting...");
|
||||
LOG_INFO(Frontend, "Eden starting...");
|
||||
|
||||
if (params.program_id == 0 ||
|
||||
params.program_id > static_cast<u64>(Service::AM::AppletProgramId::MaxProgramId)) {
|
||||
|
@ -3621,8 +3621,8 @@ void GMainWindow::OnMenuReportCompatibility() {
|
|||
} else {
|
||||
QMessageBox::critical(
|
||||
this, tr("Missing yuzu Account"),
|
||||
tr("In order to submit a game compatibility test case, you must link your eden "
|
||||
"account.<br><br/>To link your eden account, go to Emulation > Configuration "
|
||||
tr("In order to submit a game compatibility test case, you must set up your web token and "
|
||||
"username.<br><br/>To link your eden account, go to Emulation > Configuration "
|
||||
"> "
|
||||
"Web."));
|
||||
}
|
||||
|
@ -3650,7 +3650,7 @@ void GMainWindow::OnOpenQuickstartGuide() {
|
|||
}
|
||||
|
||||
void GMainWindow::OnOpenFAQ() {
|
||||
OpenURL(QUrl(QStringLiteral("https://eden-emulator.github.io/")));
|
||||
OpenURL(QUrl(QStringLiteral("https://eden-emu.dev")));
|
||||
}
|
||||
|
||||
void GMainWindow::OnOpenDiscord()
|
||||
|
@ -5260,8 +5260,8 @@ bool GMainWindow::ConfirmClose() {
|
|||
UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Based_On_Game) {
|
||||
return true;
|
||||
}
|
||||
const auto text = tr("Are you sure you want to close eden?");
|
||||
return question(this, tr("eden"), text);
|
||||
const auto text = tr("Are you sure you want to close Eden?");
|
||||
return question(this, tr("Eden"), text);
|
||||
}
|
||||
|
||||
void GMainWindow::closeEvent(QCloseEvent* event) {
|
||||
|
@ -5341,7 +5341,7 @@ bool GMainWindow::ConfirmChangeGame() {
|
|||
|
||||
// Use custom question to link controller navigation
|
||||
return question(
|
||||
this, tr("eden"),
|
||||
this, tr("Eden"),
|
||||
tr("Are you sure you want to stop the emulation? Any unsaved progress will be lost."),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
}
|
||||
|
@ -5350,10 +5350,10 @@ bool GMainWindow::ConfirmForceLockedExit() {
|
|||
if (emu_thread == nullptr) {
|
||||
return true;
|
||||
}
|
||||
const auto text = tr("The currently running application has requested eden to not exit.\n\n"
|
||||
const auto text = tr("The currently running application has requested Eden to not exit.\n\n"
|
||||
"Would you like to bypass this and exit anyway?");
|
||||
|
||||
return question(this, tr("eden"), text);
|
||||
return question(this, tr("Eden"), text);
|
||||
}
|
||||
|
||||
void GMainWindow::RequestGameExit() {
|
||||
|
|
|
@ -269,7 +269,7 @@
|
|||
</action>
|
||||
<action name="action_About">
|
||||
<property name="text">
|
||||
<string>&About eden</string>
|
||||
<string>&About Eden</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Single_Window_Mode">
|
||||
|
|
|
@ -60,7 +60,7 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
|
|||
ui->username->setText(
|
||||
QString::fromStdString(UISettings::values.multiplayer_room_nickname.GetValue()));
|
||||
if (ui->username->text().isEmpty() && !Settings::values.eden_username.GetValue().empty()) {
|
||||
// Use eden Web Service user name as nickname by default
|
||||
// Use Eden Web Service user name as nickname by default
|
||||
ui->username->setText(QString::fromStdString(Settings::values.eden_username.GetValue()));
|
||||
}
|
||||
ui->room_name->setText(
|
||||
|
@ -186,7 +186,7 @@ void HostRoomWindow::Host() {
|
|||
QMessageBox::warning(
|
||||
this, tr("Error"),
|
||||
tr("Failed to announce the room to the public lobby. In order to host a "
|
||||
"room publicly, you must have a valid eden account configured in "
|
||||
"room publicly, you must have a valid Eden account configured in "
|
||||
"Emulation -> Configure -> Web. If you do not want to publish a room in "
|
||||
"the public lobby, then select Unlisted instead.\nDebug Message: ") +
|
||||
QString::fromStdString(result.result_string),
|
||||
|
|
|
@ -66,14 +66,14 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
|||
QString::fromStdString(UISettings::values.multiplayer_nickname.GetValue()));
|
||||
|
||||
// Try find the best nickname by default
|
||||
if (ui->nickname->text().isEmpty() || ui->nickname->text() == QStringLiteral("eden")) {
|
||||
if (ui->nickname->text().isEmpty() || ui->nickname->text() == QStringLiteral("Eden")) {
|
||||
if (!Settings::values.eden_username.GetValue().empty()) {
|
||||
ui->nickname->setText(
|
||||
QString::fromStdString(Settings::values.eden_username.GetValue()));
|
||||
} else if (!GetProfileUsername().empty()) {
|
||||
ui->nickname->setText(QString::fromStdString(GetProfileUsername()));
|
||||
} else {
|
||||
ui->nickname->setText(QStringLiteral("eden"));
|
||||
ui->nickname->setText(QStringLiteral("Eden"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,12 +29,12 @@ const ConnectionError ErrorManager::UNABLE_TO_CONNECT(
|
|||
const ConnectionError ErrorManager::ROOM_IS_FULL(
|
||||
QT_TR_NOOP("Unable to connect to the room because it is already full."));
|
||||
const ConnectionError ErrorManager::COULD_NOT_CREATE_ROOM(
|
||||
QT_TR_NOOP("Creating a room failed. Please retry. Restarting eden might be necessary."));
|
||||
QT_TR_NOOP("Creating a room failed. Please retry. Restarting Eden might be necessary."));
|
||||
const ConnectionError ErrorManager::HOST_BANNED(
|
||||
QT_TR_NOOP("The host of the room has banned you. Speak with the host to unban you "
|
||||
"or try a different room."));
|
||||
const ConnectionError ErrorManager::WRONG_VERSION(
|
||||
QT_TR_NOOP("Version mismatch! Please update to the latest version of eden. If the problem "
|
||||
QT_TR_NOOP("Version mismatch! Please update to the latest version of Eden. If the problem "
|
||||
"persists, contact the room host and ask them to update the server."));
|
||||
const ConnectionError ErrorManager::WRONG_PASSWORD(QT_TR_NOOP("Incorrect password."));
|
||||
const ConnectionError ErrorManager::GENERIC_ERROR(QT_TR_NOOP(
|
||||
|
|
|
@ -242,7 +242,7 @@ const std::array<Shortcut, 30> default_hotkeys{{
|
|||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Configure Current Game")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+."), std::string(""), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F4"), std::string("Home+Plus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit eden")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Eden")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
|
||||
|
|
|
@ -223,7 +223,7 @@ void EmuWindow_SDL2::WaitEvent() {
|
|||
const u32 current_time = SDL_GetTicks();
|
||||
if (current_time > last_time + 2000) {
|
||||
const auto results = system.GetAndResetPerfStats();
|
||||
const auto title = fmt::format("eden {} | {}-{} | FPS: {:.0f} ({:.0f}%)",
|
||||
const auto title = fmt::format("Eden {} | {}-{} | FPS: {:.0f} ({:.0f}%)",
|
||||
Common::g_build_fullname,
|
||||
Common::g_scm_branch,
|
||||
Common::g_scm_desc,
|
||||
|
@ -238,7 +238,7 @@ void EmuWindow_SDL2::WaitEvent() {
|
|||
void EmuWindow_SDL2::SetWindowIcon() {
|
||||
SDL_RWops* const yuzu_icon_stream = SDL_RWFromConstMem((void*)yuzu_icon, yuzu_icon_size);
|
||||
if (yuzu_icon_stream == nullptr) {
|
||||
LOG_WARNING(Frontend, "Failed to create eden icon stream.");
|
||||
LOG_WARNING(Frontend, "Failed to create Eden icon stream.");
|
||||
return;
|
||||
}
|
||||
SDL_Surface* const window_icon = SDL_LoadBMP_RW(yuzu_icon_stream, 1);
|
||||
|
|
|
@ -90,7 +90,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste
|
|||
}
|
||||
SDL_GL_SetSwapInterval(0);
|
||||
|
||||
std::string window_title = fmt::format("eden {} | {}-{}", Common::g_build_fullname,
|
||||
std::string window_title = fmt::format("Eden {} | {}-{}", Common::g_build_fullname,
|
||||
Common::g_scm_branch, Common::g_scm_desc);
|
||||
render_window =
|
||||
SDL_CreateWindow(window_title.c_str(),
|
||||
|
@ -138,7 +138,7 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste
|
|||
OnResize();
|
||||
OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
|
||||
SDL_PumpEvents();
|
||||
LOG_INFO(Frontend, "eden Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch,
|
||||
LOG_INFO(Frontend, "Eden Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch,
|
||||
Common::g_scm_desc);
|
||||
Settings::LogSettings();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_,
|
||||
Core::System& system_, bool fullscreen)
|
||||
: EmuWindow_SDL2{input_subsystem_, system_} {
|
||||
const std::string window_title = fmt::format("eden {} | {}-{} (Vulkan)", Common::g_build_name,
|
||||
const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)", Common::g_build_name,
|
||||
Common::g_scm_branch, Common::g_scm_desc);
|
||||
render_window =
|
||||
SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
|
@ -40,7 +40,7 @@ EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subs
|
|||
OnResize();
|
||||
OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
|
||||
SDL_PumpEvents();
|
||||
LOG_INFO(Frontend, "eden Version: {} | {}-{} (Null)", Common::g_build_name,
|
||||
LOG_INFO(Frontend, "Eden Version: {} | {}-{} (Null)", Common::g_build_name,
|
||||
Common::g_scm_branch, Common::g_scm_desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_,
|
||||
Core::System& system_, bool fullscreen)
|
||||
: EmuWindow_SDL2{input_subsystem_, system_} {
|
||||
const std::string window_title = fmt::format("eden {} | {}-{} (Vulkan)",
|
||||
const std::string window_title = fmt::format("Eden {} | {}-{} (Vulkan)",
|
||||
Common::g_build_name,
|
||||
Common::g_scm_branch,
|
||||
Common::g_scm_desc);
|
||||
|
@ -84,7 +84,7 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
|
|||
OnResize();
|
||||
OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size);
|
||||
SDL_PumpEvents();
|
||||
LOG_INFO(Frontend, "eden Version: {} | {}-{} (Vulkan)", Common::g_build_name,
|
||||
LOG_INFO(Frontend, "Eden Version: {} | {}-{} (Vulkan)", Common::g_build_name,
|
||||
Common::g_scm_branch, Common::g_scm_desc);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ static void PrintHelp(const char* argv0) {
|
|||
}
|
||||
|
||||
static void PrintVersion() {
|
||||
std::cout << "eden " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl;
|
||||
std::cout << "Eden " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl;
|
||||
}
|
||||
|
||||
static void OnStateChanged(const Network::RoomMember::State& state) {
|
||||
|
@ -408,7 +408,7 @@ int main(int argc, char** argv) {
|
|||
const u16 error_id = static_cast<u16>(load_result) - loader_id;
|
||||
LOG_CRITICAL(Frontend,
|
||||
"While attempting to load the ROM requested, an error occurred. Please "
|
||||
"refer to the eden wiki for more information or the eden discord for "
|
||||
"refer to the Eden wiki for more information or the Eden discord for "
|
||||
"additional help.\n\nError Code: {:04X}-{:04X}\nError Description: {}",
|
||||
loader_id,
|
||||
error_id,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue