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
commit 48891c6359
17 changed files with 238 additions and 212 deletions

View file

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

View file

@ -29,6 +29,7 @@ void Jit64AsmRoutineManager::Generate()
// Two statically allocated registers. // Two statically allocated registers.
MOV(64, R(RBX), Imm64((u64)Memory::base)); 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(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(); const u8* outerLoop = GetCodePtr();
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance)); ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
@ -55,7 +56,7 @@ void Jit64AsmRoutineManager::Generate()
SetJumpTarget(skipToRealDispatch); SetJumpTarget(skipToRealDispatch);
dispatcherNoCheck = GetCodePtr(); dispatcherNoCheck = GetCodePtr();
MOV(32, R(EAX), M(&PowerPC::ppcState.pc)); MOV(32, R(EAX), PPCSTATE(pc));
dispatcherPcInEAX = GetCodePtr(); dispatcherPcInEAX = GetCodePtr();
u32 mask = 0; u32 mask = 0;
@ -113,7 +114,7 @@ void Jit64AsmRoutineManager::Generate()
SetJumpTarget(notfound); SetJumpTarget(notfound);
//Ok, no block, let's jit //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); CALL((void *)&Jit);
JMP(dispatcherNoCheck); // no point in special casing this JMP(dispatcherNoCheck); // no point in special casing this
@ -122,10 +123,10 @@ void Jit64AsmRoutineManager::Generate()
doTiming = GetCodePtr(); doTiming = GetCodePtr();
// Test external exceptions. // 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); FixupBranch noExtException = J_CC(CC_Z);
MOV(32, R(EAX), M(&PC)); MOV(32, R(EAX), PPCSTATE(pc));
MOV(32, M(&NPC), R(EAX)); MOV(32, PPCSTATE(npc), R(EAX));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions)); ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExternalExceptions));
SetJumpTarget(noExtException); SetJumpTarget(noExtException);

View file

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

View file

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

View file

@ -248,7 +248,7 @@ void Jit64::fcmpx(UGeckoInstruction inst)
fpr.BindToRegister(b, true); fpr.BindToRegister(b, true);
if (fprf) 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? // 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)); 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))); MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_EQ)));
if (fprf) if (fprf)
OR(32, M(&FPSCR), Imm32(CR_EQ << FPRF_SHIFT)); OR(32, PPCSTATE(fpscr), Imm32(CR_EQ << FPRF_SHIFT));
continue1 = J(); continue1 = J();
SetJumpTarget(pNaN); SetJumpTarget(pNaN);
MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_SO))); MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_SO)));
if (fprf) if (fprf)
OR(32, M(&FPSCR), Imm32(CR_SO << FPRF_SHIFT)); OR(32, PPCSTATE(fpscr), Imm32(CR_SO << FPRF_SHIFT));
if (a != b) if (a != b)
{ {
@ -289,13 +289,13 @@ void Jit64::fcmpx(UGeckoInstruction inst)
SetJumpTarget(pGreater); SetJumpTarget(pGreater);
MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_GT))); MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_GT)));
if (fprf) if (fprf)
OR(32, M(&FPSCR), Imm32(CR_GT << FPRF_SHIFT)); OR(32, PPCSTATE(fpscr), Imm32(CR_GT << FPRF_SHIFT));
continue3 = J(); continue3 = J();
SetJumpTarget(pLesser); SetJumpTarget(pLesser);
MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_LT))); MOV(64, R(RAX), Imm64(PPCCRToInternal(CR_LT)));
if (fprf) if (fprf)
OR(32, M(&FPSCR), Imm32(CR_LT << FPRF_SHIFT)); OR(32, PPCSTATE(fpscr), Imm32(CR_LT << FPRF_SHIFT));
} }
SetJumpTarget(continue1); SetJumpTarget(continue1);
@ -305,7 +305,7 @@ void Jit64::fcmpx(UGeckoInstruction inst)
SetJumpTarget(continue3); SetJumpTarget(continue3);
} }
MOV(64, M(&PowerPC::ppcState.cr_val[crf]), R(RAX)); MOV(64, PPCSTATE(cr_val[crf]), R(RAX));
fpr.UnlockAll(); fpr.UnlockAll();
} }

