Minor decoder optimizations, kernel fixes, cpu backend fixes

This commit is contained in:
chss95cs@gmail.com
2022-11-05 10:50:33 -07:00
parent ba66373d8c
commit c1d922eebf
62 changed files with 1254 additions and 802 deletions

View File

@@ -425,6 +425,27 @@ typedef struct alignas(64) PPCContext_s {
uint64_t reserved_val;
ThreadState* thread_state;
uint8_t* virtual_membase;
template <typename T = uint8_t*>
inline T TranslateVirtual(uint32_t guest_address) XE_RESTRICT const {
#if XE_PLATFORM_WIN32 == 1
uint8_t* host_address = virtual_membase + guest_address;
if (guest_address >= static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this))) {
host_address += 0x1000;
}
return reinterpret_cast<T>(host_address);
#else
return processor->memory()->TranslateVirtual<T>(guest_address);
#endif
}
//for convenience in kernel functions, version that auto narrows to uint32
template <typename T = uint8_t*>
inline T TranslateVirtualGPR(uint64_t guest_address) XE_RESTRICT const {
return TranslateVirtual<T>(static_cast<uint32_t>(guest_address));
}
static std::string GetRegisterName(PPCRegister reg);
std::string GetStringFromValue(PPCRegister reg) const;
void SetValueFromString(PPCRegister reg, std::string value);

View File

