Reserve a register for ppcState.

The register is RBP, previously in the GPR allocation order.  The next
commit will investigate whether there are too few GPRs (now or before),
but for now there is no replacement.

Previously, it was accessed RIP relatively; using RBP, anything in the
first 0x100 bytes of ppcState (including all the GPRs) can be accessed
with three fewer bytes.  Code to access ppcState is generated constantly
(mostly by register save/load), so in principle, this should improve
instruction cache footprint significantly.  It seems that this makes a
significant performance difference in practice.

The vast majority of this commit is mechanically replacing
M(&PowerPC::ppcState.x) with a new macro PPCSTATE(x).

Version 2: gets most of the cases which were using the register access
macros.
This commit is contained in:
comex 2014-09-01 01:41:40 -04:00
parent 387e1e3f21
commit 48891c6359
17 changed files with 238 additions and 212 deletions

View File

@ -210,8 +210,8 @@ void Jit64::WriteCallInterpreter(UGeckoInstruction inst)
fpr.Flush();
if (js.isLastInstruction)
{
MOV(32, M(&PC), Imm32(js.compilerPC));
MOV(32, M(&NPC), Imm32(js.compilerPC + 4));
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
MOV(32, PPCSTATE(npc), Imm32(js.compilerPC + 4));
}
Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst);
ABI_CallFunctionC((void*)instr, inst.hex);
@ -279,7 +279,7 @@ void Jit64::WriteExit(u32 destination)
{
Cleanup();
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
@ -298,7 +298,7 @@ void Jit64::WriteExit(u32 destination)
}
else
{
MOV(32, M(&PC), Imm32(destination));
MOV(32, PPCSTATE(pc), Imm32(destination));
JMP(asm_routines.dispatcher, true);
}
@ -307,39 +307,39 @@ void Jit64::WriteExit(u32 destination)
void Jit64::WriteExitDestInEAX()
{
MOV(32, M(&PC), R(EAX));
MOV(32, PPCSTATE(pc), R(EAX));
Cleanup();
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
void Jit64::WriteRfiExitDestInEAX()
{
MOV(32, M(&PC), R(EAX));
MOV(32, M(&NPC), R(EAX));
MOV(32, PPCSTATE(pc), R(EAX));
MOV(32, PPCSTATE(npc), R(EAX));
Cleanup();
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
void Jit64::WriteExceptionExit()
{
Cleanup();
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
MOV(32, R(EAX), PPCSTATE(pc));
MOV(32, PPCSTATE(npc), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
void Jit64::WriteExternalExceptionExit()
{
Cleanup();
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
MOV(32, R(EAX), PPCSTATE(pc));
MOV(32, PPCSTATE(npc), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
@ -426,7 +426,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
// Downcount flag check. The last block decremented downcounter, and the flag should still be available.
FixupBranch skip = J_CC(CC_NBE);
MOV(32, M(&PC), Imm32(js.blockStart));
MOV(32, PPCSTATE(pc), Imm32(js.blockStart));
JMP(asm_routines.doTiming, true); // downcount hit zero - go doTiming.
SetJumpTarget(skip);
@ -452,7 +452,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
}
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(NAN_CHECK)
// should help logged stack-traces become more accurate
MOV(32, M(&PC), Imm32(js.blockStart));
MOV(32, PPCSTATE(pc), Imm32(js.blockStart));
#endif
// Start up the register allocators
@ -501,7 +501,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
{
js.fifoBytesThisBlock -= 32;
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
u32 registersInUse = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(registersInUse, false);
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe);
@ -520,7 +520,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
HLEFunction(function);
if (type == HLE::HLE_HOOK_REPLACE)
{
MOV(32, R(EAX), M(&NPC));
MOV(32, R(EAX), PPCSTATE(npc));
js.downcountAmount += js.st.numCycles;
WriteExitDestInEAX();
break;
@ -537,13 +537,13 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
fpr.Flush();
//This instruction uses FPU - needs to add FP exception bailout
TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit
TEST(32, PPCSTATE(msr), Imm32(1 << 13)); // Test FP enabled bit
FixupBranch b1 = J_CC(CC_NZ, true);
// If a FPU exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
MOV(32, M(&PC), Imm32(ops[i].address));
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
WriteExceptionExit();
SetJumpTarget(b1);
@ -557,16 +557,16 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
gpr.Flush();
fpr.Flush();
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = J_CC(CC_NZ, true);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = J_CC(CC_Z, true);
TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
TEST(32, PPCSTATE(msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = J_CC(CC_Z, true);
TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = J_CC(CC_Z, true);
MOV(32, M(&PC), Imm32(ops[i].address));
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
WriteExternalExceptionExit();
SetJumpTarget(noCPInt);
@ -580,7 +580,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
gpr.Flush();
fpr.Flush();
MOV(32, M(&PC), Imm32(ops[i].address));
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
@ -597,12 +597,12 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
gpr.Flush();
fpr.Flush();
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI));
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_DSI));
FixupBranch noMemException = J_CC(CC_Z, true);
// If a memory exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
MOV(32, M(&PC), Imm32(ops[i].address));
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
WriteExceptionExit();
SetJumpTarget(noMemException);
}
@ -645,9 +645,9 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (code_block.m_memory_exception)
{
// Address of instruction could not be translated
MOV(32, M(&NPC), Imm32(js.compilerPC));
MOV(32, PPCSTATE(npc), Imm32(js.compilerPC));
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI));
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI));
// Remove the invalid instruction from the icache, forcing a recompile
MOV(64, R(RAX), ImmPtr(jit->GetBlockCache()->GetICachePtr(js.compilerPC)));

View File