View file

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

View file

@ -123,7 +123,7 @@ void Jit64::lXXx(UGeckoInstruction inst)
ABI_PopRegistersAndAdjustStack(registersInUse, false); ABI_PopRegistersAndAdjustStack(registersInUse, false);
// ! we must continue executing of the loop after exception handling, maybe there is still 0 in r0 // ! 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(); WriteExceptionExit();
SetJumpTarget(noIdle); SetJumpTarget(noIdle);
@ -331,7 +331,7 @@ void Jit64::stX(UGeckoInstruction inst)
if ((addr & 0xFFFFF000) == 0xCC008000 && jo.optimizeGatherPipe) if ((addr & 0xFFFFF000) == 0xCC008000 && jo.optimizeGatherPipe)
{ {
// 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)); MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC));
gpr.FlushLockX(ABI_PARAM1); gpr.FlushLockX(ABI_PARAM1);
MOV(32, R(ABI_PARAM1), gpr.R(s)); MOV(32, R(ABI_PARAM1), gpr.R(s));
@ -367,7 +367,7 @@ void Jit64::stX(UGeckoInstruction inst)
else else
{ {
// 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)); MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC));
u32 registersInUse = CallerSavedRegistersInUse(); u32 registersInUse = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(registersInUse, false); 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 // UU[SCALE]UUUUU[TYPE] where SCALE is 6 bits and TYPE is 3 bits, so we have to AND with
// 0b0011111100000111, or 0x3F07. // 0b0011111100000111, or 0x3F07.
MOV(32, R(EAX), Imm32(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)); MOVZX(32, 8, EDX, R(AL));
// FIXME: Fix ModR/M encoding to allow [EDX*4+disp32] without a base register! // 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) switch (bit)
{ {
case CR_SO_BIT: // check bit 61 set 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)); SETcc(negate ? CC_NC : CC_C, R(out));
break; break;
case CR_EQ_BIT: // check bits 31-0 == 0 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)); SETcc(negate ? CC_NZ : CC_Z, R(out));
break; break;
case CR_GT_BIT: // check val > 0 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)); SETcc(negate ? CC_NG : CC_G, R(out));
break; break;
case CR_LT_BIT: // check bit 62 set 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)); SETcc(negate ? CC_NC : CC_C, R(out));
break; 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) 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)); MOVZX(32, 8, in, R(in));
switch (bit) switch (bit)
@ -75,7 +75,7 @@ void Jit64::SetCRFieldBit(int field, int bit, Gen::X64Reg in)
} }
BTS(64, R(ABI_PARAM1), Imm8(32)); 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) 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) switch (bit)
{ {
case CR_SO_BIT: // check bit 61 set 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); return J_CC(jump_if_set ? CC_C : CC_NC, true);
case CR_EQ_BIT: // check bits 31-0 == 0 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); return J_CC(jump_if_set ? CC_Z : CC_NZ, true);
case CR_GT_BIT: // check val > 0 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); return J_CC(jump_if_set ? CC_G : CC_LE, true);
case CR_LT_BIT: // check bit 62 set 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); return J_CC(jump_if_set ? CC_C : CC_NC, true);
default: default:
@ -154,7 +154,7 @@ void Jit64::mtspr(UGeckoInstruction inst)
gpr.Lock(d); gpr.Lock(d);
gpr.BindToRegister(d, true, false); 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(); gpr.UnlockAll();
} }
@ -190,7 +190,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
LEA(64, RAX, MComplex(RAX, RDX, SCALE_1, offset)); LEA(64, RAX, MComplex(RAX, RDX, SCALE_1, offset));
else else
ADD(64, R(RAX), R(RDX)); 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 // Two calls of TU/TL next to each other are extremely common in typical usage, so merge them
// if we can. // if we can.
@ -234,7 +234,7 @@ void Jit64::mfspr(UGeckoInstruction inst)
default: default:
gpr.Lock(d); gpr.Lock(d);
gpr.BindToRegister(d, false); gpr.BindToRegister(d, false);
MOV(32, gpr.R(d), M(&PowerPC::ppcState.spr[iIndex])); MOV(32, gpr.R(d), PPCSTATE(spr[iIndex]));
break; break;
} }
gpr.UnlockAll(); gpr.UnlockAll();
@ -251,7 +251,7 @@ void Jit64::mtmsr(UGeckoInstruction inst)
gpr.Lock(inst.RS); gpr.Lock(inst.RS);
gpr.BindToRegister(inst.RS, true, false); 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.UnlockAll();
gpr.Flush(); gpr.Flush();
fpr.Flush(); fpr.Flush();
@ -259,17 +259,17 @@ void Jit64::mtmsr(UGeckoInstruction inst)
// If some exceptions are pending and EE are now enabled, force checking // If some exceptions are pending and EE are now enabled, force checking
// external exceptions when going out of mtmsr in order to execute delayed // external exceptions when going out of mtmsr in order to execute delayed
// interrupts as soon as possible. // interrupts as soon as possible.
TEST(32, M(&MSR), Imm32(0x8000)); TEST(32, PPCSTATE(msr), Imm32(0x8000));
FixupBranch eeDisabled = J_CC(CC_Z); 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); FixupBranch noExceptionsPending = J_CC(CC_Z);
// Check if a CP interrupt is waiting and keep the GPU emulation in sync (issue 4336) // 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)); TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP));
FixupBranch cpInt = J_CC(CC_NZ); FixupBranch cpInt = J_CC(CC_NZ);
MOV(32, M(&PC), Imm32(js.compilerPC + 4)); MOV(32, PPCSTATE(pc), Imm32(js.compilerPC + 4));
WriteExternalExceptionExit(); WriteExternalExceptionExit();
SetJumpTarget(cpInt); SetJumpTarget(cpInt);
@ -288,7 +288,7 @@ void Jit64::mfmsr(UGeckoInstruction inst)
//Privileged? //Privileged?
gpr.Lock(inst.RD); gpr.Lock(inst.RD);
gpr.BindToRegister(inst.RD, false, true); gpr.BindToRegister(inst.RD, false, true);
MOV(32, gpr.R(inst.RD), M(&MSR)); MOV(32, gpr.R(inst.RD), PPCSTATE(msr));
gpr.UnlockAll(); gpr.UnlockAll();
} }
@ -318,7 +318,7 @@ void Jit64::mfcr(UGeckoInstruction inst)
if (i != 0) if (i != 0)
SHL(32, gpr.R(d), Imm8(4)); 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 // EQ: Bits 31-0 == 0; set flag bit 1
TEST(32, R(cr_val), R(cr_val)); TEST(32, R(cr_val), R(cr_val));
@ -360,12 +360,12 @@ void Jit64::mtcrf(UGeckoInstruction inst)
u64 newcrval = PPCCRToInternal(newcr); u64 newcrval = PPCCRToInternal(newcr);
if ((s64)newcrval == (s32)newcrval) 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 else
{ {
MOV(64, R(RAX), Imm64(newcrval)); 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) if (i != 0)
AND(32, R(EAX), Imm8(0xF)); AND(32, R(EAX), Imm8(0xF));
MOV(64, R(EAX), MScaled(EAX, SCALE_8, (u32)(u64)m_crTable)); 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(); gpr.UnlockAll();
@ -400,8 +400,8 @@ void Jit64::mcrf(UGeckoInstruction inst)
// USES_CR // USES_CR
if (inst.CRFS != inst.CRFD) if (inst.CRFS != inst.CRFD)
{ {
MOV(64, R(EAX), M(&PowerPC::ppcState.cr_val[inst.CRFS])); MOV(64, R(EAX), PPCSTATE(cr_val[inst.CRFS]));
MOV(64, M(&PowerPC::ppcState.cr_val[inst.CRFD]), R(EAX)); MOV(64, PPCSTATE(cr_val[inst.CRFD]), R(EAX));
} }
} }
@ -413,14 +413,14 @@ void Jit64::mcrxr(UGeckoInstruction inst)
// USES_CR // USES_CR
// Copy XER[0-3] into CR[inst.CRFD] // 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)); SHR(32, R(EAX), Imm8(28));
MOV(64, R(EAX), MScaled(EAX, SCALE_8, (u32)(u64)m_crTable)); 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] // 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) void Jit64::crXXX(UGeckoInstruction inst)

