use much faster exp2/cos approximations in ffmpeg, large decrease in cpu usage on my machine on decoder thread
properly byteswap r13 for spinlock Add PPCOpcodeBits stub out broken fpscr updating in ppc_hir_builder. it's just code that repeatedly does nothing right now. add note about 0 opcode bytes being executed to ppc_frontend Add assert to check that function end is greater than function start, can happen with malformed functions Disable prefetch and cachecontrol by default, automatic hardware prefetchers already do the job for the most part minor cleanup in simplification_pass, dont loop optimizations, let the pass manager do it for us Add experimental "delay_via_maybeyield" cvar, which uses MaybeYield to "emulate" the db16cyc instruction Add much faster/simpler way of directly calling guest functions, no longer have to do a byte by byte search through the generated code Generate label string ids on the fly Fix unused function warnings for prefetch on clang, fix many other clang warnings Eliminated majority of CallNativeSafes by replacing them with naive generic code paths. ^ Vector rotate left, vector shift left, vector shift right, vector shift arithmetic right, and vector average are included These naive paths are implemented small loops that stash the two inputs to the stack and load them in gprs from there, they are not particularly fast but should be an order of magnitude faster than callnativesafe to a host function, which would involve a call, stashing all volatile registers, an indirect call, potentially setting up a stack frame for the arrays that the inputs get stashed to, the actual operations, a return, loading all volatile registers, a return, etc Added the fast SHR_V128 path back in Implement signed vector average byte, signed vector average word. previously we were emitting no code for them. signed vector average byte appears in many games Fix bug with signed vector average 32, we were doing unsigned shift, turning negative values into big positive ones potentially
This commit is contained in:
@@ -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 "
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user