@ -29,6 +29,7 @@ void Jit64AsmRoutineManager::Generate()
// Two statically allocated registers.
MOV(64, R(RBX), Imm64((u64)Memory::base));
MOV(64, R(R15), Imm64((u64)jit->GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough
MOV(64, R(RBP), Imm64((u64)&PowerPC::ppcState + 0x80));
const u8* outerLoop = GetCodePtr();
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
@ -55,7 +56,7 @@ void Jit64AsmRoutineManager::Generate()
SetJumpTarget(skipToRealDispatch);
dispatcherNoCheck = GetCodePtr();
MOV(32, R(EAX), M(&PowerPC::ppcState.pc));
MOV(32, R(EAX), PPCSTATE(pc));
dispatcherPcInEAX = GetCodePtr();
u32 mask = 0;
@ -113,7 +114,7 @@ void Jit64AsmRoutineManager::Generate()
SetJumpTarget(notfound);
//Ok, no block, let's jit
MOV(32, R(ABI_PARAM1), M(&PowerPC::ppcState.pc));
MOV(32, R(ABI_PARAM1), PPCSTATE(pc));
CALL((void *)&Jit);
JMP(dispatcherNoCheck); // no point in special casing this
@ -122,10 +123,10 @@ void Jit64AsmRoutineManager::Generate()
doTiming = GetCodePtr();
// Test external exceptions.
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
FixupBranch noExtException = J_CC(CC_Z);
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
MOV(32, R(EAX), PPCSTATE(pc));
MOV(32, PPCSTATE(npc), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
SetJumpTarget(noExtException);

View File

@ -202,7 +202,7 @@ const int* GPRRegCache::GetAllocationOrder(size_t& count)
#ifdef _WIN32
RSI, RDI, R13, R14, R8, R9, R10, R11, R12, //, RCX
#else
RBP, R13, R14, R8, R9, R10, R11, R12, //, RCX
R13, R14, R8, R9, R10, R11, R12, //, RCX
#endif
};
count = sizeof(allocationOrder) / sizeof(const int);
@ -221,12 +221,12 @@ const int* FPURegCache::GetAllocationOrder(size_t& count)
OpArg GPRRegCache::GetDefaultLocation(size_t reg) const
{
return M(&ppcState.gpr[reg]);
return PPCSTATE(gpr[reg]);
}
OpArg FPURegCache::GetDefaultLocation(size_t reg) const
{
return M(&ppcState.ps[reg][0]);
return PPCSTATE(ps[reg][0]);
}
void RegCache::KillImmediate(size_t preg, bool doLoad, bool makeDirty)

View File

@ -28,9 +28,9 @@ void Jit64::sc(UGeckoInstruction inst)
gpr.Flush();
fpr.Flush();
MOV(32, M(&PC), Imm32(js.compilerPC + 4));
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC + 4));
LOCK();
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL));
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_SYSCALL));
WriteExceptionExit();
}
@ -45,12 +45,12 @@ void Jit64::rfi(UGeckoInstruction inst)
const u32 mask = 0x87C0FFFF;
const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13]
// MSR = ((MSR & ~mask) | (SRR1 & mask)) & clearMSR13;
AND(32, M(&MSR), Imm32((~mask) & clearMSR13));
MOV(32, R(EAX), M(&SRR1));
AND(32, PPCSTATE(msr), Imm32((~mask) & clearMSR13));
MOV(32, R(EAX), PPCSTATE_SRR1);
AND(32, R(EAX), Imm32(mask & clearMSR13));
OR(32, M(&MSR), R(EAX));
OR(32, PPCSTATE(msr), R(EAX));
// NPC = SRR0;
MOV(32, R(EAX), M(&SRR0));
MOV(32, R(EAX), PPCSTATE_SRR0);
WriteRfiExitDestInEAX();
}
@ -62,7 +62,7 @@ void Jit64::bx(UGeckoInstruction inst)
// We must always process the following sentence
// even if the blocks are merged by PPCAnalyst::Flatten().
if (inst.LK)
MOV(32, M(&LR), Imm32(js.compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.compilerPC + 4));
// If this is not the last instruction of a block,
// we will skip the rest process.
@ -82,7 +82,7 @@ void Jit64::bx(UGeckoInstruction inst)
destination = js.compilerPC + SignExt26(inst.LI << 2);
#ifdef ACID_TEST
if (inst.LK)
AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000)));
AND(32, PPCSTATE(cr), Imm32(~(0xFF000000)));
#endif
if (destination == js.compilerPC)
{
@ -108,7 +108,7 @@ void Jit64::bcx(UGeckoInstruction inst)
FixupBranch pCTRDontBranch;
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
{
SUB(32, M(&CTR), Imm8(1));
SUB(32, PPCSTATE_CTR, Imm8(1));
if (inst.BO & BO_BRANCH_IF_CTR_0)
pCTRDontBranch = J_CC(CC_NZ, true);
else
@ -123,7 +123,7 @@ void Jit64::bcx(UGeckoInstruction inst)
}
if (inst.LK)
MOV(32, M(&LR), Imm32(js.compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.compilerPC + 4));
u32 destination;
if (inst.AA)
@ -164,9 +164,9 @@ void Jit64::bcctrx(UGeckoInstruction inst)
gpr.Flush();
fpr.Flush();
MOV(32, R(EAX), M(&CTR));
MOV(32, R(EAX), PPCSTATE_CTR);
if (inst.LK_3)
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
MOV(32, PPCSTATE_LR, Imm32(js.compilerPC + 4)); // LR = PC + 4;
AND(32, R(EAX), Imm32(0xFFFFFFFC));
WriteExitDestInEAX();
}
@ -179,11 +179,11 @@ void Jit64::bcctrx(UGeckoInstruction inst)
FixupBranch b = JumpIfCRFieldBit(inst.BI >> 2, 3 - (inst.BI & 3),
!(inst.BO_2 & BO_BRANCH_IF_TRUE));
MOV(32, R(EAX), M(&CTR));
MOV(32, R(EAX), PPCSTATE_CTR);
AND(32, R(EAX), Imm32(0xFFFFFFFC));
//MOV(32, M(&PC), R(EAX)); => Already done in WriteExitDestInEAX()
//MOV(32, PPCSTATE(pc), R(EAX)); => Already done in WriteExitDestInEAX()
if (inst.LK_3)
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
MOV(32, PPCSTATE_LR, Imm32(js.compilerPC + 4)); // LR = PC + 4;
gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);
@ -204,7 +204,7 @@ void Jit64::bclrx(UGeckoInstruction inst)
FixupBranch pCTRDontBranch;
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
{
SUB(32, M(&CTR), Imm8(1));
SUB(32, PPCSTATE_CTR, Imm8(1));
if (inst.BO & BO_BRANCH_IF_CTR_0)
pCTRDontBranch = J_CC(CC_NZ, true);
else
@ -221,13 +221,13 @@ void Jit64::bclrx(UGeckoInstruction inst)
// This below line can be used to prove that blr "eats flags" in practice.
// This observation will let us do a lot of fun observations.
#ifdef ACID_TEST
AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000)));
AND(32, PPCSTATE(cr), Imm32(~(0xFF000000)));
#endif
MOV(32, R(EAX), M(&LR));
MOV(32, R(EAX), PPCSTATE_LR);
AND(32, R(EAX), Imm32(0xFFFFFFFC));
if (inst.LK)
MOV(32, M(&LR), Imm32(js.compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.compilerPC + 4));
gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);

View File

@ -248,7 +248,7 @@ void Jit64::fcmpx(UGeckoInstruction inst)
fpr.BindToRegister(b, true);
if (fprf)
AND(32, M(&FPSCR), Imm32(~FPRF_MASK));
AND(32, PPCSTATE(fpscr), Imm32(~FPRF_MASK));
// Are we masking sNaN invalid floating point exceptions? If not this could crash if we don't handle the exception?
UCOMISD(fpr.R(b).GetSimpleReg(), fpr.R(a));
@ -273,14 +273,14 @@ void Jit64::fcmpx(UGeckoInstruction inst)
MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_EQ)));
if (fprf)
OR(32, M(&FPSCR), Imm32(CR_EQ << FPRF_SHIFT));
OR(32, PPCSTATE(fpscr), Imm32(CR_EQ << FPRF_SHIFT));
continue1 = J();
SetJumpTarget(pNaN);
MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_SO)));
if (fprf)
OR(32, M(&FPSCR), Imm32(CR_SO << FPRF_SHIFT));
OR(32, PPCSTATE(fpscr), Imm32(CR_SO << FPRF_SHIFT));
if (a != b)
{
@ -289,13 +289,13 @@ void Jit64::fcmpx(UGeckoInstruction inst)
SetJumpTarget(pGreater);
MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_GT)));
if (fprf)
OR(32, M(&FPSCR), Imm32(CR_GT << FPRF_SHIFT));
OR(32, PPCSTATE(fpscr), Imm32(CR_GT << FPRF_SHIFT));
continue3 = J();
SetJumpTarget(pLesser);
MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_LT)));
if (fprf)
OR(32, M(&FPSCR), Imm32(CR_LT << FPRF_SHIFT));
OR(32, PPCSTATE(fpscr), Imm32(CR_LT << FPRF_SHIFT));
}
SetJumpTarget(continue1);
@ -305,7 +305,7 @@ void Jit64::fcmpx(UGeckoInstruction inst)
SetJumpTarget(continue3);
}
MOV(64, M(&PowerPC::ppcState.cr_val[crf]), R(RAX));
MOV(64, PPCSTATE(cr_val[crf]), R(RAX));
fpr.UnlockAll();
}

