mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Merge pull request #842 from lioncash/jit
Coding style clean up for the Jit, JitARM and JitIL
This commit is contained in:
@@ -162,7 +162,9 @@ void Jit64::Init()
|
||||
jo.enableBlocklink = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
jo.enableBlocklink = !Core::g_CoreStartupParameter.bMMU;
|
||||
}
|
||||
}
|
||||
jo.fpAccurateFcmp = Core::g_CoreStartupParameter.bEnableFPRF;
|
||||
jo.optimizeGatherPipe = true;
|
||||
@@ -435,7 +437,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
ABI_CallFunction((void *)&ImHere); //Used to get a trace of the last few blocks before a crash, sometimes VERY useful
|
||||
|
||||
// Conditionally add profiling code.
|
||||
if (Profiler::g_ProfileBlocks) {
|
||||
if (Profiler::g_ProfileBlocks)
|
||||
{
|
||||
ADD(32, M(&b->runCount), Imm8(1));
|
||||
#ifdef _WIN32
|
||||
b->ticCounter = 0;
|
||||
@@ -617,7 +620,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
//NOTICE_LOG(DYNA_REC, "Unflushed register: %s", ppc_inst.c_str());
|
||||
}
|
||||
#endif
|
||||
if (js.skipnext) {
|
||||
if (js.skipnext)
|
||||
{
|
||||
js.skipnext = false;
|
||||
i++; // Skip next instruction
|
||||
}
|
||||
|
||||
@@ -68,18 +68,22 @@ public:
|
||||
|
||||
void ClearCache() override;
|
||||
|
||||
const u8 *GetDispatcher() {
|
||||
const u8 *GetDispatcher()
|
||||
{
|
||||
return asm_routines.dispatcher;
|
||||
}
|
||||
const CommonAsmRoutines *GetAsmRoutines() override {
|
||||
|
||||
const CommonAsmRoutines *GetAsmRoutines() override
|
||||
{
|
||||
return &asm_routines;
|
||||
}
|
||||
|
||||
const char *GetName() override {
|
||||
const char *GetName() override
|
||||
{
|
||||
return "JIT64";
|
||||
}
|
||||
// Run!
|
||||
|
||||
// Run!
|
||||
void Run() override;
|
||||
void SingleStep() override;
|
||||
|
||||
|
||||
@@ -27,13 +27,15 @@ private:
|
||||
void GenerateCommon();
|
||||
|
||||
public:
|
||||
void Init() {
|
||||
void Init()
|
||||
{
|
||||
AllocCodeSpace(8192);
|
||||
Generate();
|
||||
WriteProtect();
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
void Shutdown()
|
||||
{
|
||||
FreeCodeSpace();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,21 +52,35 @@ void RegCache::Start()
|
||||
void RegCache::Lock(int p1, int p2, int p3, int p4)
|
||||
{
|
||||
regs[p1].locked = true;
|
||||
if (p2 != 0xFF) regs[p2].locked = true;
|
||||
if (p3 != 0xFF) regs[p3].locked = true;
|
||||
if (p4 != 0xFF) regs[p4].locked = true;
|
||||
|
||||
if (p2 != 0xFF)
|
||||
regs[p2].locked = true;
|
||||
|
||||
if (p3 != 0xFF)
|
||||
regs[p3].locked = true;
|
||||
|
||||
if (p4 != 0xFF)
|
||||
regs[p4].locked = true;
|
||||
}
|
||||
|
||||
// these are x64 reg indices
|
||||
void RegCache::LockX(int x1, int x2, int x3, int x4)
|
||||
{
|
||||
if (xregs[x1].locked) {
|
||||
if (xregs[x1].locked)
|
||||
{
|
||||
PanicAlert("RegCache: x %i already locked!", x1);
|
||||
}
|
||||
|
||||
xregs[x1].locked = true;
|
||||
if (x2 != 0xFF) xregs[x2].locked = true;
|
||||
if (x3 != 0xFF) xregs[x3].locked = true;
|
||||
if (x4 != 0xFF) xregs[x4].locked = true;
|
||||
|
||||
if (x2 != 0xFF)
|
||||
xregs[x2].locked = true;
|
||||
|
||||
if (x3 != 0xFF)
|
||||
xregs[x3].locked = true;
|
||||
|
||||
if (x4 != 0xFF)
|
||||
xregs[x4].locked = true;
|
||||
}
|
||||
|
||||
void RegCache::UnlockAll()
|
||||
@@ -321,6 +335,7 @@ void RegCache::Flush(FlushMode mode)
|
||||
{
|
||||
PanicAlert("Someone forgot to unlock PPC reg %" PRIx64 " (X64 reg %i).", i, RX(i));
|
||||
}
|
||||
|
||||
if (regs[i].away)
|
||||
{
|
||||
if (regs[i].location.IsSimpleReg() || regs[i].location.IsImm())
|
||||
|
||||
@@ -47,23 +47,34 @@ protected:
|
||||
|
||||
public:
|
||||
RegCache();
|
||||
|
||||
virtual ~RegCache() {}
|
||||
|
||||
void Start();
|
||||
|
||||
void DiscardRegContentsIfCached(size_t preg);
|
||||
void SetEmitter(Gen::XEmitter *emitter) {emit = emitter;}
|
||||
void SetEmitter(Gen::XEmitter *emitter)
|
||||
{
|
||||
emit = emitter;
|
||||
}
|
||||
|
||||
void FlushR(Gen::X64Reg reg);
|
||||
void FlushR(Gen::X64Reg reg, Gen::X64Reg reg2) {FlushR(reg); FlushR(reg2);}
|
||||
void FlushLockX(Gen::X64Reg reg) {
|
||||
void FlushR(Gen::X64Reg reg, Gen::X64Reg reg2)
|
||||
{
|
||||
FlushR(reg);
|
||||
FlushR(reg2);
|
||||
}
|
||||
|
||||
void FlushLockX(Gen::X64Reg reg)
|
||||
{
|
||||
FlushR(reg);
|
||||
LockX(reg);
|
||||
}
|
||||
void FlushLockX(Gen::X64Reg reg1, Gen::X64Reg reg2) {
|
||||
void FlushLockX(Gen::X64Reg reg1, Gen::X64Reg reg2)
|
||||
{
|
||||
FlushR(reg1); FlushR(reg2);
|
||||
LockX(reg1); LockX(reg2);
|
||||
}
|
||||
|
||||
void Flush(FlushMode mode = FLUSH_ALL);
|
||||
void Flush(PPCAnalyst::CodeOp *op) {Flush();}
|
||||
int SanityCheck() const;
|
||||
@@ -76,7 +87,11 @@ public:
|
||||
virtual void StoreRegister(size_t preg, Gen::OpArg newLoc) = 0;
|
||||
virtual void LoadRegister(size_t preg, Gen::X64Reg newLoc) = 0;
|
||||
|
||||
const Gen::OpArg &R(size_t preg) const {return regs[preg].location;}
|
||||
const Gen::OpArg &R(size_t preg) const
|
||||
{
|
||||
return regs[preg].location;
|
||||
}
|
||||
|
||||
Gen::X64Reg RX(size_t preg) const
|
||||
{
|
||||
if (IsBound(preg))
|
||||
|
||||
@@ -67,7 +67,8 @@ void Jit64::bx(UGeckoInstruction inst)
|
||||
// If this is not the last instruction of a block,
|
||||
// we will skip the rest process.
|
||||
// Because PPCAnalyst::Flatten() merged the blocks.
|
||||
if (!js.isLastInstruction) {
|
||||
if (!js.isLastInstruction)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,10 +136,13 @@ void Jit64::fmaddXX(UGeckoInstruction inst)
|
||||
fpr.BindToRegister(d, false);
|
||||
//YES it is necessary to dupe the result :(
|
||||
//TODO : analysis - does the top reg get used? If so, dupe, if not, don't.
|
||||
if (single_precision) {
|
||||
if (single_precision)
|
||||
{
|
||||
ForceSinglePrecisionS(XMM0);
|
||||
MOVDDUP(fpr.RX(d), R(XMM0));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
MOVSD(fpr.RX(d), R(XMM0));
|
||||
}
|
||||
// SMB checks flags after this op. Let's lie.
|
||||
@@ -159,7 +162,8 @@ void Jit64::fsign(UGeckoInstruction inst)
|
||||
fpr.Lock(b, d);
|
||||
fpr.BindToRegister(d, true, true);
|
||||
MOVSD(XMM0, fpr.R(b));
|
||||
switch (inst.SUBOP10) {
|
||||
switch (inst.SUBOP10)
|
||||
{
|
||||
case 40: // fnegx
|
||||
PXOR(XMM0, M((void*)&psSignBits2));
|
||||
break;
|
||||
|
||||
@@ -137,10 +137,26 @@ void Jit64::ComputeRC(const Gen::OpArg & arg)
|
||||
}
|
||||
}
|
||||
|
||||
static u32 Add(u32 a, u32 b) {return a + b;}
|
||||
static u32 Or (u32 a, u32 b) {return a | b;}
|
||||
static u32 And(u32 a, u32 b) {return a & b;}
|
||||
static u32 Xor(u32 a, u32 b) {return a ^ b;}
|
||||
// Following static functions are used in conjunction with regimmop
|
||||
static u32 Add(u32 a, u32 b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
static u32 Or(u32 a, u32 b)
|
||||
{
|
||||
return a | b;
|
||||
}
|
||||
|
||||
static u32 And(u32 a, u32 b)
|
||||
{
|
||||
return a & b;
|
||||
}
|
||||
|
||||
static u32 Xor(u32 a, u32 b)
|
||||
{
|
||||
return a ^ b;
|
||||
}
|
||||
|
||||
void Jit64::regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc, bool carry)
|
||||
{
|
||||
@@ -196,7 +212,7 @@ void Jit64::reg_imm(UGeckoInstruction inst)
|
||||
u32 d = inst.RD, a = inst.RA, s = inst.RS;
|
||||
switch (inst.OPCD)
|
||||
{
|
||||
case 14: // addi
|
||||
case 14: // addi
|
||||
// occasionally used as MOV - emulate, with immediate propagation
|
||||
if (gpr.R(a).IsImm() && d != a && a != 0)
|
||||
{
|
||||
@@ -244,18 +260,36 @@ void Jit64::reg_imm(UGeckoInstruction inst)
|
||||
regimmop(d, a, false, (u32)inst.SIMM_16 << 16, Add, &XEmitter::ADD);
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
case 24: // ori
|
||||
if (a == 0 && s == 0 && inst.UIMM == 0 && !inst.Rc) //check for nop
|
||||
{NOP(); return;} //make the nop visible in the generated code. not much use but interesting if we see one.
|
||||
{
|
||||
// Make the nop visible in the generated code. not much use but interesting if we see one.
|
||||
NOP();
|
||||
return;
|
||||
}
|
||||
regimmop(a, s, true, inst.UIMM, Or, &XEmitter::OR);
|
||||
break; //ori
|
||||
case 25: regimmop(a, s, true, inst.UIMM << 16, Or, &XEmitter::OR, false); break;//oris
|
||||
case 28: regimmop(a, s, true, inst.UIMM, And, &XEmitter::AND, true); break;
|
||||
case 29: regimmop(a, s, true, inst.UIMM << 16, And, &XEmitter::AND, true); break;
|
||||
case 26: regimmop(a, s, true, inst.UIMM, Xor, &XEmitter::XOR, false); break; //xori
|
||||
case 27: regimmop(a, s, true, inst.UIMM << 16, Xor, &XEmitter::XOR, false); break; //xoris
|
||||
case 12: regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, false, true); break; //addic
|
||||
case 13: regimmop(d, a, true, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, true, true); break; //addic_rc
|
||||
break;
|
||||
case 25: // oris
|
||||
regimmop(a, s, true, inst.UIMM << 16, Or, &XEmitter::OR, false);
|
||||
break;
|
||||
case 28: // andi
|
||||
regimmop(a, s, true, inst.UIMM, And, &XEmitter::AND, true);
|
||||
break;
|
||||
case 29: // andis
|
||||
regimmop(a, s, true, inst.UIMM << 16, And, &XEmitter::AND, true);
|
||||
break;
|
||||
case 26: // xori
|
||||
regimmop(a, s, true, inst.UIMM, Xor, &XEmitter::XOR, false);
|
||||
break;
|
||||
case 27: // xoris
|
||||
regimmop(a, s, true, inst.UIMM << 16, Xor, &XEmitter::XOR, false);
|
||||
break;
|
||||
case 12: // addic
|
||||
regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, false, true);
|
||||
break;
|
||||
case 13: // addic_rc
|
||||
regimmop(d, a, true, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, true, true);
|
||||
break;
|
||||
default:
|
||||
FALLBACK_IF(true);
|
||||
}
|
||||
@@ -274,20 +308,23 @@ void Jit64::cmpXX(UGeckoInstruction inst)
|
||||
int test_crf = js.next_inst.BI >> 2;
|
||||
// Check if the next instruction is a branch - if it is, merge the two.
|
||||
if (((js.next_inst.OPCD == 16 /* bcx */) ||
|
||||
((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528) /* bcctrx */) ||
|
||||
((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 16) /* bclrx */)) &&
|
||||
(js.next_inst.BO & BO_DONT_DECREMENT_FLAG) &&
|
||||
!(js.next_inst.BO & BO_DONT_CHECK_CONDITION)) {
|
||||
((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528) /* bcctrx */) ||
|
||||
((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 16) /* bclrx */)) &&
|
||||
(js.next_inst.BO & BO_DONT_DECREMENT_FLAG) &&
|
||||
!(js.next_inst.BO & BO_DONT_CHECK_CONDITION))
|
||||
{
|
||||
// Looks like a decent conditional branch that we can merge with.
|
||||
// It only test CR, not CTR.
|
||||
if (test_crf == crf) {
|
||||
if (test_crf == crf)
|
||||
{
|
||||
merge_branch = true;
|
||||
}
|
||||
}
|
||||
|
||||
OpArg comparand;
|
||||
bool signedCompare;
|
||||
if (inst.OPCD == 31) {
|
||||
if (inst.OPCD == 31)
|
||||
{
|
||||
// cmp / cmpl
|
||||
gpr.Lock(a, b);
|
||||
comparand = gpr.R(b);
|
||||
@@ -402,6 +439,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
|
||||
MOV(64, R(RAX), Imm32((s32)gpr.R(a).offset));
|
||||
else
|
||||
MOVSX(64, 32, RAX, gpr.R(a));
|
||||
|
||||
if (!comparand.IsImm())
|
||||
{
|
||||
MOVSX(64, 32, ABI_PARAM1, comparand);
|
||||
@@ -419,6 +457,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
|
||||
MOV(32, R(ABI_PARAM1), comparand);
|
||||
else
|
||||
MOVZX(64, 32, ABI_PARAM1, comparand);
|
||||
|
||||
comparand = R(ABI_PARAM1);
|
||||
}
|
||||
SUB(64, R(RAX), comparand);
|
||||
@@ -466,6 +505,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
|
||||
{
|
||||
if (js.next_inst.LK)
|
||||
MOV(32, M(&LR), Imm32(js.compilerPC + 4));
|
||||
|
||||
MOV(32, R(EAX), M(&CTR));
|
||||
AND(32, R(EAX), Imm32(0xFFFFFFFC));
|
||||
WriteExitDestInEAX();
|
||||
@@ -474,8 +514,10 @@ void Jit64::cmpXX(UGeckoInstruction inst)
|
||||
{
|
||||
MOV(32, R(EAX), M(&LR));
|
||||
AND(32, R(EAX), Imm32(0xFFFFFFFC));
|
||||
|
||||
if (js.next_inst.LK)
|
||||
MOV(32, M(&LR), Imm32(js.compilerPC + 4));
|
||||
|
||||
WriteExitDestInEAX();
|
||||
}
|
||||
else
|
||||
@@ -506,22 +548,23 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||
|
||||
if (gpr.R(s).IsImm() && gpr.R(b).IsImm())
|
||||
{
|
||||
if (inst.SUBOP10 == 28) /* andx */
|
||||
if (inst.SUBOP10 == 28) // andx
|
||||
gpr.SetImmediate32(a, (u32)gpr.R(s).offset & (u32)gpr.R(b).offset);
|
||||
else if (inst.SUBOP10 == 476) /* nandx */
|
||||
else if (inst.SUBOP10 == 476) // nandx
|
||||
gpr.SetImmediate32(a, ~((u32)gpr.R(s).offset & (u32)gpr.R(b).offset));
|
||||
else if (inst.SUBOP10 == 60) /* andcx */
|
||||
else if (inst.SUBOP10 == 60) // andcx
|
||||
gpr.SetImmediate32(a, (u32)gpr.R(s).offset & (~(u32)gpr.R(b).offset));
|
||||
else if (inst.SUBOP10 == 444) /* orx */
|
||||
else if (inst.SUBOP10 == 444) // orx
|
||||
gpr.SetImmediate32(a, (u32)gpr.R(s).offset | (u32)gpr.R(b).offset);
|
||||
else if (inst.SUBOP10 == 124) /* norx */
|
||||
else if (inst.SUBOP10 == 124) // norx
|
||||
gpr.SetImmediate32(a, ~((u32)gpr.R(s).offset | (u32)gpr.R(b).offset));
|
||||
else if (inst.SUBOP10 == 412) /* orcx */
|
||||
else if (inst.SUBOP10 == 412) // orcx
|
||||
gpr.SetImmediate32(a, (u32)gpr.R(s).offset | (~(u32)gpr.R(b).offset));
|
||||
else if (inst.SUBOP10 == 316) /* xorx */
|
||||
else if (inst.SUBOP10 == 316) // xorx
|
||||
gpr.SetImmediate32(a, (u32)gpr.R(s).offset ^ (u32)gpr.R(b).offset);
|
||||
else if (inst.SUBOP10 == 284) /* eqvx */
|
||||
else if (inst.SUBOP10 == 284) // eqvx
|
||||
gpr.SetImmediate32(a, ~((u32)gpr.R(s).offset ^ (u32)gpr.R(b).offset));
|
||||
|
||||
if (inst.Rc)
|
||||
{
|
||||
ComputeRC(gpr.R(a));
|
||||
@@ -575,16 +618,16 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||
OpArg operand = ((a == s) ? gpr.R(b) : gpr.R(s));
|
||||
gpr.BindToRegister(a, true, true);
|
||||
|
||||
if (inst.SUBOP10 == 28) /* andx */
|
||||
if (inst.SUBOP10 == 28) // andx
|
||||
{
|
||||
AND(32, gpr.R(a), operand);
|
||||
}
|
||||
else if (inst.SUBOP10 == 476) /* nandx */
|
||||
else if (inst.SUBOP10 == 476) // nandx
|
||||
{
|
||||
AND(32, gpr.R(a), operand);
|
||||
NOT(32, gpr.R(a));
|
||||
}
|
||||
else if (inst.SUBOP10 == 60) /* andcx */
|
||||
else if (inst.SUBOP10 == 60) // andcx
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
@@ -598,16 +641,16 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||
AND(32, gpr.R(a), R(EAX));
|
||||
}
|
||||
}
|
||||
else if (inst.SUBOP10 == 444) /* orx */
|
||||
else if (inst.SUBOP10 == 444) // orx
|
||||
{
|
||||
OR(32, gpr.R(a), operand);
|
||||
}
|
||||
else if (inst.SUBOP10 == 124) /* norx */
|
||||
else if (inst.SUBOP10 == 124) // norx
|
||||
{
|
||||
OR(32, gpr.R(a), operand);
|
||||
NOT(32, gpr.R(a));
|
||||
}
|
||||
else if (inst.SUBOP10 == 412) /* orcx */
|
||||
else if (inst.SUBOP10 == 412) // orcx
|
||||
{
|
||||
if (a == b)
|
||||
{
|
||||
@@ -621,11 +664,11 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||
OR(32, gpr.R(a), R(EAX));
|
||||
}
|
||||
}
|
||||
else if (inst.SUBOP10 == 316) /* xorx */
|
||||
else if (inst.SUBOP10 == 316) // xorx
|
||||
{
|
||||
XOR(32, gpr.R(a), operand);
|
||||
}
|
||||
else if (inst.SUBOP10 == 284) /* eqvx */
|
||||
else if (inst.SUBOP10 == 284) // eqvx
|
||||
{
|
||||
NOT(32, gpr.R(a));
|
||||
XOR(32, gpr.R(a), operand);
|
||||
@@ -643,46 +686,46 @@ void Jit64::boolX(UGeckoInstruction inst)
|
||||
gpr.Lock(a,s,b);
|
||||
gpr.BindToRegister(a, false, true);
|
||||
|
||||
if (inst.SUBOP10 == 28) /* andx */
|
||||
if (inst.SUBOP10 == 28) // andx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
AND(32, gpr.R(a), gpr.R(b));
|
||||
}
|
||||
else if (inst.SUBOP10 == 476) /* nandx */
|
||||
else if (inst.SUBOP10 == 476) // nandx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
AND(32, gpr.R(a), gpr.R(b));
|
||||
NOT(32, gpr.R(a));
|
||||
}
|
||||
else if (inst.SUBOP10 == 60) /* andcx */
|
||||
else if (inst.SUBOP10 == 60) // andcx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(b));
|
||||
NOT(32, gpr.R(a));
|
||||
AND(32, gpr.R(a), gpr.R(s));
|
||||
}
|
||||
else if (inst.SUBOP10 == 444) /* orx */
|
||||
else if (inst.SUBOP10 == 444) // orx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
OR(32, gpr.R(a), gpr.R(b));
|
||||
}
|
||||
else if (inst.SUBOP10 == 124) /* norx */
|
||||
else if (inst.SUBOP10 == 124) // norx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
OR(32, gpr.R(a), gpr.R(b));
|
||||
NOT(32, gpr.R(a));
|
||||
}
|
||||
else if (inst.SUBOP10 == 412) /* orcx */
|
||||
else if (inst.SUBOP10 == 412) // orcx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(b));
|
||||
NOT(32, gpr.R(a));
|
||||
OR(32, gpr.R(a), gpr.R(s));
|
||||
}
|
||||
else if (inst.SUBOP10 == 316) /* xorx */
|
||||
else if (inst.SUBOP10 == 316) // xorx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
XOR(32, gpr.R(a), gpr.R(b));
|
||||
}
|
||||
else if (inst.SUBOP10 == 284) /* eqvx */
|
||||
else if (inst.SUBOP10 == 284) // eqvx
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
NOT(32, gpr.R(a));
|
||||
@@ -992,13 +1035,25 @@ void Jit64::mulli(UGeckoInstruction inst)
|
||||
else if ((imm & (imm - 1)) == 0)
|
||||
{
|
||||
u32 shift = 0;
|
||||
if (imm & 0xFFFF0000) shift |= 16;
|
||||
if (imm & 0xFF00FF00) shift |= 8;
|
||||
if (imm & 0xF0F0F0F0) shift |= 4;
|
||||
if (imm & 0xCCCCCCCC) shift |= 2;
|
||||
if (imm & 0xAAAAAAAA) shift |= 1;
|
||||
|
||||
if (imm & 0xFFFF0000)
|
||||
shift |= 16;
|
||||
|
||||
if (imm & 0xFF00FF00)
|
||||
shift |= 8;
|
||||
|
||||
if (imm & 0xF0F0F0F0)
|
||||
shift |= 4;
|
||||
|
||||
if (imm & 0xCCCCCCCC)
|
||||
shift |= 2;
|
||||
|
||||
if (imm & 0xAAAAAAAA)
|
||||
shift |= 1;
|
||||
|
||||
if (d != a)
|
||||
MOV(32, gpr.R(d), gpr.R(a));
|
||||
|
||||
if (shift)
|
||||
SHL(32, gpr.R(d), Imm8(shift));
|
||||
}
|
||||
@@ -1047,13 +1102,25 @@ void Jit64::mullwx(UGeckoInstruction inst)
|
||||
else if ((imm & (imm - 1)) == 0 && !inst.OE)
|
||||
{
|
||||
u32 shift = 0;
|
||||
if (imm & 0xFFFF0000) shift |= 16;
|
||||
if (imm & 0xFF00FF00) shift |= 8;
|
||||
if (imm & 0xF0F0F0F0) shift |= 4;
|
||||
if (imm & 0xCCCCCCCC) shift |= 2;
|
||||
if (imm & 0xAAAAAAAA) shift |= 1;
|
||||
|
||||
if (imm & 0xFFFF0000)
|
||||
shift |= 16;
|
||||
|
||||
if (imm & 0xFF00FF00)
|
||||
shift |= 8;
|
||||
|
||||
if (imm & 0xF0F0F0F0)
|
||||
shift |= 4;
|
||||
|
||||
if (imm & 0xCCCCCCCC)
|
||||
shift |= 2;
|
||||
|
||||
if (imm & 0xAAAAAAAA)
|
||||
shift |= 1;
|
||||
|
||||
if (d != src)
|
||||
MOV(32, gpr.R(d), gpr.R(src));
|
||||
|
||||
if (shift)
|
||||
SHL(32, gpr.R(d), Imm8(shift));
|
||||
}
|
||||
@@ -1517,7 +1584,7 @@ void Jit64::rlwinmx(UGeckoInstruction inst)
|
||||
int s = inst.RS;
|
||||
if (gpr.R(s).IsImm())
|
||||
{
|
||||
unsigned result = (int)gpr.R(s).offset;
|
||||
u32 result = (int)gpr.R(s).offset;
|
||||
if (inst.SH != 0)
|
||||
result = _rotl(result, inst.SH);
|
||||
result &= Helper_Mask(inst.MB, inst.ME);
|
||||
@@ -1554,6 +1621,7 @@ void Jit64::rlwinmx(UGeckoInstruction inst)
|
||||
{
|
||||
ROL(32, gpr.R(a), Imm8(inst.SH));
|
||||
}
|
||||
|
||||
if (!(inst.MB==0 && inst.ME==31))
|
||||
{
|
||||
AND(32, gpr.R(a), Imm32(Helper_Mask(inst.MB, inst.ME)));
|
||||
@@ -1604,10 +1672,12 @@ void Jit64::rlwimix(UGeckoInstruction inst)
|
||||
{
|
||||
MOV(32, gpr.R(a), gpr.R(s));
|
||||
}
|
||||
|
||||
if (inst.SH)
|
||||
{
|
||||
ROL(32, gpr.R(a), Imm8(inst.SH));
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
{
|
||||
ComputeRC(gpr.R(a));
|
||||
@@ -1637,6 +1707,7 @@ void Jit64::rlwimix(UGeckoInstruction inst)
|
||||
AND(32, R(EAX), Imm32(mask));
|
||||
XOR(32, gpr.R(a), R(EAX));
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
ComputeRC(gpr.R(a));
|
||||
}
|
||||
@@ -1700,6 +1771,7 @@ void Jit64::negx(UGeckoInstruction inst)
|
||||
{
|
||||
ComputeRC(gpr.R(d));
|
||||
}
|
||||
|
||||
if (inst.OE)
|
||||
{
|
||||
GenerateConstantOverflow(gpr.R(d).offset == 0x80000000);
|
||||
@@ -1821,7 +1893,9 @@ void Jit64::srawx(UGeckoInstruction inst)
|
||||
SetJumpTarget(nocarry);
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
if (inst.Rc) {
|
||||
|
||||
if (inst.Rc)
|
||||
{
|
||||
ComputeRC(gpr.R(a));
|
||||
}
|
||||
}
|
||||
@@ -1888,8 +1962,10 @@ void Jit64::cntlzwx(UGeckoInstruction inst)
|
||||
u32 mask = 0x80000000;
|
||||
u32 i = 0;
|
||||
for (; i < 32; i++, mask >>= 1)
|
||||
{
|
||||
if ((u32)gpr.R(s).offset & mask)
|
||||
break;
|
||||
}
|
||||
gpr.SetImmediate32(a, i);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -30,26 +30,26 @@ void Jit64::lXXx(UGeckoInstruction inst)
|
||||
bool signExtend = false;
|
||||
switch (inst.OPCD)
|
||||
{
|
||||
case 32: /* lwz */
|
||||
case 33: /* lwzu */
|
||||
case 32: // lwz
|
||||
case 33: // lwzu
|
||||
accessSize = 32;
|
||||
signExtend = false;
|
||||
break;
|
||||
|
||||
case 34: /* lbz */
|
||||
case 35: /* lbzu */
|
||||
case 34: // lbz
|
||||
case 35: // lbzu
|
||||
accessSize = 8;
|
||||
signExtend = false;
|
||||
break;
|
||||
|
||||
case 40: /* lhz */
|
||||
case 41: /* lhzu */
|
||||
case 40: // lhz
|
||||
case 41: // lhzu
|
||||
accessSize = 16;
|
||||
signExtend = false;
|
||||
break;
|
||||
|
||||
case 42: /* lha */
|
||||
case 43: /* lhau */
|
||||
case 42: // lha
|
||||
case 43: // lhau
|
||||
accessSize = 16;
|
||||
signExtend = true;
|
||||
break;
|
||||
@@ -57,25 +57,25 @@ void Jit64::lXXx(UGeckoInstruction inst)
|
||||
case 31:
|
||||
switch (inst.SUBOP10)
|
||||
{
|
||||
case 23: /* lwzx */
|
||||
case 55: /* lwzux */
|
||||
case 23: // lwzx
|
||||
case 55: // lwzux
|
||||
accessSize = 32;
|
||||
signExtend = false;
|
||||
break;
|
||||
|
||||
case 87: /* lbzx */
|
||||
case 119: /* lbzux */
|
||||
case 87: // lbzx
|
||||
case 119: // lbzux
|
||||
accessSize = 8;
|
||||
signExtend = false;
|
||||
break;
|
||||
case 279: /* lhzx */
|
||||
case 311: /* lhzux */
|
||||
case 279: // lhzx
|
||||
case 311: // lhzux
|
||||
accessSize = 16;
|
||||
signExtend = false;
|
||||
break;
|
||||
|
||||
case 343: /* lhax */
|
||||
case 375: /* lhaux */
|
||||
case 343: // lhax
|
||||
case 375: // lhaux
|
||||
accessSize = 16;
|
||||
signExtend = true;
|
||||
break;
|
||||
@@ -96,11 +96,11 @@ void Jit64::lXXx(UGeckoInstruction inst)
|
||||
// ... maybe the throttle one already do that :p
|
||||
// if (CommandProcessor::AllowIdleSkipping() && PixelEngine::AllowIdleSkipping())
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
|
||||
inst.OPCD == 32 &&
|
||||
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
|
||||
(Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
inst.OPCD == 32 &&
|
||||
(inst.hex & 0xFFFF0000) == 0x800D0000 &&
|
||||
(Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
|
||||
(SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
|
||||
Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
|
||||
{
|
||||
// TODO(LinesPrower):
|
||||
// - Rewrite this!
|
||||
@@ -259,10 +259,18 @@ void Jit64::stX(UGeckoInstruction inst)
|
||||
int accessSize;
|
||||
switch (inst.OPCD & ~1)
|
||||
{
|
||||
case 36: accessSize = 32; break; //stw
|
||||
case 44: accessSize = 16; break; //sth
|
||||
case 38: accessSize = 8; break; //stb
|
||||
default: _assert_msg_(DYNA_REC, 0, "AWETKLJASDLKF"); return;
|
||||
case 36: // stw
|
||||
accessSize = 32;
|
||||
break;
|
||||
case 44: // sth
|
||||
accessSize = 16;
|
||||
break;
|
||||
case 38: // stb
|
||||
accessSize = 8;
|
||||
break;
|
||||
default:
|
||||
_assert_msg_(DYNA_REC, 0, "stX: Invalid access size.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a == 0) || gpr.R(a).IsImm())
|
||||
@@ -273,18 +281,27 @@ void Jit64::stX(UGeckoInstruction inst)
|
||||
addr += offset;
|
||||
if ((addr & 0xFFFFF000) == 0xCC008000 && jo.optimizeGatherPipe)
|
||||
{
|
||||
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
|
||||
// Helps external systems know which instruction triggered the write
|
||||
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
|
||||
|
||||
gpr.FlushLockX(ABI_PARAM1);
|
||||
MOV(32, R(ABI_PARAM1), gpr.R(s));
|
||||
if (update)
|
||||
gpr.SetImmediate32(a, addr);
|
||||
|
||||
// No need to protect these, they don't touch any state
|
||||
// question - should we inline them instead? Pro: Lose a CALL Con: Code bloat
|
||||
switch (accessSize)
|
||||
{
|
||||
// No need to protect these, they don't touch any state
|
||||
// question - should we inline them instead? Pro: Lose a CALL Con: Code bloat
|
||||
case 8: CALL((void *)asm_routines.fifoDirectWrite8); break;
|
||||
case 16: CALL((void *)asm_routines.fifoDirectWrite16); break;
|
||||
case 32: CALL((void *)asm_routines.fifoDirectWrite32); break;
|
||||
case 8:
|
||||
CALL((void *)asm_routines.fifoDirectWrite8);
|
||||
break;
|
||||
case 16:
|
||||
CALL((void *)asm_routines.fifoDirectWrite16);
|
||||
break;
|
||||
case 32:
|
||||
CALL((void *)asm_routines.fifoDirectWrite32);
|
||||
break;
|
||||
}
|
||||
js.fifoBytesThisBlock += accessSize >> 3;
|
||||
gpr.UnlockAllX();
|
||||
@@ -300,14 +317,22 @@ void Jit64::stX(UGeckoInstruction inst)
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
|
||||
// Helps external systems know which instruction triggered the write
|
||||
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
|
||||
|
||||
u32 registersInUse = RegistersInUse();
|
||||
ABI_PushRegistersAndAdjustStack(registersInUse, false);
|
||||
switch (accessSize)
|
||||
{
|
||||
case 32: ABI_CallFunctionAC(true ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), gpr.R(s), addr); break;
|
||||
case 16: ABI_CallFunctionAC(true ? ((void *)&Memory::Write_U16) : ((void *)&Memory::Write_U16_Swap), gpr.R(s), addr); break;
|
||||
case 8: ABI_CallFunctionAC((void *)&Memory::Write_U8, gpr.R(s), addr); break;
|
||||
case 32:
|
||||
ABI_CallFunctionAC(true ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), gpr.R(s), addr);
|
||||
break;
|
||||
case 16:
|
||||
ABI_CallFunctionAC(true ? ((void *)&Memory::Write_U16) : ((void *)&Memory::Write_U16_Swap), gpr.R(s), addr);
|
||||
break;
|
||||
case 8:
|
||||
ABI_CallFunctionAC((void *)&Memory::Write_U8, gpr.R(s), addr);
|
||||
break;
|
||||
}
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, false);
|
||||
if (update)
|
||||
@@ -359,17 +384,29 @@ void Jit64::stXx(UGeckoInstruction inst)
|
||||
ADD(32, gpr.R(a), gpr.R(b));
|
||||
MOV(32, R(EDX), gpr.R(a));
|
||||
MEMCHECK_END
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
MOV(32, R(EDX), gpr.R(a));
|
||||
ADD(32, R(EDX), gpr.R(b));
|
||||
}
|
||||
|
||||
int accessSize;
|
||||
switch (inst.SUBOP10 & ~32) {
|
||||
case 151: accessSize = 32; break;
|
||||
case 407: accessSize = 16; break;
|
||||
case 215: accessSize = 8; break;
|
||||
default: PanicAlert("stXx: invalid access size");
|
||||
accessSize = 0; break;
|
||||
switch (inst.SUBOP10 & ~32)
|
||||
{
|
||||
case 151:
|
||||
accessSize = 32;
|
||||
break;
|
||||
case 407:
|
||||
accessSize = 16;
|
||||
break;
|
||||
case 215:
|
||||
accessSize = 8;
|
||||
break;
|
||||
default:
|
||||
PanicAlert("stXx: invalid access size");
|
||||
accessSize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
MOV(32, R(ECX), gpr.R(s));
|
||||
|
||||
@@ -47,12 +47,15 @@ void Jit64::psq_st(UGeckoInstruction inst)
|
||||
MOVZX(32, 8, EDX, R(AL));
|
||||
|
||||
// FIXME: Fix ModR/M encoding to allow [EDX*4+disp32] without a base register!
|
||||
if (inst.W) {
|
||||
if (inst.W)
|
||||
{
|
||||
// One value
|
||||
PXOR(XMM0, R(XMM0)); // TODO: See if we can get rid of this cheaply by tweaking the code in the singleStore* functions.
|
||||
CVTSD2SS(XMM0, fpr.R(s));
|
||||
CALLptr(MScaled(EDX, SCALE_8, (u32)(u64)asm_routines.singleStoreQuantized));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pair of values
|
||||
CVTPD2PS(XMM0, fpr.R(s));
|
||||
CALLptr(MScaled(EDX, SCALE_8, (u32)(u64)asm_routines.pairedStoreQuantized));
|
||||
|
||||
@@ -156,12 +156,21 @@ void Jit64::ps_arith(UGeckoInstruction inst)
|
||||
|
||||
switch (inst.SUBOP5)
|
||||
{
|
||||
case 18: tri_op(inst.FD, inst.FA, inst.FB, false, &XEmitter::DIVPD); break; //div
|
||||
case 20: tri_op(inst.FD, inst.FA, inst.FB, false, &XEmitter::SUBPD); break; //sub
|
||||
case 21: tri_op(inst.FD, inst.FA, inst.FB, true, &XEmitter::ADDPD); break; //add
|
||||
case 25: tri_op(inst.FD, inst.FA, inst.FC, true, &XEmitter::MULPD); break; //mul
|
||||
case 18: // div
|
||||
tri_op(inst.FD, inst.FA, inst.FB, false, &XEmitter::DIVPD);
|
||||
break;
|
||||
case 20: // sub
|
||||
tri_op(inst.FD, inst.FA, inst.FB, false, &XEmitter::SUBPD);
|
||||
break;
|
||||
case 21: // add
|
||||
tri_op(inst.FD, inst.FA, inst.FB, true, &XEmitter::ADDPD);
|
||||
break;
|
||||
case 25: // mul
|
||||
tri_op(inst.FD, inst.FA, inst.FC, true, &XEmitter::MULPD);
|
||||
break;
|
||||
default:
|
||||
_assert_msg_(DYNA_REC, 0, "ps_arith WTF!!!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -174,8 +174,12 @@ namespace JitILProfiler
|
||||
u64 codeHash;
|
||||
u64 totalElapsed;
|
||||
u64 numberOfCalls;
|
||||
Block() : index(0), codeHash(0), totalElapsed(0), numberOfCalls(0) { }
|
||||
|
||||
Block() : index(0), codeHash(0), totalElapsed(0), numberOfCalls(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<Block> blocks;
|
||||
static u32 blockIndex;
|
||||
static u64 beginTime;
|
||||
@@ -188,6 +192,7 @@ namespace JitILProfiler
|
||||
block.codeHash = codeHash;
|
||||
return block;
|
||||
}
|
||||
|
||||
// These functions need to be static because they are called with
|
||||
// ABI_CallFunction().
|
||||
static void Begin(u32 index)
|
||||
@@ -195,6 +200,7 @@ namespace JitILProfiler
|
||||
blockIndex = index;
|
||||
beginTime = __rdtsc();
|
||||
}
|
||||
|
||||
static void End()
|
||||
{
|
||||
const u64 endTime = __rdtsc();
|
||||
@@ -203,6 +209,7 @@ namespace JitILProfiler
|
||||
block.totalElapsed += duration;
|
||||
++block.numberOfCalls;
|
||||
}
|
||||
|
||||
struct JitILProfilerFinalizer
|
||||
{
|
||||
virtual ~JitILProfilerFinalizer()
|
||||
@@ -221,11 +228,13 @@ namespace JitILProfiler
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static std::unique_ptr<JitILProfilerFinalizer> finalizer;
|
||||
static void Init()
|
||||
{
|
||||
finalizer = std::make_unique<JitILProfilerFinalizer>();
|
||||
}
|
||||
|
||||
static void Shutdown()
|
||||
{
|
||||
finalizer.reset();
|
||||
@@ -246,10 +255,14 @@ void JitIL::Init()
|
||||
else
|
||||
{
|
||||
if (!Core::g_CoreStartupParameter.bJITBlockLinking)
|
||||
{
|
||||
jo.enableBlocklink = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Speed boost, but not 100% safe
|
||||
jo.enableBlocklink = !Core::g_CoreStartupParameter.bMMU;
|
||||
}
|
||||
}
|
||||
|
||||
jo.fpAccurateFcmp = false;
|
||||
@@ -268,7 +281,8 @@ void JitIL::Init()
|
||||
code_block.m_gpa = &js.gpa;
|
||||
code_block.m_fpa = &js.fpa;
|
||||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
|
||||
{
|
||||
JitILProfiler::Init();
|
||||
}
|
||||
}
|
||||
@@ -282,7 +296,8 @@ void JitIL::ClearCache()
|
||||
|
||||
void JitIL::Shutdown()
|
||||
{
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
|
||||
{
|
||||
JitILProfiler::Shutdown();
|
||||
}
|
||||
|
||||
@@ -352,11 +367,14 @@ static void ImHere()
|
||||
PowerPC::ppcState.gpr[5], PowerPC::ppcState.gpr[6]);
|
||||
f.Flush();
|
||||
}
|
||||
if (been_here.find(PC) != been_here.end()) {
|
||||
|
||||
if (been_here.find(PC) != been_here.end())
|
||||
{
|
||||
been_here.find(PC)->second++;
|
||||
if ((been_here.find(PC)->second) & 1023)
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR);
|
||||
been_here[PC] = 1;
|
||||
}
|
||||
@@ -376,7 +394,8 @@ void JitIL::Cleanup()
|
||||
void JitIL::WriteExit(u32 destination)
|
||||
{
|
||||
Cleanup();
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
|
||||
{
|
||||
ABI_CallFunction((void *)JitILProfiler::End);
|
||||
}
|
||||
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
|
||||
@@ -408,7 +427,8 @@ void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg)
|
||||
{
|
||||
MOV(32, M(&PC), arg);
|
||||
Cleanup();
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
|
||||
{
|
||||
ABI_CallFunction((void *)JitILProfiler::End);
|
||||
}
|
||||
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
|
||||
@@ -420,7 +440,8 @@ void JitIL::WriteRfiExitDestInOpArg(const Gen::OpArg& arg)
|
||||
MOV(32, M(&PC), arg);
|
||||
MOV(32, M(&NPC), arg);
|
||||
Cleanup();
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
|
||||
{
|
||||
ABI_CallFunction((void *)JitILProfiler::End);
|
||||
}
|
||||
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
|
||||
@@ -431,7 +452,8 @@ void JitIL::WriteRfiExitDestInOpArg(const Gen::OpArg& arg)
|
||||
void JitIL::WriteExceptionExit()
|
||||
{
|
||||
Cleanup();
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
|
||||
{
|
||||
ABI_CallFunction((void *)JitILProfiler::End);
|
||||
}
|
||||
MOV(32, R(EAX), M(&PC));
|
||||
@@ -554,7 +576,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
|
||||
u64 codeHash = -1;
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling ||
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILOutputIR)
|
||||
SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILOutputIR)
|
||||
{
|
||||
// For profiling and IR Writer
|
||||
for (u32 i = 0; i < code_block.m_num_instructions; i++)
|
||||
@@ -577,7 +599,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
|
||||
js.downcountAmount = 0;
|
||||
if (!Core::g_CoreStartupParameter.bEnableDebugging)
|
||||
js.downcountAmount += PatchEngine::GetSpeedhackCycles(code_block.m_address);
|
||||
js.downcountAmount += PatchEngine::GetSpeedhackCycles(code_block.m_address);
|
||||
|
||||
// Translate instructions
|
||||
for (u32 i = 0; i < code_block.m_num_instructions; i++)
|
||||
|
||||
@@ -67,19 +67,22 @@ public:
|
||||
bool IsInCodeSpace(u8 *ptr) override { return IsInSpace(ptr); }
|
||||
|
||||
void ClearCache() override;
|
||||
const u8 *GetDispatcher() {
|
||||
const u8 *GetDispatcher()
|
||||
{
|
||||
return asm_routines.dispatcher; // asm_routines.dispatcher
|
||||
}
|
||||
const CommonAsmRoutines *GetAsmRoutines() override {
|
||||
|
||||
const CommonAsmRoutines *GetAsmRoutines() override
|
||||
{
|
||||
return &asm_routines;
|
||||
}
|
||||
|
||||
const char *GetName() override {
|
||||
const char *GetName() override
|
||||
{
|
||||
return "JIT64IL";
|
||||
}
|
||||
|
||||
// Run!
|
||||
|
||||
void Run() override;
|
||||
void SingleStep() override;
|
||||
|
||||
|
||||
@@ -376,15 +376,19 @@ void CompileInstruction(PPCAnalyst::CodeOp & op)
|
||||
JitIL *jitil = (JitIL *)jit;
|
||||
(jitil->*dynaOpTable[op.inst.OPCD])(op.inst);
|
||||
GekkoOPInfo *info = op.opinfo;
|
||||
if (info) {
|
||||
if (info)
|
||||
{
|
||||
#ifdef OPLOG
|
||||
if (!strcmp(info->opname, OP_TO_LOG)){ ///"mcrfs"
|
||||
if (!strcmp(info->opname, OP_TO_LOG)) // "mcrfs"
|
||||
{
|
||||
rsplocations.push_back(jit.js.compilerPC);
|
||||
}
|
||||
#endif
|
||||
info->compileCount++;
|
||||
info->lastUse = jit->js.compilerPC;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("Tried to compile illegal (or unknown) instruction %08x, at %08x", op.inst.hex, jit->js.compilerPC);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,12 +108,14 @@ static void ImHere()
|
||||
}
|
||||
fprintf(f.GetHandle(), "%08x\n", PC);
|
||||
}
|
||||
|
||||
if (been_here.find(PC) != been_here.end())
|
||||
{
|
||||
been_here.find(PC)->second++;
|
||||
if ((been_here.find(PC)->second) & 1023)
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(DYNA_REC, "I'm here - PC = %08x , LR = %08x", PC, LR);
|
||||
been_here[PC] = 1;
|
||||
}
|
||||
@@ -374,8 +376,10 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
||||
SetCC();
|
||||
gpr.Unlock(A, C);
|
||||
}
|
||||
|
||||
// Conditionally add profiling code.
|
||||
if (Profiler::g_ProfileBlocks) {
|
||||
if (Profiler::g_ProfileBlocks)
|
||||
{
|
||||
ARMReg rA = gpr.GetReg();
|
||||
ARMReg rB = gpr.GetReg();
|
||||
MOVI2R(rA, (u32)&b->runCount); // Load in to register
|
||||
@@ -415,7 +419,8 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
||||
// WARNING - cmp->branch merging will screw this up.
|
||||
js.isLastInstruction = true;
|
||||
js.next_inst = 0;
|
||||
if (Profiler::g_ProfileBlocks) {
|
||||
if (Profiler::g_ProfileBlocks)
|
||||
{
|
||||
// CAUTION!!! push on stack regs you use, do your stuff, then pop
|
||||
PROFILER_VPUSH;
|
||||
// get end tic
|
||||
@@ -431,6 +436,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
||||
js.next_inst = ops[i + 1].inst;
|
||||
js.next_compilerPC = ops[i + 1].address;
|
||||
}
|
||||
|
||||
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
|
||||
{
|
||||
js.fifoBytesThisBlock -= 32;
|
||||
@@ -438,6 +444,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
||||
QuickCallFunction(R14, (void*)&GPFifo::CheckGatherPipe);
|
||||
POP(4, R0, R1, R2, R3);
|
||||
}
|
||||
|
||||
if (Core::g_CoreStartupParameter.bEnableDebugging)
|
||||
{
|
||||
// Add run count
|
||||
@@ -457,6 +464,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
||||
fpr.Unlock(VA);
|
||||
fpr.Unlock(VB);
|
||||
}
|
||||
|
||||
if (!ops[i].skip)
|
||||
{
|
||||
PrintDebug(ops[i].inst, DEBUG_OUTPUT);
|
||||
@@ -474,6 +482,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (code_block.m_memory_exception)
|
||||
BKPT(0x500);
|
||||
|
||||
|
||||
@@ -74,18 +74,22 @@ public:
|
||||
|
||||
void ClearCache();
|
||||
|
||||
const u8 *GetDispatcher() {
|
||||
const u8 *GetDispatcher()
|
||||
{
|
||||
return asm_routines.dispatcher;
|
||||
}
|
||||
CommonAsmRoutinesBase *GetAsmRoutines() {
|
||||
|
||||
CommonAsmRoutinesBase *GetAsmRoutines()
|
||||
{
|
||||
return &asm_routines;
|
||||
}
|
||||
|
||||
const char *GetName() {
|
||||
const char *GetName()
|
||||
{
|
||||
return "JITARM";
|
||||
}
|
||||
// Run!
|
||||
|
||||
// Run!
|
||||
void Run();
|
||||
void SingleStep();
|
||||
|
||||
|
||||
@@ -16,20 +16,21 @@
|
||||
|
||||
using namespace ArmGen;
|
||||
|
||||
void JitArmBlockCache::WriteLinkBlock(u8* location, const u8* address)
|
||||
{
|
||||
ARMXEmitter emit(location);
|
||||
emit.B(address);
|
||||
emit.FlushIcache();
|
||||
}
|
||||
void JitArmBlockCache::WriteDestroyBlock(const u8* location, u32 address)
|
||||
{
|
||||
ARMXEmitter emit((u8 *)location);
|
||||
emit.MOVI2R(R11, address);
|
||||
emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher);
|
||||
emit.STR(R11, R9, PPCSTATE_OFF(pc));
|
||||
emit.B(R12);
|
||||
emit.FlushIcache();
|
||||
}
|
||||
void JitArmBlockCache::WriteLinkBlock(u8* location, const u8* address)
|
||||
{
|
||||
ARMXEmitter emit(location);
|
||||
emit.B(address);
|
||||
emit.FlushIcache();
|
||||
}
|
||||
|
||||
void JitArmBlockCache::WriteDestroyBlock(const u8* location, u32 address)
|
||||
{
|
||||
ARMXEmitter emit((u8 *)location);
|
||||
emit.MOVI2R(R11, address);
|
||||
emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher);
|
||||
emit.STR(R11, R9, PPCSTATE_OFF(pc));
|
||||
emit.B(R12);
|
||||
emit.FlushIcache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -97,10 +97,12 @@ void JitArm::bx(UGeckoInstruction inst)
|
||||
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
|
||||
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
|
||||
}
|
||||
|
||||
// If this is not the last instruction of a block,
|
||||
// we will skip the rest process.
|
||||
// Because PPCAnalyst::Flatten() merged the blocks.
|
||||
if (!js.isLastInstruction) {
|
||||
if (!js.isLastInstruction)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -231,7 +233,8 @@ void JitArm::bcctrx(UGeckoInstruction inst)
|
||||
LDR(rA, R9, PPCSTATE_OFF(spr[SPR_CTR]));
|
||||
BIC(rA, rA, 0x3);
|
||||
|
||||
if (inst.LK_3){
|
||||
if (inst.LK_3)
|
||||
{
|
||||
u32 Jumpto = js.compilerPC + 4;
|
||||
MOVI2R(rB, Jumpto);
|
||||
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
|
||||
@@ -285,7 +288,8 @@ void JitArm::bclrx(UGeckoInstruction inst)
|
||||
//AND(32, R(EAX), Imm32(0xFFFFFFFC));
|
||||
LDR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
|
||||
BIC(rA, rA, 0x3);
|
||||
if (inst.LK){
|
||||
if (inst.LK)
|
||||
{
|
||||
u32 Jumpto = js.compilerPC + 4;
|
||||
MOVI2R(rB, Jumpto);
|
||||
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
|
||||
|
||||
@@ -117,7 +117,8 @@ void JitArm::fctiwx(UGeckoInstruction inst)
|
||||
NEONXEmitter nemit(this);
|
||||
nemit.VORR(vD, vD, V0);
|
||||
|
||||
if (inst.Rc) Helper_UpdateCR1(fpscrReg, rA);
|
||||
if (inst.Rc)
|
||||
Helper_UpdateCR1(fpscrReg, rA);
|
||||
|
||||
STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
|
||||
gpr.Unlock(rA);
|
||||
@@ -197,7 +198,8 @@ void JitArm::fctiwzx(UGeckoInstruction inst)
|
||||
NEONXEmitter nemit(this);
|
||||
nemit.VORR(vD, vD, V0);
|
||||
|
||||
if (inst.Rc) Helper_UpdateCR1(fpscrReg, rA);
|
||||
if (inst.Rc)
|
||||
Helper_UpdateCR1(fpscrReg, rA);
|
||||
|
||||
STR(fpscrReg, R9, PPCSTATE_OFF(fpscr));
|
||||
gpr.Unlock(rA);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user