[LINT] Linted files + Added lint job to CI

This commit is contained in:
Gliniak
2024-03-12 08:59:10 +01:00
committed by Radosław Gliński
parent e8afad8f8a
commit b9061e6292
117 changed files with 1177 additions and 883 deletions

View File

@@ -78,7 +78,8 @@ class Backend {
virtual void InitializeBackendContext(void* ctx) {}
/*
Free any dynamically allocated data/resources that the backendcontext uses
Free any dynamically allocated data/resources that the backendcontext
uses
*/
virtual void DeinitializeBackendContext(void* ctx) {}
virtual void SetGuestRoundingMode(void* ctx, unsigned int mode){};

View File

@@ -314,7 +314,6 @@ SIMPLE_THREEOPERAND(vpshaw, xop_VPSHAW)
SIMPLE_THREEOPERAND(vpshad, xop_VPSHAD)
SIMPLE_THREEOPERAND(vpshaq, xop_VPSHAQ)
SIMPLE_THREEOPERAND(vpshlb, xop_VPSHLB)
SIMPLE_THREEOPERAND(vpshlw, xop_VPSHLW)
SIMPLE_THREEOPERAND(vpshld, xop_VPSHLD)

View File

@@ -924,7 +924,8 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
Xbyak::Label L18, L2, L35, L4, L9, L8, L10, L11, L12, L13, L1;
Xbyak::Label LC1, _LCPI3_1;
Xbyak::Label handle_denormal_input;
Xbyak::Label specialcheck_1, convert_to_signed_inf_and_ret, handle_oddball_denormal;
Xbyak::Label specialcheck_1, convert_to_signed_inf_and_ret,
handle_oddball_denormal;
auto emulate_lzcnt_helper_unary_reg = [this](auto& reg, auto& scratch_reg) {
inLocalLabel();
@@ -941,19 +942,19 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
vmovd(r8d, xmm0);
vmovaps(xmm1, xmm0);
mov(ecx, r8d);
//extract mantissa
// extract mantissa
and_(ecx, 0x7fffff);
mov(edx, ecx);
cmp(r8d, 0xff800000);
jz(specialcheck_1, CodeGenerator::T_NEAR);
//is exponent zero?
// is exponent zero?
test(r8d, 0x7f800000);
jne(L18);
test(ecx, ecx);
jne(L2);
L(L18);
//extract biased exponent and unbias
// extract biased exponent and unbias
mov(r9d, r8d);
shr(r9d, 23);
movzx(r9d, r9b);
@@ -988,7 +989,7 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
vxorps(xmm0, xmm0, xmm0);
vcomiss(xmm0, xmm1);
jbe(L9);
vmovss(xmm2, ptr[rip+LC1]);
vmovss(xmm2, ptr[rip + LC1]);
vandps(xmm1, GetXmmConstPtr(XMMSignMaskF32));
test(edx, edx);
@@ -1019,7 +1020,7 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
L(L11);
vxorps(xmm2, xmm2, xmm2);
vmovss(xmm0, ptr[rip+LC1]);
vmovss(xmm0, ptr[rip + LC1]);
vcomiss(xmm2, xmm1);
ja(L1, CodeGenerator::T_NEAR);
mov(ecx, 127);
@@ -1080,7 +1081,7 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
or_(ecx, r8d);
or_(ecx, eax);
vmovd(xmm0, ecx);
vaddss(xmm0, xmm1);//apply DAZ behavior to output
vaddss(xmm0, xmm1); // apply DAZ behavior to output
L(L1);
ret();
@@ -1107,7 +1108,8 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
xchg(ecx, edx);
// esi is just the value of xmm0's low word, so we can restore it from there
shl(r8d, cl);
mov(ecx, edx); // restore ecx, dont xchg because we're going to spoil edx anyway
mov(ecx,
edx); // restore ecx, dont xchg because we're going to spoil edx anyway
mov(edx, r8d);
vmovd(r8d, xmm0);
}
@@ -1115,8 +1117,8 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
jmp(L4);
L(specialcheck_1);
//should be extremely rare
vmovss(xmm0, ptr[rip+LC1]);
// should be extremely rare
vmovss(xmm0, ptr[rip + LC1]);
ret();
L(handle_oddball_denormal);
@@ -1131,7 +1133,8 @@ void* X64HelperEmitter::EmitScalarVRsqrteHelper() {
dd(0xFF800000);
dd(0x7F800000);
L(LC1);
//the position of 7FC00000 here matters, this address will be indexed in handle_oddball_denormal
// the position of 7FC00000 here matters, this address will be indexed in
// handle_oddball_denormal
dd(0x7FC00000);
dd(0x5F34FD00);
@@ -1148,11 +1151,13 @@ void* X64HelperEmitter::EmitVectorVRsqrteHelper(void* scalar_helper) {
Xbyak::Label check_scalar_operation_in_vmx, actual_vector_version;
auto result_ptr =
GetBackendCtxPtr(offsetof(X64BackendContext, helper_scratch_xmms[0]));
auto counter_ptr = GetBackendCtxPtr(offsetof(X64BackendContext, helper_scratch_u64s[2]));
auto counter_ptr =
GetBackendCtxPtr(offsetof(X64BackendContext, helper_scratch_u64s[2]));
counter_ptr.setBit(64);
//shuffle and xor to check whether all lanes are equal
//sadly has to leave the float pipeline for the vptest, which is moderate yikes
// shuffle and xor to check whether all lanes are equal
// sadly has to leave the float pipeline for the vptest, which is moderate
// yikes
vmovhlps(xmm2, xmm0, xmm0);
vmovsldup(xmm1, xmm0);
vxorps(xmm1, xmm1, xmm0);
@@ -1160,7 +1165,7 @@ void* X64HelperEmitter::EmitVectorVRsqrteHelper(void* scalar_helper) {
vorps(xmm2, xmm1, xmm2);
vptest(xmm2, xmm2);
jnz(check_scalar_operation_in_vmx);
//jmp(scalar_helper, CodeGenerator::T_NEAR);
// jmp(scalar_helper, CodeGenerator::T_NEAR);
call(scalar_helper);
vshufps(xmm0, xmm0, xmm0, 0);
ret();
@@ -1169,7 +1174,7 @@ void* X64HelperEmitter::EmitVectorVRsqrteHelper(void* scalar_helper) {
vptest(xmm0, ptr[backend()->LookupXMMConstantAddress(XMMThreeFloatMask)]);
jnz(actual_vector_version);
vshufps(xmm0, xmm0,xmm0, _MM_SHUFFLE(3, 3, 3, 3));
vshufps(xmm0, xmm0, xmm0, _MM_SHUFFLE(3, 3, 3, 3));
call(scalar_helper);
// this->DebugBreak();
vinsertps(xmm0, xmm0, (3 << 4));
@@ -1189,11 +1194,11 @@ void* X64HelperEmitter::EmitVectorVRsqrteHelper(void* scalar_helper) {
L(loop);
lea(rax, result_ptr);
vmovss(xmm0, ptr[rax+rcx*4]);
vmovss(xmm0, ptr[rax + rcx * 4]);
call(scalar_helper);
mov(rcx, counter_ptr);
lea(rax, result_ptr);
vmovss(ptr[rax+rcx*4], xmm0);
vmovss(ptr[rax + rcx * 4], xmm0);
inc(ecx);
cmp(ecx, 4);
mov(counter_ptr, rcx);
@@ -1274,7 +1279,7 @@ void* X64HelperEmitter::EmitFrsqrteHelper() {
xor_(eax, 8);
sub(edx, ecx);
lea(rcx, ptr[rip + frsqrte_table2]);
movzx(eax, byte[rax+rcx]);
movzx(eax, byte[rax + rcx]);
sal(rdx, 52);
sal(rax, 44);
or_(rax, rdx);

View File

@@ -12,8 +12,8 @@
#include <memory>
#include "xenia/base/cvar.h"
#include "xenia/base/bit_map.h"
#include "xenia/base/cvar.h"
#include "xenia/cpu/backend/backend.h"
#if XE_PLATFORM_WIN32 == 1
@@ -44,9 +44,10 @@ typedef void* (*GuestToHostThunk)(void* target, void* arg0, void* arg1);
typedef void (*ResolveFunctionThunk)();
/*
place guest trampolines in the memory range that the HV normally occupies.
This way guests can call in via the indirection table and we don't have to clobber/reuse an existing memory range
The xboxkrnl range is already used by export trampolines (see kernel/kernel_module.cc)
place guest trampolines in the memory range that the HV normally occupies.
This way guests can call in via the indirection table and we don't have to
clobber/reuse an existing memory range The xboxkrnl range is already used by
export trampolines (see kernel/kernel_module.cc)
*/
static constexpr uint32_t GUEST_TRAMPOLINE_BASE = 0x80000000;
static constexpr uint32_t GUEST_TRAMPOLINE_END = 0x80040000;
@@ -75,11 +76,13 @@ struct X64BackendStackpoint {
// use
unsigned guest_return_address_;
};
enum : uint32_t {
kX64BackendMXCSRModeBit = 0,
kX64BackendHasReserveBit = 1,
kX64BackendNJMOn = 2, //non-java mode bit is currently set. for use in software fp routines
kX64BackendNonIEEEMode = 3, //non-ieee mode is currently enabled for scalar fpu.
enum : uint32_t {
kX64BackendMXCSRModeBit = 0,
kX64BackendHasReserveBit = 1,
kX64BackendNJMOn =
2, // non-java mode bit is currently set. for use in software fp routines
kX64BackendNonIEEEMode =
3, // non-ieee mode is currently enabled for scalar fpu.
};
// located prior to the ctx register
// some things it would be nice to have be per-emulator instance instead of per
@@ -170,8 +173,8 @@ class X64Backend : public Backend {
reinterpret_cast<intptr_t>(ctx) - sizeof(X64BackendContext));
}
virtual uint32_t CreateGuestTrampoline(GuestTrampolineProc proc,
void* userdata1,
void* userdata2, bool long_term) override;
void* userdata1, void* userdata2,
bool long_term) override;
virtual void FreeGuestTrampoline(uint32_t trampoline_addr) override;
virtual void SetGuestRoundingMode(void* ctx, unsigned int mode) override;
@@ -213,6 +216,7 @@ class X64Backend : public Backend {
void* vrsqrtefp_vector_helper = nullptr;
void* vrsqrtefp_scalar_helper = nullptr;
void* frsqrtefp_helper = nullptr;
private:
#if XE_X64_PROFILER_AVAILABLE == 1
GuestProfilerData profiler_data_;

View File

@@ -93,7 +93,8 @@ class X64CodeCache : public CodeCache {
// This is picked to be high enough to cover whatever we can reasonably
// expect. If we hit issues with this it probably means some corner case
// in analysis triggering.
//chrispy: raised this, some games that were compiled with low optimization levels can exceed this
// chrispy: raised this, some games that were compiled with low optimization
// levels can exceed this
static const size_t kMaximumFunctionCount = 1000000;
struct UnwindReservation {

View File

@@ -213,7 +213,8 @@ Win32X64CodeCache::RequestUnwindReservation(uint8_t* entry_address) {
if (unwind_table_count_ >= kMaximumFunctionCount) {
// we should not just be ignoring this in release if it happens
xe::FatalError(
"Unwind table count (unwind_table_count_) exceeded maximum! Please report this to "
"Unwind table count (unwind_table_count_) exceeded maximum! Please "
"report this to "
"Xenia/Canary developers");
}
#else

View File

@@ -210,24 +210,27 @@ bool X64Emitter::Emit(HIRBuilder* builder, EmitFunctionInfo& func_info) {
// Adding or changing anything here must be matched!
/*
pick a page to use as the local base as close to the commonly accessed page that contains most backend fields
the sizes that are checked are chosen based on PTE coalescing sizes. zen does 16k or 32k
pick a page to use as the local base as close to the commonly accessed page
that contains most backend fields the sizes that are checked are chosen
based on PTE coalescing sizes. zen does 16k or 32k
*/
size_t stack_size = StackLayout::GUEST_STACK_SIZE;
if (stack_offset < (4096 - sizeof(X64BackendContext))) {
locals_page_delta_ = 4096;
} else if (stack_offset < (16384 - sizeof(X64BackendContext))) {//16k PTE coalescing
} else if (stack_offset <
(16384 - sizeof(X64BackendContext))) { // 16k PTE coalescing
locals_page_delta_ = 16384;
} else if (stack_offset < (32768 - sizeof(X64BackendContext))) {
locals_page_delta_ = 32768;
} else if (stack_offset < (65536 - sizeof(X64BackendContext))) {
locals_page_delta_ = 65536;
} else {
//extremely unlikely, fall back to stack
stack_size = xe::align<size_t>(StackLayout::GUEST_STACK_SIZE + stack_offset, 16);
// extremely unlikely, fall back to stack
stack_size =
xe::align<size_t>(StackLayout::GUEST_STACK_SIZE + stack_offset, 16);
locals_page_delta_ = 0;
}
assert_true((stack_size + 8) % 16 == 0);
func_info.stack_size = stack_size;
stack_size_ = stack_size;
@@ -1002,7 +1005,7 @@ static inline vec128_t v128_setr_bytes(unsigned char v0, unsigned char v1,
}
static inline vec128_t v128_setr_words(uint32_t v0, uint32_t v1, uint32_t v2,
uint32_t v3) {
uint32_t v3) {
vec128_t result;
result.u32[0] = v0;
result.u32[1] = v1;
@@ -1181,7 +1184,7 @@ static const vec128_t xmm_consts[] = {
v128_setr_bytes(13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3, 0x80),
// XMMVSRMask
vec128b(1),
//XMMVRsqrteTableStart
// XMMVRsqrteTableStart
v128_setr_words(0x568B4FD, 0x4F3AF97, 0x48DAAA5, 0x435A618),
v128_setr_words(0x3E7A1E4, 0x3A29DFE, 0x3659A5C, 0x32E96F8),
v128_setr_words(0x2FC93CA, 0x2D090CE, 0x2A88DFE, 0x2838B57),
@@ -1190,8 +1193,8 @@ static const vec128_t xmm_consts[] = {
v128_setr_words(0x2C27279, 0x2926FB7, 0x2666D26, 0x23F6AC0),
v128_setr_words(0x21D6881, 0x1FD6665, 0x1E16468, 0x1C76287),
v128_setr_words(0x1AF60C1, 0x1995F12, 0x1855D79, 0x1735BF4),
//XMMVRsqrteTableBase
vec128i(0) //filled in later
// XMMVRsqrteTableBase
vec128i(0) // filled in later
};
void* X64Emitter::FindByteConstantOffset(unsigned bytevalue) {
@@ -1267,12 +1270,13 @@ uintptr_t X64Emitter::PlaceConstData() {
std::memcpy(mem, xmm_consts, sizeof(xmm_consts));
/*
set each 32-bit element of the constant XMMVRsqrteTableBase to be the address of the start of the constant XMMVRsqrteTableStart
this
set each 32-bit element of the constant XMMVRsqrteTableBase to be the
address of the start of the constant XMMVRsqrteTableStart this
*/
vec128_t* deferred_constants = reinterpret_cast<vec128_t*>(mem);
vec128_t* vrsqrte_table_base = &deferred_constants[XMMVRsqrteTableBase];
uint32_t ptr_to_vrsqrte_table32 = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(&deferred_constants[XMMVRsqrteTableStart]));
uint32_t ptr_to_vrsqrte_table32 = static_cast<uint32_t>(
reinterpret_cast<uintptr_t>(&deferred_constants[XMMVRsqrteTableStart]));
*vrsqrte_table_base = vec128i(ptr_to_vrsqrte_table32);
memory::Protect(mem, kConstDataSize, memory::PageAccess::kReadOnly, nullptr);
@@ -1288,8 +1292,10 @@ void X64Emitter::FreeConstData(uintptr_t data) {
Xbyak::Address X64Emitter::GetXmmConstPtr(XmmConst id) {
// Load through fixed constant table setup by PlaceConstData.
// It's important that the pointer is not signed, as it will be sign-extended.
void* emitter_data_ptr = backend_->LookupXMMConstantAddress(static_cast<unsigned>(id));
xenia_assert(reinterpret_cast<uintptr_t>(emitter_data_ptr) < (1ULL << 31));//must not have signbit set
void* emitter_data_ptr =
backend_->LookupXMMConstantAddress(static_cast<unsigned>(id));
xenia_assert(reinterpret_cast<uintptr_t>(emitter_data_ptr) <
(1ULL << 31)); // must not have signbit set
return ptr[emitter_data_ptr];
}
// Implies possible StashXmm(0, ...)!
@@ -1610,8 +1616,8 @@ SimdDomain X64Emitter::DeduceSimdDomain(const hir::Value* for_value) {
return SimdDomain::DONTCARE;
}
Xbyak::RegExp X64Emitter::GetLocalsBase() const {
return !locals_page_delta_ ? rsp : GetContextReg() - locals_page_delta_;
Xbyak::RegExp X64Emitter::GetLocalsBase() const {
return !locals_page_delta_ ? rsp : GetContextReg() - locals_page_delta_;
}
Xbyak::Address X64Emitter::GetBackendCtxPtr(int offset_in_x64backendctx) const {
/*

View File

@@ -176,7 +176,10 @@ enum XmmConst {
XMMVSRShlByteshuf,
XMMVSRMask,
XMMVRsqrteTableStart,
XMMVRsqrteTableBase = XMMVRsqrteTableStart + (32 / 4), //32 4-byte elements in table, 4 4-byte elements fit in each xmm
XMMVRsqrteTableBase =
XMMVRsqrteTableStart +
(32 /
4), // 32 4-byte elements in table, 4 4-byte elements fit in each xmm
};
using amdfx::xopcompare_e;
@@ -311,7 +314,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
size_t stack_size() const { return stack_size_; }
Xbyak::RegExp GetLocalsBase() const;
SimdDomain DeduceSimdDomain(const hir::Value* for_value);
void ForgetMxcsrMode() { mxcsr_mode_ = MXCSRMode::Unknown; }
/*
returns true if had to load mxcsr. DOT_PRODUCT can use this to skip
@@ -390,6 +393,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
void EmitGetCurrentThreadId();
void EmitTraceUserCallReturn();
static void HandleStackpointOverflowError(ppc::PPCContext* context);
protected:
Processor* processor_ = nullptr;
X64Backend* backend_ = nullptr;

View File

@@ -398,8 +398,7 @@ struct I<OPCODE, DEST, SRC1, SRC2, SRC3> : DestField<DEST> {
};
template <typename T>
XE_MAYBE_UNUSED
static const T GetTempReg(X64Emitter& e);
XE_MAYBE_UNUSED static const T GetTempReg(X64Emitter& e);
template <>
XE_MAYBE_UNUSED const Reg8 GetTempReg<Reg8>(X64Emitter& e) {
return e.al;

View File

@@ -705,7 +705,8 @@ struct STORE_LOCAL_I16
static void Emit(X64Emitter& e, const EmitArgType& i) {
// e.TraceStoreI16(DATA_LOCAL, i.src1.constant, i.src2);
if (LocalStoreMayUseMembaseLow(e, i)) {
e.mov(e.word[e.GetLocalsBase() + i.src1.constant()], e.GetMembaseReg().cvt16());
e.mov(e.word[e.GetLocalsBase() + i.src1.constant()],
e.GetMembaseReg().cvt16());
} else {
e.mov(e.word[e.GetLocalsBase() + i.src1.constant()], i.src2);
}
@@ -716,7 +717,8 @@ struct STORE_LOCAL_I32
static void Emit(X64Emitter& e, const EmitArgType& i) {
// e.TraceStoreI32(DATA_LOCAL, i.src1.constant, i.src2);
if (LocalStoreMayUseMembaseLow(e, i)) {
e.mov(e.dword[e.GetLocalsBase() + i.src1.constant()], e.GetMembaseReg().cvt32());
e.mov(e.dword[e.GetLocalsBase() + i.src1.constant()],
e.GetMembaseReg().cvt32());
} else {
e.mov(e.dword[e.GetLocalsBase() + i.src1.constant()], i.src2);
}

View File

@@ -2120,9 +2120,9 @@ struct RSQRT_V128 : Sequence<RSQRT_V128, I<OPCODE_RSQRT, V128Op, V128Op>> {
e.ChangeMxcsrMode(MXCSRMode::Vmx);
Xmm src1 = GetInputRegOrConstant(e, i.src1, e.xmm3);
/*
the vast majority of inputs to vrsqrte come from vmsum3 or vmsum4 as part
of a vector normalization sequence. in fact, its difficult to find uses of vrsqrte in titles
that have inputs which do not come from vmsum.
the vast majority of inputs to vrsqrte come from vmsum3 or vmsum4 as
part of a vector normalization sequence. in fact, its difficult to find
uses of vrsqrte in titles that have inputs which do not come from vmsum.
*/
if (i.src1.value && i.src1.value->AllFloatVectorLanesSameValue()) {
e.vmovss(e.xmm0, src1);
@@ -3193,8 +3193,7 @@ struct SET_ROUNDING_MODE_I32
if (constant_value & 4) {
e.or_(flags_ptr, 1U << kX64BackendNonIEEEMode);
}
else {
} else {
e.btr(flags_ptr, kX64BackendNonIEEEMode);
}
e.mov(e.dword[e.rsp + StackLayout::GUEST_SCRATCH], e.eax);
@@ -3202,14 +3201,14 @@ struct SET_ROUNDING_MODE_I32
e.vldmxcsr(e.dword[e.rsp + StackLayout::GUEST_SCRATCH]);
} else {
//can andnot, but this is a very infrequently used opcode
// can andnot, but this is a very infrequently used opcode
e.mov(e.eax, 1U << kX64BackendNonIEEEMode);
e.mov(e.edx, e.eax);
e.not_(e.edx);
e.mov(e.ecx, flags_ptr);
//edx = flags w/ non ieee cleared
// edx = flags w/ non ieee cleared
e.and_(e.edx, e.ecx);
//eax = flags w/ non ieee set
// eax = flags w/ non ieee set
e.or_(e.eax, e.ecx);
e.bt(i.src1, 2);

View File

@@ -122,10 +122,12 @@ class StackLayout {
*
*/
static const size_t GUEST_STACK_SIZE = 104;
//was GUEST_CTX_HOME, can't remove because that'd throw stack alignment off. instead, can be used as a temporary in sequences
// was GUEST_CTX_HOME, can't remove because that'd throw stack alignment off.
// instead, can be used as a temporary in sequences
static const size_t GUEST_SCRATCH = 0;
//when profiling is on, this stores the nanosecond time at the start of the function
// when profiling is on, this stores the nanosecond time at the start of the
// function
static const size_t GUEST_PROFILER_START = 80;
static const size_t GUEST_RET_ADDR = 88;
static const size_t GUEST_CALL_RET_ADDR = 96;

View File

@@ -29,15 +29,14 @@ namespace x64 {
bool trace_enabled = true;
#define THREAD_MATCH \
(!TARGET_THREAD || ppc_context->thread_id == TARGET_THREAD)
#define THREAD_MATCH (!TARGET_THREAD || ppc_context->thread_id == TARGET_THREAD)
#define IFLUSH()
#define IPRINT(s) \
if (trace_enabled && THREAD_MATCH) \
xe::logging::AppendLogLine(xe::LogLevel::Debug, 't', s, xe::LogSrc::Cpu)
#define DFLUSH()
#define DPRINT(...) \
if (trace_enabled && THREAD_MATCH) \
#define DPRINT(...) \
if (trace_enabled && THREAD_MATCH) \
xe::logging::AppendLogLineFormat(xe::LogSrc::Cpu, xe::LogLevel::Debug, 't', \
__VA_ARGS__)

View File

@@ -429,7 +429,7 @@ bool RegisterAllocationPass::SpillOneRegister(HIRBuilder* builder, Block* block,
// Set the local slot of the new value to our existing one. This way we will
// reuse that same memory if needed.
new_value->SetLocalSlot( spill_value->GetLocalSlot());
new_value->SetLocalSlot(spill_value->GetLocalSlot());
// Rename all future uses of the SSA value to the new value as loaded
// from the local.

View File

@@ -1372,27 +1372,27 @@ bool SimplificationPass::SimplifyVectorOps(hir::Instr* i,
}
/*
splatting a 32-bit value extracted from a vector where all 4 32-bit values are the same should be eliminated and
instead use the vector extracted from, which will be identical
have seen this happen, some games vmsum and then splat the low float to all 4 floats, even though it already is there
splatting a 32-bit value extracted from a vector where all 4 32-bit values
are the same should be eliminated and instead use the vector extracted from,
which will be identical have seen this happen, some games vmsum and then
splat the low float to all 4 floats, even though it already is there
*/
if (opc == OPCODE_SPLAT) {
if (i->dest->type == VEC128_TYPE) {
auto splatted_value = i->src1.value;
auto splat_type = splatted_value->type;
if (splat_type == FLOAT32_TYPE || splat_type == INT32_TYPE) {
//its a splat of a fourbyte value, check the definition
// its a splat of a fourbyte value, check the definition
auto splat_input_definition = splatted_value->GetDefSkipAssigns();
if (splat_input_definition) {
auto defining_opcode = splat_input_definition->GetOpcodeNum();
if (defining_opcode == OPCODE_EXTRACT) {
auto value_extracted_from = splat_input_definition->src1.value;
if (value_extracted_from->type == VEC128_TYPE) {
xenia_assert(splat_input_definition->dest->type == splat_type);
if (value_extracted_from->AllFloatVectorLanesSameValue()) {
i->Replace(&OPCODE_ASSIGN_info,0);
i->Replace(&OPCODE_ASSIGN_info, 0);
i->set_src1(value_extracted_from);
return true;
}

View File

@@ -36,7 +36,7 @@ class SimplificationPass : public ConditionalGroupSubpass {
// handles simple multiplication/addition rules
bool SimplifyBasicArith(hir::HIRBuilder* builder);
bool SimplifyVectorOps(hir::HIRBuilder* builder);
bool SimplifyVectorOps(hir::HIRBuilder* builder);
bool SimplifyVectorOps(hir::Instr* i, hir::HIRBuilder* builder);
bool SimplifyBasicArith(hir::Instr* i, hir::HIRBuilder* builder);
bool SimplifyAddWithSHL(hir::Instr* i, hir::HIRBuilder* builder);

View File

@@ -49,7 +49,7 @@ class EntryTable {
xe::global_critical_region global_critical_region_;
// TODO(benvanik): replace with a better data structure.
xe::split_map<uint32_t, Entry*> map_;
//std::unordered_map<uint32_t, Entry*> map_;
// std::unordered_map<uint32_t, Entry*> map_;
};
} // namespace cpu

View File

@@ -95,7 +95,6 @@ class Export {
uint32_t variable_ptr;
struct {
// Trampoline that is called from the guest-to-host thunk.
// Expects only PPC context as first arg.
ExportTrampoline trampoline;

View File

@@ -115,7 +115,6 @@ uintptr_t GuestFunction::MapGuestAddressToMachineCode(
return reinterpret_cast<uintptr_t>(machine_code()) + entry->code_offset;
} else {
return 0;
}
}

View File

@@ -79,10 +79,11 @@ class Instr {
void MoveBefore(Instr* other);
void Replace(const OpcodeInfo* new_opcode, uint16_t new_flags);
void UnlinkAndNOP();
//chrispy: wanted to change this one to Remove, but i changed Remove's name to UnlinkAndNOP,
//so if changes happened in master that we wanted to port over, and those changes used Remove, then we would have a lot of issues that the cause of would
//be difficult to track
//^todo: rework this comment, im frazzled
// chrispy: wanted to change this one to Remove, but i changed Remove's name
// to UnlinkAndNOP, so if changes happened in master that we wanted to port
// over, and those changes used Remove, then we would have a lot of issues
// that the cause of would be difficult to track ^todo: rework this comment,
// im frazzled
void Deallocate();
const OpcodeInfo* GetOpcodeInfo() const { return opcode; }
// if opcode is null, we have bigger problems

View File

@@ -30,9 +30,7 @@ class Label {
// this will later be used as an input to xbyak. xbyak only accepts
// std::string as a value, not passed by reference, so precomputing the
// stringification does not help
std::string GetIdString() {
return std::to_string(id);
}
std::string GetIdString() { return std::to_string(id); }
};
} // namespace hir

View File

@@ -43,7 +43,7 @@ void Value::RemoveUse(Use* use) {
use->next->prev = use->prev;
}
//HIRBuilder::GetCurrent()->DeallocateUse(use);
// HIRBuilder::GetCurrent()->DeallocateUse(use);
}
uint32_t Value::AsUint32() {
@@ -1805,7 +1805,7 @@ bool Value::AllUsesByOneInsn() const {
return true;
}
bool Value::AllFloatVectorLanesSameValue(const hir::Value* for_value,
uint32_t current_depth) {
uint32_t current_depth) {
// limit recursion, otherwise this function will slow down emission
if (current_depth == 16) {
return false;
@@ -1819,7 +1819,8 @@ re_enter:
xenia_assert(for_value->IsConstant());
auto&& constant_value = for_value->constant.v128;
for (unsigned constant_lane_index = 1; constant_lane_index < 4; ++constant_lane_index) {
for (unsigned constant_lane_index = 1; constant_lane_index < 4;
++constant_lane_index) {
if (constant_value.u32[0] != constant_value.u32[constant_lane_index]) {
return false;
}
@@ -1844,9 +1845,10 @@ re_enter:
definition_opcode_number == OPCODE_DOT_PRODUCT_3) {
return true;
}
//if splat of 32-bit value type, return true
//technically a splat of int16 or int8 would also produce the same "float" in all lanes
//but i think its best to keep this function focused on specifically float data
// if splat of 32-bit value type, return true
// technically a splat of int16 or int8 would also produce the same "float" in
// all lanes but i think its best to keep this function focused on
// specifically float data
if (definition_opcode_number == OPCODE_SPLAT) {
if (definition->dest->type == VEC128_TYPE) {
auto splat_src_value_type = definition->src1.value->type;
@@ -1857,33 +1859,32 @@ re_enter:
}
}
switch (definition_opcode_number) {
//all of these opcodes produce the same value for the same input
case OPCODE_RSQRT:
case OPCODE_RECIP:
case OPCODE_POW2:
case OPCODE_LOG2:
switch (definition_opcode_number) {
// all of these opcodes produce the same value for the same input
case OPCODE_RSQRT:
case OPCODE_RECIP:
case OPCODE_POW2:
case OPCODE_LOG2:
for_value = definition->src1.value;
goto re_enter;
//binary opcodes
case OPCODE_ADD:
case OPCODE_SUB:
case OPCODE_MUL:
// binary opcodes
case OPCODE_ADD:
case OPCODE_SUB:
case OPCODE_MUL:
if (!AllFloatVectorLanesSameValue(definition->src1.value,
current_depth + 1)) {
return false;
}
for_value = definition->src2.value;
goto re_enter;
default:
default:
break;
}
return false;
}
} // namespace hir
} // namespace cpu
} // namespace xe

View File

@@ -621,6 +621,7 @@ class Value {
bool AllFloatVectorLanesSameValue() const {
return Value::AllFloatVectorLanesSameValue(this);
}
private:
/*
returns true if for_value (which must be VEC128_TYPE) has the same value in

View File

@@ -48,7 +48,9 @@ class MMIOHandler {
typedef uint32_t (*HostToGuestVirtual)(const void* context,
const void* host_address);
typedef bool (*AccessViolationCallback)(
global_unique_lock_type global_lock_locked_once, //not passed by reference with const like the others?
global_unique_lock_type
global_lock_locked_once, // not passed by reference with const like
// the others?
void* context, void* host_address, bool is_write);
// access_violation_callback is called with global_critical_region locked once

View File

@@ -55,6 +55,7 @@ class Module {
bool ReadMap(const char* file_name);
virtual void Precompile() {}
protected:
virtual std::unique_ptr<Function> CreateFunction(uint32_t address) = 0;

View File

@@ -375,11 +375,11 @@ typedef struct alignas(64) PPCContext_s {
// Most frequently used registers first.
uint64_t r[32]; // 0x20 General purpose registers
uint64_t ctr; // 0x18 Count register
uint64_t lr; // 0x10 Link register
uint64_t r[32]; // 0x20 General purpose registers
uint64_t ctr; // 0x18 Count register
uint64_t lr; // 0x10 Link register
uint64_t msr; //machine state register
uint64_t msr; // machine state register
double f[32]; // 0x120 Floating-point registers
vec128_t v[128]; // 0x220 VMX128 vector registers

View File

@@ -46,7 +46,7 @@ struct PPCDecodeData {
uint32_t LEV() const { return bits_.LEV; }
private:
XE_MAYBE_UNUSED
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;

View File

@@ -132,23 +132,23 @@ int InstrEmit_branch(PPCHIRBuilder& f, const char* src, uint64_t cia,
#else
{
#endif
// Jump to pointer.
bool likely_return = !lk && nia_is_lr;
if (likely_return) {
call_flags |= CALL_POSSIBLE_RETURN;
}
if (cond) {
if (!expect_true) {
cond = f.IsFalse(cond);
// Jump to pointer.
bool likely_return = !lk && nia_is_lr;
if (likely_return) {
call_flags |= CALL_POSSIBLE_RETURN;
}
if (cond) {
if (!expect_true) {
cond = f.IsFalse(cond);
}
f.CallIndirectTrue(cond, nia, call_flags);
} else {
f.CallIndirect(nia, call_flags);
}
f.CallIndirectTrue(cond, nia, call_flags);
} else {
f.CallIndirect(nia, call_flags);
}
}
}
return 0;
return 0;
} // namespace ppc
int InstrEmit_bx(PPCHIRBuilder& f, const InstrData& i) {
@@ -789,9 +789,8 @@ int InstrEmit_mtspr(PPCHIRBuilder& f, const InstrData& i) {
// code requires it. Sequences of mtmsr/lwar/stcw/mtmsr come up a lot, and
// without the lock here threads can livelock.
//0x400 = debug singlestep i think
//ive seen 0x8000 used in kernel code
// 0x400 = debug singlestep i think
// ive seen 0x8000 used in kernel code
int InstrEmit_mfmsr(PPCHIRBuilder& f, const InstrData& i) {
// bit 48 = EE; interrupt enabled
// bit 62 = RI; recoverable interrupt
@@ -806,7 +805,7 @@ int InstrEmit_mtmsr(PPCHIRBuilder& f, const InstrData& i) {
}
int InstrEmit_mtmsrd(PPCHIRBuilder& f, const InstrData& i) {
//todo: this is moving msr under a mask, so only writing EE and RI
// todo: this is moving msr under a mask, so only writing EE and RI
Value* from = f.LoadGPR(i.X.RT);
Value* mtmsrd_mask = f.LoadConstantUint64((1ULL << 15));

View File

@@ -106,16 +106,17 @@ bool PPCFrontend::Initialize() {
}
bool PPCFrontend::DeclareFunction(GuestFunction* function) {
//chrispy: make sure we aren't declaring a function that is actually padding data, this will mess up PPCScanner and is hard to debug
//wow, this halo reach actually has branches into 0 opcodes, look into further
//xenia_assert(*reinterpret_cast<const uint32_t*>(
// this->memory()->TranslateVirtual(function->address())) != 0);
// Could scan or something here.
// Could also check to see if it's a well-known function type and classify
// for later.
// Could also kick off a precompiler, since we know it's likely the function
// will be demanded soon.
// chrispy: make sure we aren't declaring a function that is actually padding
// data, this will mess up PPCScanner and is hard to debug wow, this halo
// reach actually has branches into 0 opcodes, look into further
// xenia_assert(*reinterpret_cast<const uint32_t*>(
// this->memory()->TranslateVirtual(function->address())) !=
// 0);
// Could scan or something here.
// Could also check to see if it's a well-known function type and classify
// for later.
// Could also kick off a precompiler, since we know it's likely the function
// will be demanded soon.
return true;
}

View File

@@ -80,8 +80,10 @@ class PPCHIRBuilder : public hir::HIRBuilder {
void StoreReserved(Value* val);
Value* LoadReserved();
//calls original impl in hirbuilder, but also records the is_return_site bit into flags in the guestmodule
// calls original impl in hirbuilder, but also records the is_return_site bit
// into flags in the guestmodule
void SetReturnAddress(Value* value);
private:
void MaybeBreakOnInstruction(uint32_t address);
void AnnotateLabel(uint32_t address, Label* label);

View File

@@ -267,7 +267,7 @@ Function* Processor::ResolveFunction(uint32_t address) {
entry->status = Entry::STATUS_FAILED;
return nullptr;
}
//only add it to the list of resolved functions if resolving succeeded
// only add it to the list of resolved functions if resolving succeeded
auto module_for = function->module();
auto xexmod = dynamic_cast<XexModule*>(module_for);
@@ -1300,7 +1300,7 @@ uint32_t Processor::GuestAtomicIncrement32(ppc::PPCContext* context,
result = *host_address;
// todo: should call a processor->backend function that acquires a
// reservation instead of using host atomics
if (xe::atomic_cas(result, xe::byte_swap(xe::byte_swap(result)+1),
if (xe::atomic_cas(result, xe::byte_swap(xe::byte_swap(result) + 1),
host_address)) {
break;
}
@@ -1316,7 +1316,7 @@ uint32_t Processor::GuestAtomicDecrement32(ppc::PPCContext* context,
result = *host_address;
// todo: should call a processor->backend function that acquires a
// reservation instead of using host atomics
if (xe::atomic_cas(result,xe::byte_swap( xe::byte_swap(result)-1),
if (xe::atomic_cas(result, xe::byte_swap(xe::byte_swap(result) - 1),
host_address)) {
break;
}
@@ -1326,9 +1326,9 @@ uint32_t Processor::GuestAtomicDecrement32(ppc::PPCContext* context,
uint32_t Processor::GuestAtomicOr32(ppc::PPCContext* context,
uint32_t guest_address, uint32_t mask) {
return xe::byte_swap(xe::atomic_or(
context->TranslateVirtual<volatile int32_t*>(guest_address),
xe::byte_swap(mask)));
return xe::byte_swap(
xe::atomic_or(context->TranslateVirtual<volatile int32_t*>(guest_address),
xe::byte_swap(mask)));
}
uint32_t Processor::GuestAtomicXor32(ppc::PPCContext* context,
uint32_t guest_address, uint32_t mask) {

View File

@@ -189,11 +189,11 @@ class Processor {
uint32_t GuestAtomicDecrement32(ppc::PPCContext* context,
uint32_t guest_address);
uint32_t GuestAtomicOr32(ppc::PPCContext* context, uint32_t guest_address,
uint32_t mask);
uint32_t mask);
uint32_t GuestAtomicXor32(ppc::PPCContext* context, uint32_t guest_address,
uint32_t mask);
uint32_t mask);
uint32_t GuestAtomicAnd32(ppc::PPCContext* context, uint32_t guest_address,
uint32_t mask);
uint32_t mask);
bool GuestAtomicCAS32(ppc::PPCContext* context, uint32_t old_value,
uint32_t new_value, uint32_t guest_address);

View File

@@ -77,8 +77,7 @@ ThreadState::ThreadState(Processor* processor, uint32_t thread_id,
// Allocate with 64b alignment.
context_ = reinterpret_cast<ppc::PPCContext*>(
AllocateContext());
context_ = reinterpret_cast<ppc::PPCContext*>(AllocateContext());
processor->backend()->InitializeBackendContext(context_);
assert_true(((uint64_t)context_ & 0x3F) == 0);
std::memset(context_, 0, sizeof(ppc::PPCContext));
@@ -97,9 +96,11 @@ ThreadState::ThreadState(Processor* processor, uint32_t thread_id,
// fixme: VSCR must be set here!
context_->msr = 0x9030; // dumped from a real 360, 0x8000
//this register can be used for arbitrary data according to the PPC docs
//but the suggested use is to mark which vector registers are in use, for faster save/restore
//it seems unlikely anything uses this, especially since we have way more than 32 vrs, but setting it to all ones seems closer to correct than 0
// this register can be used for arbitrary data according to the PPC docs
// but the suggested use is to mark which vector registers are in use, for
// faster save/restore it seems unlikely anything uses this, especially since
// we have way more than 32 vrs, but setting it to all ones seems closer to
// correct than 0
context_->vrsave = ~0u;
}