View File

@ -21,12 +21,12 @@ void Jit64::GenerateConstantOverflow(bool overflow)
if (overflow)
{
//XER[OV/SO] = 1
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_SO_MASK | XER_OV_MASK));
OR(32, PPCSTATE(spr[SPR_XER]), Imm32(XER_SO_MASK | XER_OV_MASK));
}
else
{
//XER[OV] = 0
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_OV_MASK));
AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~XER_OV_MASK));
}
}
@ -34,11 +34,11 @@ void Jit64::GenerateOverflow()
{
FixupBranch jno = J_CC(CC_NO);
//XER[OV/SO] = 1
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_SO_MASK | XER_OV_MASK));
OR(32, PPCSTATE(spr[SPR_XER]), Imm32(XER_SO_MASK | XER_OV_MASK));
FixupBranch exit = J();
SetJumpTarget(jno);
//XER[OV] = 0
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_OV_MASK));
AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~XER_OV_MASK));
SetJumpTarget(exit);
}
@ -54,7 +54,7 @@ void Jit64::FinalizeCarryOverflow(bool oe, bool inv)
JitSetCA();
SetJumpTarget(carry1);
//XER[OV/SO] = 1
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_SO_MASK | XER_OV_MASK));
OR(32, PPCSTATE(spr[SPR_XER]), Imm32(XER_SO_MASK | XER_OV_MASK));
FixupBranch exit = J();
SetJumpTarget(jno);
// Do carry
@ -74,7 +74,7 @@ void Jit64::FinalizeCarryOverflow(bool oe, bool inv)
void Jit64::GetCarryEAXAndClear()
{
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
MOV(32, R(EAX), PPCSTATE(spr[SPR_XER]));
BTR(32, R(EAX), Imm8(29));
}
@ -109,7 +109,7 @@ void Jit64::FinalizeCarryGenerateOverflowEAX(bool oe, bool inv)
SetJumpTarget(carry1);
}
// Dump EAX back into XER
MOV(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(EAX));
MOV(32, PPCSTATE(spr[SPR_XER]), R(EAX));
}
// Assumes that the flags were just set through an addition.
@ -117,10 +117,10 @@ void Jit64::GenerateCarry()
{
// USES_XER
FixupBranch pNoCarry = J_CC(CC_NC);
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_CA_MASK));
OR(32, PPCSTATE(spr[SPR_XER]), Imm32(XER_CA_MASK));
FixupBranch pContinue = J();
SetJumpTarget(pNoCarry);
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(XER_CA_MASK)));
AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~(XER_CA_MASK)));
SetJumpTarget(pContinue);
}
@ -128,12 +128,12 @@ void Jit64::ComputeRC(const Gen::OpArg & arg)
{
if (arg.IsImm())
{
MOV(64, M(&PowerPC::ppcState.cr_val[0]), Imm32((s32)arg.offset));
MOV(64, PPCSTATE(cr_val[0]), Imm32((s32)arg.offset));
}
else
{
MOVSX(64, 32, RAX, arg);
MOV(64, M(&PowerPC::ppcState.cr_val[0]), R(RAX));
MOV(64, PPCSTATE(cr_val[0]), R(RAX));
}
}
@ -375,7 +375,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
compareResult = CR_LT;
}
MOV(64, R(RAX), Imm64(PPCCRToInternal(compareResult)));
MOV(64, M(&PowerPC::ppcState.cr_val[crf]), R(RAX));
MOV(64, PPCSTATE(cr_val[crf]), R(RAX));
gpr.UnlockAll();
if (merge_branch)
@ -393,7 +393,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
if (js.next_inst.OPCD == 16) // bcx
{
if (js.next_inst.LK)
MOV(32, M(&LR), Imm32(js.next_compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.next_compilerPC + 4));
u32 destination;
if (js.next_inst.AA)
@ -405,16 +405,16 @@ void Jit64::cmpXX(UGeckoInstruction inst)
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx
{
if (js.next_inst.LK)
MOV(32, M(&LR), Imm32(js.next_compilerPC + 4));
MOV(32, R(EAX), M(&CTR));
MOV(32, PPCSTATE_LR, Imm32(js.next_compilerPC + 4));
MOV(32, R(EAX), PPCSTATE_CTR);
AND(32, R(EAX), Imm32(0xFFFFFFFC));
WriteExitDestInEAX();
}
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 16)) // bclrx
{
MOV(32, R(EAX), M(&LR));
MOV(32, R(EAX), PPCSTATE_LR);
if (js.next_inst.LK)
MOV(32, M(&LR), Imm32(js.next_compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.next_compilerPC + 4));
WriteExitDestInEAX();
}
else
@ -461,7 +461,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
comparand = R(ABI_PARAM1);
}
SUB(64, R(RAX), comparand);
MOV(64, M(&PowerPC::ppcState.cr_val[crf]), R(RAX));
MOV(64, PPCSTATE(cr_val[crf]), R(RAX));
if (merge_branch)
{
@ -492,7 +492,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
if (js.next_inst.OPCD == 16) // bcx
{
if (js.next_inst.LK)
MOV(32, M(&LR), Imm32(js.next_compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.next_compilerPC + 4));
u32 destination;
if (js.next_inst.AA)
@ -504,19 +504,19 @@ void Jit64::cmpXX(UGeckoInstruction inst)
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx
{
if (js.next_inst.LK)
MOV(32, M(&LR), Imm32(js.next_compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.next_compilerPC + 4));
MOV(32, R(EAX), M(&CTR));
MOV(32, R(EAX), PPCSTATE_CTR);
AND(32, R(EAX), Imm32(0xFFFFFFFC));
WriteExitDestInEAX();
}
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 16)) // bclrx
{
MOV(32, R(EAX), M(&LR));
MOV(32, R(EAX), PPCSTATE_LR);
AND(32, R(EAX), Imm32(0xFFFFFFFC));
if (js.next_inst.LK)
MOV(32, M(&LR), Imm32(js.next_compilerPC + 4));
MOV(32, PPCSTATE_LR, Imm32(js.next_compilerPC + 4));
WriteExitDestInEAX();
}
@ -2020,7 +2020,7 @@ void Jit64::twx(UGeckoInstruction inst)
SetJumpTarget(fixup);
}
LOCK();
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_PROGRAM));
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_PROGRAM));
gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);

View File