View file

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

View file

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

View file

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

View file

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

View file

@ -370,6 +370,6 @@ using namespace Gen;
void JitBlockCache::WriteDestroyBlock(const u8* location, u32 address) void JitBlockCache::WriteDestroyBlock(const u8* location, u32 address)
{ {
XEmitter emit((u8 *)location); XEmitter emit((u8 *)location);
emit.MOV(32, M(&PC), Imm32(address)); emit.MOV(32, PPCSTATE(pc), Imm32(address));
emit.JMP(jit->GetAsmRoutines()->dispatcher, true); 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)); TEST(32, R(reg_addr), Imm32(mem_mask));
FixupBranch fast = J_CC(CC_Z, true); FixupBranch fast = J_CC(CC_Z, true);
// PC is used by memory watchpoints (if enabled) or to print accurate PC locations in debug logs // 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 noProlog = (0 != (flags & SAFE_LOADSTORE_NO_PROLOG));
bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP); bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP);
ABI_PushRegistersAndAdjustStack(registersInUse, noProlog); ABI_PushRegistersAndAdjustStack(registersInUse, noProlog);
@ -718,7 +718,7 @@ static const u64 GC_ALIGNED16(psDoubleNoSign[2]) = {0x7FFFFFFFFFFFFFFFULL, 0};
// quite that necessary. // quite that necessary.
void EmuCodeBlock::SetFPRF(Gen::X64Reg xmm) 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; FixupBranch continue1, continue2, continue3, continue4;
if (cpu_info.bSSE4_1) if (cpu_info.bSSE4_1)
@ -799,24 +799,24 @@ void EmuCodeBlock::SetFPRF(Gen::X64Reg xmm)
SetJumpTarget(continue3); SetJumpTarget(continue3);
SetJumpTarget(continue4); SetJumpTarget(continue4);
SHL(32, R(EAX), Imm8(FPRF_SHIFT)); SHL(32, R(EAX), Imm8(FPRF_SHIFT));
OR(32, M(&FPSCR), R(EAX)); OR(32, PPCSTATE(fpscr), R(EAX));
} }
void EmuCodeBlock::JitClearCA() 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() 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) void EmuCodeBlock::JitClearCAOV(bool oe)
{ {
if (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 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 \ #define MEMCHECK_START \
Gen::FixupBranch memException; \ Gen::FixupBranch memException; \
if (jit->js.memcheck) \ 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); } memException = J_CC(Gen::CC_NZ, true); }
#define MEMCHECK_END \ #define MEMCHECK_END \
if (jit->js.memcheck) \ if (jit->js.memcheck) \
SetJumpTarget(memException); 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. // Like XCodeBlock but has some utilities for memory access.
class EmuCodeBlock : public Gen::X64CodeBlock class EmuCodeBlock : public Gen::X64CodeBlock

View file

@ -4,6 +4,8 @@
#pragma once #pragma once
#include <tuple>
#include "Common/BreakPoints.h" #include "Common/BreakPoints.h"
#include "Common/Common.h" #include "Common/Common.h"
@ -30,11 +32,6 @@ struct GC_ALIGNED64(PowerPCState)
{ {
u32 gpr[32]; // General purpose registers. r1 = stack pointer. 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 pc; // program counter
u32 npc; 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. // This variable should be inside of the CoreTiming namespace if we wanted to be correct.
int downcount; 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. u32 sr[16]; // Segment registers.
// special purpose registers - controls quantizers, DMA, and lots of other misc extensions. // special purpose registers - controls quantizers, DMA, and lots of other misc extensions.
@ -84,6 +95,10 @@ struct GC_ALIGNED64(PowerPCState)
InstructionCache iCache; 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 enum CPUState
{ {
CPU_RUNNING = 0, CPU_RUNNING = 0,