@@ -46,6 +46,7 @@ struct PPCDecodeData {
uint32_t LEV() const { return bits_.LEV; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -74,6 +75,7 @@ struct PPCDecodeData {
uint32_t L() const { return bits_.RT & 0x1; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -95,6 +97,7 @@ struct PPCDecodeData {
int32_t ds() const { return static_cast<int32_t>(XEEXTS16(DS() << 2)); }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -174,6 +177,7 @@ struct PPCDecodeData {
uint32_t CRFS() const { return bits_.RA >> 2; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -200,6 +204,7 @@ struct PPCDecodeData {
uint32_t CRFS() const { return CRBA() >> 2; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -223,6 +228,7 @@ struct PPCDecodeData {
}
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -244,6 +250,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -266,6 +273,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -289,6 +297,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -314,6 +323,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -339,6 +349,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -363,6 +374,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -389,6 +401,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -412,6 +425,7 @@ struct PPCDecodeData {
int32_t SIMM() const { return static_cast<int32_t>(XEEXTS16(VA())); }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -431,6 +445,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -452,6 +467,7 @@ struct PPCDecodeData {
uint32_t SHB() const { return VC() & 0xF; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -473,6 +489,7 @@ struct PPCDecodeData {
uint32_t VB() const { return bits_.VB128l | (bits_.VB128h << 5); }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -498,6 +515,7 @@ struct PPCDecodeData {
uint32_t RB() const { return bits_.RB; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -521,6 +539,7 @@ struct PPCDecodeData {
uint32_t VC() const { return bits_.VC; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -546,6 +565,7 @@ struct PPCDecodeData {
int32_t SIMM() const { return static_cast<int32_t>(XEEXTS16(bits_.UIMM)); }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -567,6 +587,7 @@ struct PPCDecodeData {
uint32_t z() const { return bits_.z; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -592,6 +613,7 @@ struct PPCDecodeData {
uint32_t SH() const { return bits_.SH; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -618,6 +640,7 @@ struct PPCDecodeData {
bool Rc() const { return bits_.Rc ? true : false; }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;
@@ -642,6 +665,7 @@ struct PPCDecodeData {
uint32_t UIMM() const { return bits_.PERMl | (bits_.PERMh << 5); }
private:
XE_MAYBE_UNUSED
uint32_t address_;
union {
uint32_t value_;

View File

@@ -2014,8 +2014,7 @@ int InstrEmit_vupkhsh(PPCHIRBuilder& f, const InstrData& i) {
return InstrEmit_vupkhsh_(f, i.VX.VD, i.VX.VB);
}
int InstrEmit_vupkhsh128(PPCHIRBuilder& f, const InstrData& i) {
uint32_t va = VX128_VA128;
assert_zero(va);
assert_zero(VX128_VA128);
return InstrEmit_vupkhsh_(f, VX128_VD128, VX128_VB128);
}
@@ -2032,8 +2031,7 @@ int InstrEmit_vupklsh(PPCHIRBuilder& f, const InstrData& i) {
return InstrEmit_vupklsh_(f, i.VX.VD, i.VX.VB);
}
int InstrEmit_vupklsh128(PPCHIRBuilder& f, const InstrData& i) {
uint32_t va = VX128_VA128;
assert_zero(va);
assert_zero(VX128_VA128);
return InstrEmit_vupklsh_(f, VX128_VD128, VX128_VB128);
}

View File

@@ -16,7 +16,7 @@
#include "xenia/cpu/ppc/ppc_hir_builder.h"
DEFINE_bool(
disable_prefetch_and_cachecontrol, false,
disable_prefetch_and_cachecontrol, true,
"Disables translating ppc prefetch/cache flush instructions to host "
"prefetch/cacheflush instructions. This may improve performance as these "
"instructions were written with the Xbox 360's cache in mind, and modern "

View File

@@ -105,6 +105,11 @@ 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.

View File

@@ -34,6 +34,11 @@ DEFINE_bool(
"unimplemented PowerPC instruction is encountered.",
"CPU");
DEFINE_bool(
emit_useless_fpscr_updates, false,
"Emit useless fpscr update instructions (pre-10/30/2022 behavior). ",
"CPU");
namespace xe {
namespace cpu {
namespace ppc {
@@ -89,6 +94,9 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
function_ = function;
start_address_ = function_->address();
//chrispy: i've seen this one happen, not sure why but i think from trying to precompile twice
//i've also seen ones with a start and end address that are the same...
assert_true(function_->address() <= function_->end_address());
instr_count_ = (function_->end_address() - function_->address()) / 4 + 1;
with_debug_info_ = (flags & EMIT_DEBUG_COMMENTS) == EMIT_DEBUG_COMMENTS;
@@ -242,6 +250,7 @@ void PPCHIRBuilder::MaybeBreakOnInstruction(uint32_t address) {
}
void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) {
//chrispy: label->name is unused, it would be nice to be able to remove the field and this code
char name_buffer[13];
auto format_result = fmt::format_to_n(name_buffer, 12, "loc_{:08X}", address);
name_buffer[format_result.size] = '\0';
@@ -447,31 +456,38 @@ void PPCHIRBuilder::StoreFPSCR(Value* value) {
void PPCHIRBuilder::UpdateFPSCR(Value* result, bool update_cr1) {
// TODO(benvanik): detect overflow and nan cases.
// fx and vx are the most important.
Value* fx = LoadConstantInt8(0);
Value* fex = LoadConstantInt8(0);
Value* vx = LoadConstantInt8(0);
Value* ox = LoadConstantInt8(0);
/*
chrispy: stubbed this out because right now all it does is waste
memory and CPU time
*/
if (cvars::emit_useless_fpscr_updates) {
Value* fx = LoadConstantInt8(0);
Value* fex = LoadConstantInt8(0);
Value* vx = LoadConstantInt8(0);
Value* ox = LoadConstantInt8(0);
if (update_cr1) {
// Store into the CR1 field.
// We do this instead of just calling CopyFPSCRToCR1 so that we don't
// have to read back the bits and do shifting work.
StoreContext(offsetof(PPCContext, cr1.cr1_fx), fx);
StoreContext(offsetof(PPCContext, cr1.cr1_fex), fex);
StoreContext(offsetof(PPCContext, cr1.cr1_vx), vx);
StoreContext(offsetof(PPCContext, cr1.cr1_ox), ox);
if (update_cr1) {
// Store into the CR1 field.
// We do this instead of just calling CopyFPSCRToCR1 so that we don't
// have to read back the bits and do shifting work.
StoreContext(offsetof(PPCContext, cr1.cr1_fx), fx);
StoreContext(offsetof(PPCContext, cr1.cr1_fex), fex);
StoreContext(offsetof(PPCContext, cr1.cr1_vx), vx);
StoreContext(offsetof(PPCContext, cr1.cr1_ox), ox);
}
// Generate our new bits.
Value* new_bits = Shl(ZeroExtend(fx, INT32_TYPE), 31);
new_bits = Or(new_bits, Shl(ZeroExtend(fex, INT32_TYPE), 30));
new_bits = Or(new_bits, Shl(ZeroExtend(vx, INT32_TYPE), 29));
new_bits = Or(new_bits, Shl(ZeroExtend(ox, INT32_TYPE), 28));
// Mix into fpscr while preserving sticky bits (FX and OX).
Value* bits = LoadFPSCR();
bits = Or(And(bits, LoadConstantUint32(0x9FFFFFFF)), new_bits);
StoreFPSCR(bits);
}
// Generate our new bits.
Value* new_bits = Shl(ZeroExtend(fx, INT32_TYPE), 31);
new_bits = Or(new_bits, Shl(ZeroExtend(fex, INT32_TYPE), 30));
new_bits = Or(new_bits, Shl(ZeroExtend(vx, INT32_TYPE), 29));
new_bits = Or(new_bits, Shl(ZeroExtend(ox, INT32_TYPE), 28));
// Mix into fpscr while preserving sticky bits (FX and OX).
Value* bits = LoadFPSCR();
bits = Or(And(bits, LoadConstantUint32(0x9FFFFFFF)), new_bits);
StoreFPSCR(bits);
}
void PPCHIRBuilder::CopyFPSCRToCR1() {

View File

@@ -21,13 +21,7 @@ namespace xe {
namespace cpu {
namespace ppc {
// DEPRECATED
// TODO(benvanik): move code to PPCDecodeData.
struct InstrData {
PPCOpcode opcode;
const PPCOpcodeInfo* opcode_info;
uint32_t address;
struct PPCOpcodeBits {
union {
uint32_t code;
@@ -329,6 +323,14 @@ struct InstrData {
};
};
// DEPRECATED
// TODO(benvanik): move code to PPCDecodeData.
struct InstrData : public PPCOpcodeBits {
PPCOpcode opcode;
const PPCOpcodeInfo* opcode_info;
uint32_t address;
};
} // namespace ppc
} // namespace cpu
} // namespace xe