@ -123,7 +123,7 @@ void Jit64::lXXx(UGeckoInstruction inst)
ABI_PopRegistersAndAdjustStack(registersInUse, false);
// ! we must continue executing of the loop after exception handling, maybe there is still 0 in r0
//MOV(32, M(&PowerPC::ppcState.pc), Imm32(js.compilerPC));
//MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
WriteExceptionExit();
SetJumpTarget(noIdle);
@ -331,7 +331,7 @@ void Jit64::stX(UGeckoInstruction inst)
if ((addr & 0xFFFFF000) == 0xCC008000 && jo.optimizeGatherPipe)
{
// Helps external systems know which instruction triggered the write
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC));
gpr.FlushLockX(ABI_PARAM1);
MOV(32, R(ABI_PARAM1), gpr.R(s));
@ -367,7 +367,7 @@ void Jit64::stX(UGeckoInstruction inst)
else
{
// Helps external systems know which instruction triggered the write
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC));
u32 registersInUse = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(registersInUse, false);

View File

@ -43,7 +43,7 @@ void Jit64::psq_st(UGeckoInstruction inst)
// UU[SCALE]UUUUU[TYPE] where SCALE is 6 bits and TYPE is 3 bits, so we have to AND with
// 0b0011111100000111, or 0x3F07.
MOV(32, R(EAX), Imm32(0x3F07));
AND(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_GQR0 + inst.I]));
AND(32, R(EAX), PPCSTATE(spr[SPR_GQR0 + inst.I]));
MOVZX(32, 8, EDX, R(AL));
// FIXME: Fix ModR/M encoding to allow [EDX*4+disp32] without a base register!

View File

@ -16,22 +16,22 @@ void Jit64::GetCRFieldBit(int field, int bit, Gen::X64Reg out, bool negate)
switch (bit)
{
case CR_SO_BIT: // check bit 61 set
BT(64, M(&PowerPC::ppcState.cr_val[field]), Imm8(61));
BT(64, PPCSTATE(cr_val[field]), Imm8(61));
SETcc(negate ? CC_NC : CC_C, R(out));
break;
case CR_EQ_BIT: // check bits 31-0 == 0
CMP(32, M(&PowerPC::ppcState.cr_val[field]), Imm8(0));
CMP(32, PPCSTATE(cr_val[field]), Imm8(0));
SETcc(negate ? CC_NZ : CC_Z, R(out));
break;
case CR_GT_BIT: // check val > 0
CMP(64, M(&PowerPC::ppcState.cr_val[field]), Imm8(0));
CMP(64, PPCSTATE(cr_val[field]), Imm8(0));
SETcc(negate ? CC_NG : CC_G, R(out));
break;
case CR_LT_BIT: // check bit 62 set
BT(64, M(&PowerPC::ppcState.cr_val[field]), Imm8(62));
BT(64, PPCSTATE(cr_val[field]), Imm8(62));
SETcc(negate ? CC_NC : CC_C, R(out));
break;
@ -42,7 +42,7 @@ void Jit64::GetCRFieldBit(int field, int bit, Gen::X64Reg out, bool negate)
void Jit64::SetCRFieldBit(int field, int bit, Gen::X64Reg in)
{
MOV(64, R(ABI_PARAM1), M(&PowerPC::ppcState.cr_val[field]));
MOV(64, R(ABI_PARAM1), PPCSTATE(cr_val[field]));
MOVZX(32, 8, in, R(in));
switch (bit)
@ -75,7 +75,7 @@ void Jit64::SetCRFieldBit(int field, int bit, Gen::X64Reg in)
}
BTS(64, R(ABI_PARAM1), Imm8(32));
MOV(64, M(&PowerPC::ppcState.cr_val[field]), R(ABI_PARAM1));
MOV(64, PPCSTATE(cr_val[field]), R(ABI_PARAM1));
}
FixupBranch Jit64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
@ -83,19 +83,19 @@ FixupBranch Jit64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
switch (bit)
{
case CR_SO_BIT: // check bit 61 set
BT(64, M(&PowerPC::ppcState.cr_val[field]), Imm8(61));
BT(64, PPCSTATE(cr_val[field]), Imm8(61));
return J_CC(jump_if_set ? CC_C : CC_NC, true);
case CR_EQ_BIT: // check bits 31-0 == 0
CMP(32, M(&PowerPC::ppcState.cr_val[field]), Imm8(0));
CMP(32, PPCSTATE(cr_val[field]), Imm8(0));
return J_CC(jump_if_set ? CC_Z : CC_NZ, true);
case CR_GT_BIT: // check val > 0
CMP(64, M(&PowerPC::ppcState.cr_val[field]), Imm8(0));
CMP(64, PPCSTATE(cr_val[field]), Imm8(0));
return J_CC(jump_if_set ? CC_G : CC_LE, true);
case CR_LT_BIT: // check bit 62 set
BT(64, M(&PowerPC::ppcState.cr_val[field]), Imm8(62));
BT(64, PPCSTATE(cr_val[field]), Imm8(62));
return J_CC(jump_if_set ? CC_C : CC_NC, true);
default:
@ -154,7 +154,7 @@ void Jit64::mtspr(UGeckoInstruction inst)
gpr.Lock(d);
gpr.BindToRegister(d, true, false);
}
MOV(32, M(&PowerPC::ppcState.spr[iIndex]), gpr.R(d));
MOV(32, PPCSTATE(spr[iIndex]), gpr.R(d));
gpr.UnlockAll();
}
@ -190,7 +190,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
LEA(64, RAX, MComplex(RAX, RDX, SCALE_1, offset));
else
ADD(64, R(RAX), R(RDX));
MOV(64, M(&TL), R(RAX));
MOV(64, PPCSTATE(spr[SPR_TL]), R(RAX));
// Two calls of TU/TL next to each other are extremely common in typical usage, so merge them
// if we can.
@ -234,7 +234,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
default:
gpr.Lock(d);
gpr.BindToRegister(d, false);
MOV(32, gpr.R(d), M(&PowerPC::ppcState.spr[iIndex]));
MOV(32, gpr.R(d), PPCSTATE(spr[iIndex]));
break;
}
gpr.UnlockAll();
@ -251,7 +251,7 @@ void Jit64::mtmsr(UGeckoInstruction inst)
gpr.Lock(inst.RS);
gpr.BindToRegister(inst.RS, true, false);
}
MOV(32, M(&MSR), gpr.R(inst.RS));
MOV(32, PPCSTATE(msr), gpr.R(inst.RS));
gpr.UnlockAll();
gpr.Flush();
fpr.Flush();
@ -259,17 +259,17 @@ void Jit64::mtmsr(UGeckoInstruction inst)
// If some exceptions are pending and EE are now enabled, force checking
// external exceptions when going out of mtmsr in order to execute delayed
// interrupts as soon as possible.
TEST(32, M(&MSR), Imm32(0x8000));
TEST(32, PPCSTATE(msr), Imm32(0x8000));
FixupBranch eeDisabled = J_CC(CC_Z);
TEST(32, M((void*)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
FixupBranch noExceptionsPending = J_CC(CC_Z);
// Check if a CP interrupt is waiting and keep the GPU emulation in sync (issue 4336)
TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP));
FixupBranch cpInt = J_CC(CC_NZ);
MOV(32, M(&PC), Imm32(js.compilerPC + 4));
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC + 4));
WriteExternalExceptionExit();
SetJumpTarget(cpInt);
@ -288,7 +288,7 @@ void Jit64::mfmsr(UGeckoInstruction inst)
//Privileged?
gpr.Lock(inst.RD);
gpr.BindToRegister(inst.RD, false, true);
MOV(32, gpr.R(inst.RD), M(&MSR));
MOV(32, gpr.R(inst.RD), PPCSTATE(msr));
gpr.UnlockAll();
}
@ -318,7 +318,7 @@ void Jit64::mfcr(UGeckoInstruction inst)
if (i != 0)
SHL(32, gpr.R(d), Imm8(4));
MOV(64, R(cr_val), M(&PowerPC::ppcState.cr_val[i]));
MOV(64, R(cr_val), PPCSTATE(cr_val[i]));
// EQ: Bits 31-0 == 0; set flag bit 1
TEST(32, R(cr_val), R(cr_val));
@ -360,12 +360,12 @@ void Jit64::mtcrf(UGeckoInstruction inst)
u64 newcrval = PPCCRToInternal(newcr);
if ((s64)newcrval == (s32)newcrval)
{
MOV(64, M(&PowerPC::ppcState.cr_val[i]), Imm32((s32)newcrval));
MOV(64, PPCSTATE(cr_val[i]), Imm32((s32)newcrval));
}
else
{
MOV(64, R(RAX), Imm64(newcrval));
MOV(64, M(&PowerPC::ppcState.cr_val[i]), R(RAX));
MOV(64, PPCSTATE(cr_val[i]), R(RAX));
}
}
}
@ -384,7 +384,7 @@ void Jit64::mtcrf(UGeckoInstruction inst)
if (i != 0)
AND(32, R(EAX), Imm8(0xF));
MOV(64, R(EAX), MScaled(EAX, SCALE_8, (u32)(u64)m_crTable));
MOV(64, M(&PowerPC::ppcState.cr_val[i]), R(EAX));
MOV(64, PPCSTATE(cr_val[i]), R(EAX));
}
}
gpr.UnlockAll();
@ -400,8 +400,8 @@ void Jit64::mcrf(UGeckoInstruction inst)
// USES_CR
if (inst.CRFS != inst.CRFD)
{
MOV(64, R(EAX), M(&PowerPC::ppcState.cr_val[inst.CRFS]));
MOV(64, M(&PowerPC::ppcState.cr_val[inst.CRFD]), R(EAX));
MOV(64, R(EAX), PPCSTATE(cr_val[inst.CRFS]));
MOV(64, PPCSTATE(cr_val[inst.CRFD]), R(EAX));
}
}
@ -413,14 +413,14 @@ void Jit64::mcrxr(UGeckoInstruction inst)
// USES_CR
// Copy XER[0-3] into CR[inst.CRFD]
MOV(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_XER]));
MOV(32, R(EAX), PPCSTATE(spr[SPR_XER]));
SHR(32, R(EAX), Imm8(28));
MOV(64, R(EAX), MScaled(EAX, SCALE_8, (u32)(u64)m_crTable));
MOV(64, M(&PowerPC::ppcState.cr_val[inst.CRFD]), R(EAX));
MOV(64, PPCSTATE(cr_val[inst.CRFD]), R(EAX));
// Clear XER[0-3]
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(0x0FFFFFFF));
AND(32, PPCSTATE(spr[SPR_XER]), Imm32(0x0FFFFFFF));
}
void Jit64::crXXX(UGeckoInstruction inst)

