Merge pull request #61 from chrisps/canary_experimental

performance improvements, kernel fixes, cpu accuracy improvements
This commit is contained in:
Radosław Gliński
2022-08-21 09:31:09 +02:00
committed by GitHub
70 changed files with 1744 additions and 541 deletions

View File

@@ -14,8 +14,8 @@
#include <mutex>
#include <string>
#include "xenia/base/mutex.h"
#include "xenia/base/vec128.h"
namespace xe {
namespace cpu {
class Processor;
@@ -390,9 +390,11 @@ typedef struct alignas(64) PPCContext_s {
// These are split to make it easier to do DCE on unused stores.
uint64_t cr() const;
void set_cr(uint64_t value);
// todo: remove, saturation should be represented by a vector
uint8_t vscr_sat;
uint32_t vrsave;
// uint32_t get_fprf() {
// return fpscr.value & 0x000F8000;
// }
@@ -405,7 +407,7 @@ typedef struct alignas(64) PPCContext_s {
// Global interrupt lock, held while interrupts are disabled or interrupts are
// executing. This is shared among all threads and comes from the processor.
std::recursive_mutex* global_mutex;
global_mutex_type* global_mutex;
// Used to shuttle data into externs. Contents volatile.
uint64_t scratch;

View File

@@ -1197,7 +1197,7 @@ int InstrEmit_vnmsubfp_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb,
Value* b = f.VectorDenormFlush(f.LoadVR(vb));
Value* c = f.VectorDenormFlush(f.LoadVR(vc));
Value* v = f.Neg(f.MulSub(a, c, b));
Value* v = f.NegatedMulSub(a, c, b);
f.StoreVR(vd, v);
return 0;
}

View File

@@ -16,6 +16,12 @@
#include "xenia/cpu/ppc/ppc_hir_builder.h"
#include <stddef.h>
// chrispy: added this, we can have simpler control flow and do dce on the
// inputs
DEFINE_bool(ignore_trap_instructions, true,
"Generate no code for powerpc trap instructions, can result in "
"better performance in games that aggressively check with trap.",
"CPU");
namespace xe {
namespace cpu {
@@ -449,6 +455,9 @@ constexpr uint32_t TRAP_SLT = 1 << 4, TRAP_SGT = 1 << 3, TRAP_EQ = 1 << 2,
int InstrEmit_trap(PPCHIRBuilder& f, const InstrData& i, Value* va, Value* vb,
uint32_t TO) {
if (cvars::ignore_trap_instructions) {
return 0;
}
// if (a < b) & TO[0] then TRAP
// if (a > b) & TO[1] then TRAP
// if (a = b) & TO[2] then TRAP
@@ -521,6 +530,9 @@ int InstrEmit_trap(PPCHIRBuilder& f, const InstrData& i, Value* va, Value* vb,
}
int InstrEmit_td(PPCHIRBuilder& f, const InstrData& i) {
if (cvars::ignore_trap_instructions) {
return 0;
}
// a <- (RA)
// b <- (RB)
// if (a < b) & TO[0] then TRAP
@@ -534,6 +546,9 @@ int InstrEmit_td(PPCHIRBuilder& f, const InstrData& i) {
}
int InstrEmit_tdi(PPCHIRBuilder& f, const InstrData& i) {
if (cvars::ignore_trap_instructions) {
return 0;
}
// a <- (RA)
// if (a < EXTS(SI)) & TO[0] then TRAP
// if (a > EXTS(SI)) & TO[1] then TRAP
@@ -546,6 +561,9 @@ int InstrEmit_tdi(PPCHIRBuilder& f, const InstrData& i) {
}
int InstrEmit_tw(PPCHIRBuilder& f, const InstrData& i) {
if (cvars::ignore_trap_instructions) {
return 0;
}
// a <- EXTS((RA)[32:63])
// b <- EXTS((RB)[32:63])
// if (a < b) & TO[0] then TRAP
@@ -561,6 +579,9 @@ int InstrEmit_tw(PPCHIRBuilder& f, const InstrData& i) {
}
int InstrEmit_twi(PPCHIRBuilder& f, const InstrData& i) {
if (cvars::ignore_trap_instructions) {
return 0;
}
// a <- EXTS((RA)[32:63])
// if (a < EXTS(SI)) & TO[0] then TRAP
// if (a > EXTS(SI)) & TO[1] then TRAP
@@ -645,7 +666,9 @@ int InstrEmit_mfspr(PPCHIRBuilder& f, const InstrData& i) {
break;
case 256:
// VRSAVE
v = f.LoadZeroInt64();
v = f.ZeroExtend(f.LoadContext(offsetof(PPCContext, vrsave), INT32_TYPE),
INT64_TYPE);
break;
case 268:
// TB
@@ -749,6 +772,8 @@ int InstrEmit_mtspr(PPCHIRBuilder& f, const InstrData& i) {
f.StoreCTR(rt);
break;
case 256:
f.StoreContext(offsetof(PPCContext, vrsave), f.Truncate(rt, INT32_TYPE));
// VRSAVE
break;
default:
@@ -768,6 +793,7 @@ int InstrEmit_mfmsr(PPCHIRBuilder& f, const InstrData& i) {
// bit 48 = EE; interrupt enabled
// bit 62 = RI; recoverable interrupt
// return 8000h if unlocked (interrupts enabled), else 0
#if 0
f.MemoryBarrier();
if (cvars::disable_global_lock || true) {
f.StoreGPR(i.X.RT, f.LoadConstantUint64(0));
@@ -777,63 +803,23 @@ int InstrEmit_mfmsr(PPCHIRBuilder& f, const InstrData& i) {
f.StoreGPR(i.X.RT,
f.LoadContext(offsetof(PPCContext, scratch), INT64_TYPE));
}
#else
f.StoreGPR(i.X.RT, f.LoadConstantUint64(0));
#endif
return 0;
}
int InstrEmit_mtmsr(PPCHIRBuilder& f, const InstrData& i) {
if (i.X.RA & 0x01) {
// L = 1
// iff storing from r13
f.MemoryBarrier();
f.StoreContext(
offsetof(PPCContext, scratch),
f.ZeroExtend(f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE), INT64_TYPE));
#if 0
if (i.X.RT == 13) {
// iff storing from r13 we are taking a lock (disable interrupts).
if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->enter_global_lock);
}
} else {
// Otherwise we are restoring interrupts (probably).
if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->leave_global_lock);
}
}
#endif
return 0;
} else {
// L = 0
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.StoreContext(
offsetof(PPCContext, scratch),
f.ZeroExtend(f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE), INT64_TYPE));
return 0;
}
int InstrEmit_mtmsrd(PPCHIRBuilder& f, const InstrData& i) {
if (i.X.RA & 0x01) {
// L = 1
f.MemoryBarrier();
f.StoreContext(offsetof(PPCContext, scratch),
f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE));
#if 0
if (i.X.RT == 13) {
// iff storing from r13 we are taking a lock (disable interrupts).
if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->enter_global_lock);
}
} else {
// Otherwise we are restoring interrupts (probably).
if (!cvars::disable_global_lock) {
f.CallExtern(f.builtins()->leave_global_lock);
}
}
#endif
return 0;
} else {
// L = 0
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.StoreContext(offsetof(PPCContext, scratch),
f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE));
return 0;
}
void RegisterEmitCategoryControl() {

View File

@@ -195,8 +195,8 @@ int InstrEmit_fmsubsx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fnmaddx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] + frB)
Value* v = f.Neg(
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* v = f.NegatedMulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC),
f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc);
return 0;
@@ -204,8 +204,8 @@ int InstrEmit_fnmaddx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fnmaddsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] + frB)
Value* v = f.Neg(
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* v = f.NegatedMulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC),
f.LoadFPR(i.A.FRB));
v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc);
@@ -214,8 +214,8 @@ int InstrEmit_fnmaddsx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fnmsubx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] - frB)
Value* v = f.Neg(
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* v = f.NegatedMulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC),
f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc);
return 0;
@@ -223,8 +223,8 @@ int InstrEmit_fnmsubx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fnmsubsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] - frB)
Value* v = f.Neg(
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* v = f.NegatedMulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC),
f.LoadFPR(i.A.FRB));
v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc);

View File

@@ -834,6 +834,7 @@ int InstrEmit_stdcx(PPCHIRBuilder& f, const InstrData& i) {
// Issue memory barrier for when we go out of lock and want others to see our
// updates.
f.MemoryBarrier();
return 0;