View File

@ -163,7 +163,7 @@ static void fregSpill(RegInfo& RI, X64Reg reg)
#ifdef _WIN32
static const X64Reg RegAllocOrder[] = {RSI, RDI, R12, R13, R14, R8, R9, R10, R11};
#else
static const X64Reg RegAllocOrder[] = {RBP, R12, R13, R14, R8, R9, R10, R11};
static const X64Reg RegAllocOrder[] = {R12, R13, R14, R8, R9, R10, R11};
#endif
static const int RegAllocSize = sizeof(RegAllocOrder) / sizeof(X64Reg);
static const X64Reg FRegAllocOrder[] = {XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM2, XMM3, XMM4, XMM5};
@ -949,8 +949,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
// interpreter call at the moment, but optimizing interpreter
// calls isn't completely out of the question...
regSpillCallerSaved(RI);
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->MOV(32, M(&NPC), Imm32(InstLoc+4));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc));
Jit->MOV(32, PPCSTATE(npc), Imm32(InstLoc+4));
Jit->ABI_CallFunctionC((void*)GetInterpreterOp(InstCode),
InstCode);
break;
@ -962,7 +962,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
X64Reg reg = regFindFreeReg(RI);
unsigned ppcreg = *I >> 8;
Jit->MOV(32, R(reg), M(&PowerPC::ppcState.gpr[ppcreg]));
Jit->MOV(32, R(reg), PPCSTATE(gpr[ppcreg]));
RI.regs[reg] = I;
break;
}
@ -973,7 +973,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
X64Reg reg = regFindFreeReg(RI);
unsigned ppcreg = *I >> 8;
Jit->MOV(64, R(reg), M(&PowerPC::ppcState.cr_val[ppcreg]));
Jit->MOV(64, R(reg), PPCSTATE(cr_val[ppcreg]));
RI.regs[reg] = I;
break;
}
@ -983,7 +983,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
break;
X64Reg reg = regFindFreeReg(RI);
Jit->MOV(32, R(reg), M(&CTR));
Jit->MOV(32, R(reg), PPCSTATE_CTR);
RI.regs[reg] = I;
break;
}
@ -993,7 +993,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
break;
X64Reg reg = regFindFreeReg(RI);
Jit->MOV(32, R(reg), M(&LR));
Jit->MOV(32, R(reg), PPCSTATE_LR);
RI.regs[reg] = I;
break;
}
@ -1003,7 +1003,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
break;
X64Reg reg = regFindFreeReg(RI);
Jit->MOV(32, R(reg), M(&MSR));
Jit->MOV(32, R(reg), PPCSTATE(msr));
RI.regs[reg] = I;
break;
}
@ -1014,7 +1014,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
X64Reg reg = regFindFreeReg(RI);
unsigned gqr = *I >> 8;
Jit->MOV(32, R(reg), M(&GQR(gqr)));
Jit->MOV(32, R(reg), PPCSTATE(spr[SPR_GQR0 + gqr]));
RI.regs[reg] = I;
break;
}
@ -1024,7 +1024,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
break;
X64Reg reg = regFindFreeReg(RI);
Jit->MOV(32, R(reg), M(&PowerPC::ppcState.spr[SPR_XER]));
Jit->MOV(32, R(reg), PPCSTATE(spr[SPR_XER]));
Jit->SHR(32, R(reg), Imm8(29));
Jit->AND(32, R(reg), Imm8(1));
RI.regs[reg] = I;
@ -1042,7 +1042,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
{
X64Reg reg = regEnsureInReg(RI, getOp1(I));
unsigned ppcreg = *I >> 16;
Jit->MOV(64, M(&PowerPC::ppcState.cr_val[ppcreg]), R(reg));
Jit->MOV(64, PPCSTATE(cr_val[ppcreg]), R(reg));
regNormalRegClear(RI, I);
break;
}
@ -1067,15 +1067,15 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
// If some exceptions are pending and EE are now enabled, force checking
// external exceptions when going out of mtmsr in order to execute delayed
// interrupts as soon as possible.
Jit->MOV(32, R(EAX), M(&MSR));
Jit->MOV(32, R(EAX), PPCSTATE(msr));
Jit->TEST(32, R(EAX), Imm32(0x8000));
FixupBranch eeDisabled = Jit->J_CC(CC_Z);
Jit->MOV(32, R(EAX), M((void*)&PowerPC::ppcState.Exceptions));
Jit->MOV(32, R(EAX), PPCSTATE(Exceptions));
Jit->TEST(32, R(EAX), R(EAX));
FixupBranch noExceptionsPending = Jit->J_CC(CC_Z);
Jit->MOV(32, M(&PC), Imm32(InstLoc + 4));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc + 4));
Jit->WriteExceptionExit(); // TODO: Implement WriteExternalExceptionExit for JitIL
Jit->SetJumpTarget(eeDisabled);
@ -1114,8 +1114,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp1(I)));
Jit->AND(32, R(ECX), Imm8(0x1F));
Jit->SHL(32, R(ECX), Imm8(12));
Jit->AND(32, M(&FPSCR), Imm32(~(0x1F << 12)));
Jit->OR(32, M(&FPSCR), R(ECX));
Jit->AND(32, PPCSTATE(fpscr), Imm32(~(0x1F << 12)));
Jit->OR(32, PPCSTATE(fpscr), R(ECX));
regNormalRegClear(RI, I);
break;
}
@ -1641,7 +1641,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
regSpill(RI, EDX);
u32 quantreg = *I >> 24;
Jit->MOV(32, R(EAX), Imm32(0x3F07));
Jit->AND(32, R(EAX), M(&PowerPC::ppcState.spr[SPR_GQR0 + quantreg]));
Jit->AND(32, R(EAX), PPCSTATE(spr[SPR_GQR0 + quantreg]));
Jit->MOVZX(32, 8, EDX, R(AL));
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp2(I)));
@ -1778,7 +1778,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
X64Reg reg = fregFindFreeReg(RI);
unsigned ppcreg = *I >> 8;
Jit->MOVAPD(reg, M(&PowerPC::ppcState.ps[ppcreg]));
Jit->MOVAPD(reg, PPCSTATE(ps[ppcreg]));
RI.fregs[reg] = I;
break;
}
@ -1797,14 +1797,14 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
Jit->AND(32, M(p+4), Imm32(0x80000000));
Jit->MOV(32, M(p), Imm32(0));
Jit->SetJumpTarget(ok);
Jit->MOVAPD(reg, M(&PowerPC::ppcState.ps[ppcreg]));
Jit->MOVAPD(reg, PPCSTATE(ps[ppcreg]));
RI.fregs[reg] = I;
break;
}
case StoreFReg:
{
unsigned ppcreg = *I >> 16;
Jit->MOVAPD(M(&PowerPC::ppcState.ps[ppcreg]),
Jit->MOVAPD(PPCSTATE(ps[ppcreg]),
fregEnsureInReg(RI, getOp1(I)));
fregNormalRegClear(RI, I);
break;
@ -1913,15 +1913,15 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
Jit->ABI_CallFunction((void*)checkIsSNAN);
Jit->TEST(8, R(EAX), R(EAX));
FixupBranch ok = Jit->J_CC(CC_Z);
Jit->OR(32, M(&FPSCR), Imm32(FPSCR_FX)); // FPSCR.FX = 1;
Jit->OR(32, M(&FPSCR), Imm32(FPSCR_VXSNAN)); // FPSCR.Hex |= mask;
Jit->TEST(32, M(&FPSCR), Imm32(FPSCR_VE));
Jit->OR(32, PPCSTATE(fpscr), Imm32(FPSCR_FX)); // FPSCR.FX = 1;
Jit->OR(32, PPCSTATE(fpscr), Imm32(FPSCR_VXSNAN)); // FPSCR.Hex |= mask;
Jit->TEST(32, PPCSTATE(fpscr), Imm32(FPSCR_VE));
FixupBranch finish0 = Jit->J_CC(CC_NZ);
Jit->OR(32, M(&FPSCR), Imm32(FPSCR_VXVC)); // FPSCR.Hex |= mask;
Jit->OR(32, PPCSTATE(fpscr), Imm32(FPSCR_VXVC)); // FPSCR.Hex |= mask;
FixupBranch finish1 = Jit->J();
Jit->SetJumpTarget(ok);
Jit->OR(32, M(&FPSCR), Imm32(FPSCR_FX)); // FPSCR.FX = 1;
Jit->OR(32, M(&FPSCR), Imm32(FPSCR_VXVC)); // FPSCR.Hex |= mask;
Jit->OR(32, PPCSTATE(fpscr), Imm32(FPSCR_FX)); // FPSCR.FX = 1;
Jit->OR(32, PPCSTATE(fpscr), Imm32(FPSCR_VXVC)); // FPSCR.Hex |= mask;
Jit->SetJumpTarget(finish0);
Jit->SetJumpTarget(finish1);
}
@ -1942,8 +1942,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
Jit->ABI_CallFunction((void*)checkIsSNAN);
Jit->TEST(8, R(EAX), R(EAX));
FixupBranch finish = Jit->J_CC(CC_Z);
Jit->OR(32, M(&FPSCR), Imm32(FPSCR_FX)); // FPSCR.FX = 1;
Jit->OR(32, M(&FPSCR), Imm32(FPSCR_VXVC)); // FPSCR.Hex |= mask;
Jit->OR(32, PPCSTATE(fpscr), Imm32(FPSCR_FX)); // FPSCR.FX = 1;
Jit->OR(32, PPCSTATE(fpscr), Imm32(FPSCR_VXVC)); // FPSCR.Hex |= mask;
Jit->SetJumpTarget(finish);
}
@ -2094,7 +2094,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
RI.Jit->Cleanup(); // is it needed?
Jit->ABI_CallFunction((void *)&PowerPC::OnIdleIL);
Jit->MOV(32, M(&PC), Imm32(ibuild->GetImmValue( getOp2(I) )));
Jit->MOV(32, PPCSTATE(pc), Imm32(ibuild->GetImmValue( getOp2(I) )));
Jit->WriteExceptionExit();
Jit->SetJumpTarget(cont);
@ -2179,7 +2179,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
{
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->ABI_CallFunction((void *)&CoreTiming::Idle);
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc));
Jit->WriteExceptionExit();
break;
}
@ -2187,14 +2187,14 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
{
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->LOCK();
Jit->OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL));
Jit->MOV(32, M(&PC), Imm32(InstLoc + 4));
Jit->OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_SYSCALL));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc + 4));
Jit->WriteExceptionExit();
break;
}
case InterpreterBranch:
{
Jit->MOV(32, R(EAX), M(&NPC));
Jit->MOV(32, R(EAX), PPCSTATE(npc));
Jit->WriteExitDestInOpArg(R(EAX));
break;
}
@ -2203,16 +2203,16 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
// See Interpreter rfi for details
const u32 mask = 0x87C0FFFF;
// MSR = (MSR & ~mask) | (SRR1 & mask);
Jit->MOV(32, R(EAX), M(&MSR));
Jit->MOV(32, R(ECX), M(&SRR1));
Jit->MOV(32, R(EAX), PPCSTATE(msr));
Jit->MOV(32, R(ECX), PPCSTATE_SRR1);
Jit->AND(32, R(EAX), Imm32(~mask));
Jit->AND(32, R(ECX), Imm32(mask));
Jit->OR(32, R(EAX), R(ECX));
// MSR &= 0xFFFBFFFF; // Mask used to clear the bit MSR[13]
Jit->AND(32, R(EAX), Imm32(0xFFFBFFFF));
Jit->MOV(32, M(&MSR), R(EAX));
Jit->MOV(32, PPCSTATE(msr), R(EAX));
// NPC = SRR0;
Jit->MOV(32, R(EAX), M(&SRR0));
Jit->MOV(32, R(EAX), PPCSTATE_SRR0);
Jit->WriteRfiExitDestInOpArg(R(EAX));
break;
}
@ -2220,14 +2220,14 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
{
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
//This instruction uses FPU - needs to add FP exception bailout
Jit->TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit
Jit->TEST(32, PPCSTATE(msr), Imm32(1 << 13)); // Test FP enabled bit
FixupBranch b1 = Jit->J_CC(CC_NZ);
// If a FPU exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->SUB(32, M(&PowerPC::ppcState.downcount), Imm32(Jit->js.downcountAmount));
Jit->OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc));
Jit->SUB(32, PPCSTATE(downcount), Imm32(Jit->js.downcountAmount));
Jit->OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
Jit->WriteExceptionExit();
Jit->SetJumpTarget(b1);
break;
@ -2235,12 +2235,12 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
case DSIExceptionCheck:
{
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI));
Jit->TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_DSI));
FixupBranch noMemException = Jit->J_CC(CC_Z);
// If a memory exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc));
Jit->WriteExceptionExit();
Jit->SetJumpTarget(noMemException);
break;
@ -2250,8 +2250,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
// Address of instruction could not be translated
Jit->MOV(32, M(&NPC), Imm32(InstLoc));
Jit->OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI));
Jit->MOV(32, PPCSTATE(npc), Imm32(InstLoc));
Jit->OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI));
// Remove the invalid instruction from the icache, forcing a recompile
Jit->MOV(64, R(RAX), ImmPtr(jit->GetBlockCache()->GetICachePtr(InstLoc)));
@ -2263,16 +2263,16 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
{
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
Jit->TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = Jit->J_CC(CC_NZ);
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
Jit->TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
Jit->TEST(32, PPCSTATE(msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = Jit->J_CC(CC_Z);
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc));
Jit->WriteExceptionExit();
Jit->SetJumpTarget(noCPInt);
@ -2285,7 +2285,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress)
{
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->MOV(32, PPCSTATE(pc), Imm32(InstLoc));
Jit->ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = Jit->J_CC(CC_Z);

View File

@ -313,14 +313,14 @@ void JitIL::WriteCallInterpreter(UGeckoInstruction inst)
{
if (js.isLastInstruction)
{
MOV(32, M(&PC), Imm32(js.compilerPC));
MOV(32, M(&NPC), Imm32(js.compilerPC + 4));
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
MOV(32, PPCSTATE(npc), Imm32(js.compilerPC + 4));
}
Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst);
ABI_CallFunctionC((void*)instr, inst.hex);
if (js.isLastInstruction)
{
MOV(32, R(EAX), M(&NPC));
MOV(32, R(EAX), PPCSTATE(npc));
WriteRfiExitDestInOpArg(R(EAX));
}
}
@ -341,7 +341,7 @@ void JitIL::FallBackToInterpreter(UGeckoInstruction _inst)
void JitIL::HLEFunction(UGeckoInstruction _inst)
{
ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex);
MOV(32, R(EAX), M(&NPC));
MOV(32, R(EAX), PPCSTATE(npc));
WriteExitDestInOpArg(R(EAX));
}
@ -398,7 +398,7 @@ void JitIL::WriteExit(u32 destination)
{
ABI_CallFunction((void *)JitILProfiler::End);
}
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
@ -417,7 +417,7 @@ void JitIL::WriteExit(u32 destination)
}
else
{
MOV(32, M(&PC), Imm32(destination));
MOV(32, PPCSTATE(pc), Imm32(destination));
JMP(asm_routines.dispatcher, true);
}
b->linkData.push_back(linkData);
@ -425,27 +425,27 @@ void JitIL::WriteExit(u32 destination)
void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg)
{
MOV(32, M(&PC), arg);
MOV(32, PPCSTATE(pc), arg);
Cleanup();
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
{
ABI_CallFunction((void *)JitILProfiler::End);
}
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
void JitIL::WriteRfiExitDestInOpArg(const Gen::OpArg& arg)
{
MOV(32, M(&PC), arg);
MOV(32, M(&NPC), arg);
MOV(32, PPCSTATE(pc), arg);
MOV(32, PPCSTATE(npc), arg);
Cleanup();
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling)
{
ABI_CallFunction((void *)JitILProfiler::End);
}
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
@ -456,10 +456,10 @@ void JitIL::WriteExceptionExit()
{
ABI_CallFunction((void *)JitILProfiler::End);
}
MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX));
MOV(32, R(EAX), PPCSTATE(pc));
MOV(32, PPCSTATE(npc), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&PowerPC::ppcState.downcount), Imm32(js.downcountAmount));
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
JMP(asm_routines.dispatcher, true);
}
@ -548,7 +548,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
// Downcount flag check. The last block decremented downcounter, and the flag should still be available.
FixupBranch skip = J_CC(CC_NBE);
MOV(32, M(&PC), Imm32(js.blockStart));
MOV(32, PPCSTATE(pc), Imm32(js.blockStart));
JMP(asm_routines.doTiming, true); // downcount hit zero - go doTiming.
SetJumpTarget(skip);
@ -561,13 +561,13 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (js.fpa.any)
{
// This block uses FPU - needs to add FP exception bailout
TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit
TEST(32, PPCSTATE(msr), Imm32(1 << 13)); //Test FP enabled bit
FixupBranch b1 = J_CC(CC_NZ);
// If a FPU exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
MOV(32, M(&PC), Imm32(js.blockStart));
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
MOV(32, PPCSTATE(pc), Imm32(js.blockStart));
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
WriteExceptionExit();
SetJumpTarget(b1);
@ -635,7 +635,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
HLEFunction(function);
if (type == HLE::HLE_HOOK_REPLACE)
{
MOV(32, R(EAX), M(&NPC));
MOV(32, R(EAX), PPCSTATE(npc));
jit->js.downcountAmount += jit->js.st.numCycles;
WriteExitDestInOpArg(R(EAX));
break;

View File

@ -93,20 +93,20 @@ void CommonAsmRoutines::GenFrsqrte()
// Exception flags for zero input.
SetJumpTarget(zero);
TEST(32, M(&FPSCR), Imm32(FPSCR_ZX));
TEST(32, PPCSTATE(fpscr), Imm32(FPSCR_ZX));
FixupBranch skip_set_fx1 = J_CC(CC_NZ);
OR(32, M(&FPSCR), Imm32(FPSCR_FX));
OR(32, PPCSTATE(fpscr), Imm32(FPSCR_FX));
SetJumpTarget(skip_set_fx1);
OR(32, M(&FPSCR), Imm32(FPSCR_ZX));
OR(32, PPCSTATE(fpscr), Imm32(FPSCR_ZX));
FixupBranch complex3 = J();
// Exception flags for negative input.
SetJumpTarget(negative);
TEST(32, M(&FPSCR), Imm32(FPSCR_VXSQRT));
TEST(32, PPCSTATE(fpscr), Imm32(FPSCR_VXSQRT));
FixupBranch skip_set_fx2 = J_CC(CC_NZ);
OR(32, M(&FPSCR), Imm32(FPSCR_FX));
OR(32, PPCSTATE(fpscr), Imm32(FPSCR_FX));
SetJumpTarget(skip_set_fx2);
OR(32, M(&FPSCR), Imm32(FPSCR_VXSQRT));
OR(32, PPCSTATE(fpscr), Imm32(FPSCR_VXSQRT));
SetJumpTarget(complex1);
SetJumpTarget(complex2);
@ -162,11 +162,11 @@ void CommonAsmRoutines::GenFres()
// Exception flags for zero input.
SetJumpTarget(zero);
TEST(32, M(&FPSCR), Imm32(FPSCR_ZX));
TEST(32, PPCSTATE(fpscr), Imm32(FPSCR_ZX));
FixupBranch skip_set_fx1 = J_CC(CC_NZ);
OR(32, M(&FPSCR), Imm32(FPSCR_FX));
OR(32, PPCSTATE(fpscr), Imm32(FPSCR_FX));
SetJumpTarget(skip_set_fx1);
OR(32, M(&FPSCR), Imm32(FPSCR_ZX));
OR(32, PPCSTATE(fpscr), Imm32(FPSCR_ZX));
SetJumpTarget(complex1);
SetJumpTarget(complex2);

View File

@ -113,7 +113,7 @@ const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info, u32 r
// check anyway.
// PC is used by memory watchpoints (if enabled) or to print accurate PC locations in debug logs
MOV(32, M(&PC), Imm32(pc));
MOV(32, PPCSTATE(pc), Imm32(pc));
if (dataReg == ABI_PARAM2)
PanicAlert("Incorrect use of SafeWriteRegToReg");

View File

@ -370,6 +370,6 @@ using namespace Gen;
void JitBlockCache::WriteDestroyBlock(const u8* location, u32 address)
{
XEmitter emit((u8 *)location);
emit.MOV(32, M(&PC), Imm32(address));
emit.MOV(32, PPCSTATE(pc), Imm32(address));
emit.JMP(jit->GetAsmRoutines()->dispatcher, true);
}

View File

@ -468,7 +468,7 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce
TEST(32, R(reg_addr), Imm32(mem_mask));
FixupBranch fast = J_CC(CC_Z, true);
// PC is used by memory watchpoints (if enabled) or to print accurate PC locations in debug logs
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC));
bool noProlog = (0 != (flags & SAFE_LOADSTORE_NO_PROLOG));
bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP);
ABI_PushRegistersAndAdjustStack(registersInUse, noProlog);
@ -718,7 +718,7 @@ static const u64 GC_ALIGNED16(psDoubleNoSign[2]) = {0x7FFFFFFFFFFFFFFFULL, 0};
// quite that necessary.
void EmuCodeBlock::SetFPRF(Gen::X64Reg xmm)
{
AND(32, M(&FPSCR), Imm32(~FPRF_MASK));
AND(32, PPCSTATE(fpscr), Imm32(~FPRF_MASK));
FixupBranch continue1, continue2, continue3, continue4;
if (cpu_info.bSSE4_1)
@ -799,24 +799,24 @@ void EmuCodeBlock::SetFPRF(Gen::X64Reg xmm)
SetJumpTarget(continue3);
SetJumpTarget(continue4);
SHL(32, R(EAX), Imm8(FPRF_SHIFT));
OR(32, M(&FPSCR), R(EAX));
OR(32, PPCSTATE(fpscr), R(EAX));
}
void EmuCodeBlock::JitClearCA()
{
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0
AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0
}
void EmuCodeBlock::JitSetCA()
{
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_CA_MASK)); //XER.CA = 1
OR(32, PPCSTATE(spr[SPR_XER]), Imm32(XER_CA_MASK)); //XER.CA = 1
}
void EmuCodeBlock::JitClearCAOV(bool oe)
{
if (oe)
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_CA_MASK & ~XER_OV_MASK)); //XER.CA, XER.OV = 0
AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~XER_CA_MASK & ~XER_OV_MASK)); //XER.CA, XER.OV = 0
else
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0
AND(32, PPCSTATE(spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0
}

View File

@ -13,13 +13,23 @@ namespace MMIO { class Mapping; }
#define MEMCHECK_START \
Gen::FixupBranch memException; \
if (jit->js.memcheck) \
{ TEST(32, Gen::M((void *)&PowerPC::ppcState.Exceptions), Gen::Imm32(EXCEPTION_DSI)); \
{ TEST(32, PPCSTATE(Exceptions), Gen::Imm32(EXCEPTION_DSI)); \
memException = J_CC(Gen::CC_NZ, true); }
#define MEMCHECK_END \
if (jit->js.memcheck) \
SetJumpTarget(memException);
// We offset by 0x80 because the range of one byte memory offsets is
// -0x80..0x7f.
#define PPCSTATE(x) MDisp(RBP, \
(int) ((char *) &PowerPC::ppcState.x - (char *) &PowerPC::ppcState) - 0x80)
// In case you want to disable the ppcstate register:
// #define PPCSTATE(x) M((void*) &PowerPC::ppcState.x)
#define PPCSTATE_LR PPCSTATE(spr[SPR_LR])
#define PPCSTATE_CTR PPCSTATE(spr[SPR_CTR])
#define PPCSTATE_SRR0 PPCSTATE(spr[SPR_SRR0])
#define PPCSTATE_SRR1 PPCSTATE(spr[SPR_SRR1])
// Like XCodeBlock but has some utilities for memory access.
class EmuCodeBlock : public Gen::X64CodeBlock

View File

@ -4,6 +4,8 @@
#pragma once
#include <tuple>
#include "Common/BreakPoints.h"
#include "Common/Common.h"
@ -30,11 +32,6 @@ struct GC_ALIGNED64(PowerPCState)
{
u32 gpr[32]; // General purpose registers. r1 = stack pointer.
// The paired singles are strange : PS0 is stored in the full 64 bits of each FPR
// but ps calculations are only done in 32-bit precision, and PS1 is only 32 bits.
// Since we want to use SIMD, SSE2 is the only viable alternative - 2x double.
u64 ps[32][2];
u32 pc; // program counter
u32 npc;
@ -64,6 +61,20 @@ struct GC_ALIGNED64(PowerPCState)
// This variable should be inside of the CoreTiming namespace if we wanted to be correct.
int downcount;
#if _M_X86_64
// This member exists for the purpose of an assertion in x86 JitBase.cpp
// that its offset <= 0x100. To minimize code size on x86, we want as much
// useful stuff in the one-byte offset range as possible - which is why ps
// is sitting down here. It currently doesn't make a difference on other
// supported architectures.
std::tuple<> above_fits_in_first_0x100;
#endif
// The paired singles are strange : PS0 is stored in the full 64 bits of each FPR
// but ps calculations are only done in 32-bit precision, and PS1 is only 32 bits.
// Since we want to use SIMD, SSE2 is the only viable alternative - 2x double.
GC_ALIGNED16(u64 ps[32][2]);
u32 sr[16]; // Segment registers.
// special purpose registers - controls quantizers, DMA, and lots of other misc extensions.
@ -84,6 +95,10 @@ struct GC_ALIGNED64(PowerPCState)
InstructionCache iCache;
};
#if _M_X86_64
static_assert(offsetof(PowerPC::PowerPCState, above_fits_in_first_0x100) <= 0x100, "top of PowerPCState too big");
#endif
enum CPUState
{
CPU_RUNNING = 0,