PowerPC: Make the PowerPCState's msr member variable a UReg_MSR instance
Gets rid of the need to construct UReg_MSR values around the the actual member in order to query information from it (without using shifts and masks). This makes it more concise in some areas, while helping with readability in some other places (such as copying the ILE bit to the LE bit in the exception checking functions).
This commit is contained in:
parent
58b96eeb9d
commit
ffcf107dd2
|
@ -269,10 +269,9 @@ bool CBoot::Load_BS2(const std::string& boot_rom_filename)
|
||||||
PowerPC::ppcState.gpr[4] = 0x00002030;
|
PowerPC::ppcState.gpr[4] = 0x00002030;
|
||||||
PowerPC::ppcState.gpr[5] = 0x0000009c;
|
PowerPC::ppcState.gpr[5] = 0x0000009c;
|
||||||
|
|
||||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
MSR.FP = 1;
|
||||||
m_MSR.FP = 1;
|
MSR.DR = 1;
|
||||||
m_MSR.DR = 1;
|
MSR.IR = 1;
|
||||||
m_MSR.IR = 1;
|
|
||||||
|
|
||||||
PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464;
|
PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464;
|
||||||
PowerPC::ppcState.spr[SPR_IBAT3U] = 0xfff0001f;
|
PowerPC::ppcState.spr[SPR_IBAT3U] = 0xfff0001f;
|
||||||
|
|
|
@ -55,11 +55,10 @@ void CBoot::RunFunction(u32 address)
|
||||||
|
|
||||||
void CBoot::SetupMSR()
|
void CBoot::SetupMSR()
|
||||||
{
|
{
|
||||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
MSR.FP = 1;
|
||||||
m_MSR.FP = 1;
|
MSR.DR = 1;
|
||||||
m_MSR.DR = 1;
|
MSR.IR = 1;
|
||||||
m_MSR.IR = 1;
|
MSR.EE = 1;
|
||||||
m_MSR.EE = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBoot::SetupBAT(bool is_wii)
|
void CBoot::SetupBAT(bool is_wii)
|
||||||
|
|
|
@ -284,7 +284,7 @@ bool Kernel::BootstrapPPC(const std::string& boot_content_path)
|
||||||
// NAND titles start with address translation off at 0x3400 (via the PPC bootstub)
|
// NAND titles start with address translation off at 0x3400 (via the PPC bootstub)
|
||||||
// The state of other CPU registers (like the BAT registers) doesn't matter much
|
// The state of other CPU registers (like the BAT registers) doesn't matter much
|
||||||
// because the realmode code at 0x3400 initializes everything itself anyway.
|
// because the realmode code at 0x3400 initializes everything itself anyway.
|
||||||
MSR = 0;
|
MSR.Hex = 0;
|
||||||
PC = 0x3400;
|
PC = 0x3400;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -65,7 +65,7 @@ bool Load()
|
||||||
|
|
||||||
const PowerPC::CoreMode core_mode = PowerPC::GetMode();
|
const PowerPC::CoreMode core_mode = PowerPC::GetMode();
|
||||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||||
MSR = 0;
|
MSR.Hex = 0;
|
||||||
PC = 0x3400;
|
PC = 0x3400;
|
||||||
NOTICE_LOG(IOS, "Loaded MIOS and bootstrapped PPC.");
|
NOTICE_LOG(IOS, "Loaded MIOS and bootstrapped PPC.");
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ static void ApplyPatches(const std::vector<Patch>& patches)
|
||||||
// We require at least 2 stack frames, if the stack is shallower than that then it won't work.
|
// We require at least 2 stack frames, if the stack is shallower than that then it won't work.
|
||||||
static bool IsStackSane()
|
static bool IsStackSane()
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(UReg_MSR(MSR).DR && UReg_MSR(MSR).IR);
|
DEBUG_ASSERT(MSR.DR && MSR.IR);
|
||||||
|
|
||||||
// Check the stack pointer
|
// Check the stack pointer
|
||||||
u32 SP = GPR(1);
|
u32 SP = GPR(1);
|
||||||
|
@ -220,13 +220,12 @@ bool ApplyFramePatches()
|
||||||
// callback hook we can end up catching the game in an exception vector.
|
// callback hook we can end up catching the game in an exception vector.
|
||||||
// We deal with this by returning false so that SystemTimers will reschedule us in a few cycles
|
// We deal with this by returning false so that SystemTimers will reschedule us in a few cycles
|
||||||
// where we can try again after the CPU hopefully returns back to the normal instruction flow.
|
// where we can try again after the CPU hopefully returns back to the normal instruction flow.
|
||||||
UReg_MSR msr = MSR;
|
if (!MSR.DR || !MSR.IR || !IsStackSane())
|
||||||
if (!msr.DR || !msr.IR || !IsStackSane())
|
|
||||||
{
|
{
|
||||||
DEBUG_LOG(
|
DEBUG_LOG(
|
||||||
ACTIONREPLAY,
|
ACTIONREPLAY,
|
||||||
"Need to retry later. CPU configuration is currently incorrect. PC = 0x%08X, MSR = 0x%08X",
|
"Need to retry later. CPU configuration is currently incorrect. PC = 0x%08X, MSR = 0x%08X",
|
||||||
PC, MSR);
|
PC, MSR.Hex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,8 +150,7 @@ static void WriteBrokenBlockNPC(UGeckoInstruction data)
|
||||||
|
|
||||||
static bool CheckFPU(u32 data)
|
static bool CheckFPU(u32 data)
|
||||||
{
|
{
|
||||||
UReg_MSR msr{MSR};
|
if (!MSR.FP)
|
||||||
if (!msr.FP)
|
|
||||||
{
|
{
|
||||||
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
|
|
|
@ -446,7 +446,7 @@ static void gdb_read_register()
|
||||||
wbe32hex(reply, PC);
|
wbe32hex(reply, PC);
|
||||||
break;
|
break;
|
||||||
case 65:
|
case 65:
|
||||||
wbe32hex(reply, MSR);
|
wbe32hex(reply, MSR.Hex);
|
||||||
break;
|
break;
|
||||||
case 66:
|
case 66:
|
||||||
wbe32hex(reply, PowerPC::GetCR());
|
wbe32hex(reply, PowerPC::GetCR());
|
||||||
|
@ -531,7 +531,7 @@ static void gdb_write_register()
|
||||||
PC = re32hex(bufptr);
|
PC = re32hex(bufptr);
|
||||||
break;
|
break;
|
||||||
case 65:
|
case 65:
|
||||||
MSR = re32hex(bufptr);
|
MSR.Hex = re32hex(bufptr);
|
||||||
break;
|
break;
|
||||||
case 66:
|
case 66:
|
||||||
PowerPC::SetCR(re32hex(bufptr));
|
PowerPC::SetCR(re32hex(bufptr));
|
||||||
|
|
|
@ -96,8 +96,7 @@ static void Trace(UGeckoInstruction& inst)
|
||||||
"INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016lx FPSCR: %08x MSR: %08x LR: "
|
"INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016lx FPSCR: %08x MSR: %08x LR: "
|
||||||
"%08x %s %08x %s",
|
"%08x %s %08x %s",
|
||||||
PC, SRR0, SRR1, (unsigned long)PowerPC::ppcState.cr_val[0], PowerPC::ppcState.fpscr,
|
PC, SRR0, SRR1, (unsigned long)PowerPC::ppcState.cr_val[0], PowerPC::ppcState.fpscr,
|
||||||
PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), inst.hex,
|
MSR.Hex, PowerPC::ppcState.spr[8], regs.c_str(), inst.hex, ppc_inst.c_str());
|
||||||
ppc_inst.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Interpreter::SingleStepInner()
|
int Interpreter::SingleStepInner()
|
||||||
|
@ -153,8 +152,7 @@ int Interpreter::SingleStepInner()
|
||||||
|
|
||||||
if (m_prev_inst.hex != 0)
|
if (m_prev_inst.hex != 0)
|
||||||
{
|
{
|
||||||
const UReg_MSR msr{MSR};
|
if (MSR.FP) // If FPU is enabled, just execute
|
||||||
if (msr.FP) // If FPU is enabled, just execute
|
|
||||||
{
|
{
|
||||||
m_op_table[m_prev_inst.OPCD](m_prev_inst);
|
m_op_table[m_prev_inst.OPCD](m_prev_inst);
|
||||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||||
|
|
|
@ -119,9 +119,9 @@ void Interpreter::rfi(UGeckoInstruction inst)
|
||||||
// Restore saved bits from SRR1 to MSR.
|
// Restore saved bits from SRR1 to MSR.
|
||||||
// Gecko/Broadway can save more bits than explicitly defined in ppc spec
|
// Gecko/Broadway can save more bits than explicitly defined in ppc spec
|
||||||
const int mask = 0x87C0FFFF;
|
const int mask = 0x87C0FFFF;
|
||||||
MSR = (MSR & ~mask) | (SRR1 & mask);
|
MSR.Hex = (MSR.Hex & ~mask) | (SRR1 & mask);
|
||||||
// MSR[13] is set to 0.
|
// MSR[13] is set to 0.
|
||||||
MSR &= 0xFFFBFFFF;
|
MSR.Hex &= 0xFFFBFFFF;
|
||||||
// Here we should check if there are pending exceptions, and if their corresponding enable bits
|
// Here we should check if there are pending exceptions, and if their corresponding enable bits
|
||||||
// are set
|
// are set
|
||||||
// if above is true, we'd do:
|
// if above is true, we'd do:
|
||||||
|
|
|
@ -278,7 +278,7 @@ void Interpreter::lmw(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
u32 address = Helper_Get_EA(inst);
|
u32 address = Helper_Get_EA(inst);
|
||||||
|
|
||||||
if ((address & 0b11) != 0 || UReg_MSR{MSR}.LE)
|
if ((address & 0b11) != 0 || MSR.LE)
|
||||||
{
|
{
|
||||||
GenerateAlignmentException(address);
|
GenerateAlignmentException(address);
|
||||||
return;
|
return;
|
||||||
|
@ -306,7 +306,7 @@ void Interpreter::stmw(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
u32 address = Helper_Get_EA(inst);
|
u32 address = Helper_Get_EA(inst);
|
||||||
|
|
||||||
if ((address & 0b11) != 0 || UReg_MSR{MSR}.LE)
|
if ((address & 0b11) != 0 || MSR.LE)
|
||||||
{
|
{
|
||||||
GenerateAlignmentException(address);
|
GenerateAlignmentException(address);
|
||||||
return;
|
return;
|
||||||
|
@ -685,7 +685,7 @@ void Interpreter::lswx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
u32 EA = Helper_Get_EA_X(inst);
|
u32 EA = Helper_Get_EA_X(inst);
|
||||||
|
|
||||||
if (UReg_MSR{MSR}.LE)
|
if (MSR.LE)
|
||||||
{
|
{
|
||||||
GenerateAlignmentException(EA);
|
GenerateAlignmentException(EA);
|
||||||
return;
|
return;
|
||||||
|
@ -867,7 +867,7 @@ void Interpreter::lswi(UGeckoInstruction inst)
|
||||||
else
|
else
|
||||||
EA = rGPR[inst.RA];
|
EA = rGPR[inst.RA];
|
||||||
|
|
||||||
if (UReg_MSR{MSR}.LE)
|
if (MSR.LE)
|
||||||
{
|
{
|
||||||
GenerateAlignmentException(EA);
|
GenerateAlignmentException(EA);
|
||||||
return;
|
return;
|
||||||
|
@ -918,7 +918,7 @@ void Interpreter::stswi(UGeckoInstruction inst)
|
||||||
else
|
else
|
||||||
EA = rGPR[inst.RA];
|
EA = rGPR[inst.RA];
|
||||||
|
|
||||||
if (UReg_MSR{MSR}.LE)
|
if (MSR.LE)
|
||||||
{
|
{
|
||||||
GenerateAlignmentException(EA);
|
GenerateAlignmentException(EA);
|
||||||
return;
|
return;
|
||||||
|
@ -958,7 +958,7 @@ void Interpreter::stswx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
u32 EA = Helper_Get_EA_X(inst);
|
u32 EA = Helper_Get_EA_X(inst);
|
||||||
|
|
||||||
if (UReg_MSR{MSR}.LE)
|
if (MSR.LE)
|
||||||
{
|
{
|
||||||
GenerateAlignmentException(EA);
|
GenerateAlignmentException(EA);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -136,7 +136,7 @@ void Interpreter::mtcrf(UGeckoInstruction inst)
|
||||||
void Interpreter::mfmsr(UGeckoInstruction inst)
|
void Interpreter::mfmsr(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
// Privileged?
|
// Privileged?
|
||||||
rGPR[inst.RD] = MSR;
|
rGPR[inst.RD] = MSR.Hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::mfsr(UGeckoInstruction inst)
|
void Interpreter::mfsr(UGeckoInstruction inst)
|
||||||
|
@ -153,7 +153,7 @@ void Interpreter::mfsrin(UGeckoInstruction inst)
|
||||||
void Interpreter::mtmsr(UGeckoInstruction inst)
|
void Interpreter::mtmsr(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
// Privileged?
|
// Privileged?
|
||||||
MSR = rGPR[inst.RS];
|
MSR.Hex = rGPR[inst.RS];
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
m_end_block = true;
|
m_end_block = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -565,8 +565,8 @@ void Jit64::Trace()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUG_LOG(DYNA_REC, "JIT64 PC: %08x SRR0: %08x SRR1: %08x FPSCR: %08x MSR: %08x LR: %08x %s %s",
|
DEBUG_LOG(DYNA_REC, "JIT64 PC: %08x SRR0: %08x SRR1: %08x FPSCR: %08x MSR: %08x LR: %08x %s %s",
|
||||||
PC, SRR0, SRR1, PowerPC::ppcState.fpscr, PowerPC::ppcState.msr,
|
PC, SRR0, SRR1, PowerPC::ppcState.fpscr, MSR.Hex, PowerPC::ppcState.spr[8],
|
||||||
PowerPC::ppcState.spr[8], regs.c_str(), fregs.c_str());
|
regs.c_str(), fregs.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::Jit(u32 em_address)
|
void Jit64::Jit(u32 em_address)
|
||||||
|
|
|
@ -342,7 +342,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
||||||
ADD(32, R(RSCRATCH), gpr.R(a));
|
ADD(32, R(RSCRATCH), gpr.R(a));
|
||||||
AND(32, R(RSCRATCH), Imm32(~31));
|
AND(32, R(RSCRATCH), Imm32(~31));
|
||||||
|
|
||||||
if (UReg_MSR(MSR).DR)
|
if (MSR.DR)
|
||||||
{
|
{
|
||||||
// Perform lookup to see if we can use fast path.
|
// Perform lookup to see if we can use fast path.
|
||||||
MOV(64, R(RSCRATCH2), ImmPtr(&PowerPC::dbat_table[0]));
|
MOV(64, R(RSCRATCH2), ImmPtr(&PowerPC::dbat_table[0]));
|
||||||
|
@ -367,7 +367,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
||||||
ABI_CallFunctionR(PowerPC::ClearCacheLine, RSCRATCH);
|
ABI_CallFunctionR(PowerPC::ClearCacheLine, RSCRATCH);
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||||
|
|
||||||
if (UReg_MSR(MSR).DR)
|
if (MSR.DR)
|
||||||
{
|
{
|
||||||
FixupBranch end = J(true);
|
FixupBranch end = J(true);
|
||||||
SwitchToNearCode();
|
SwitchToNearCode();
|
||||||
|
|
|
@ -24,7 +24,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst)
|
||||||
JITDISABLE(bJITLoadStorePairedOff);
|
JITDISABLE(bJITLoadStorePairedOff);
|
||||||
|
|
||||||
// For performance, the AsmCommon routines assume address translation is on.
|
// For performance, the AsmCommon routines assume address translation is on.
|
||||||
FALLBACK_IF(!UReg_MSR(MSR).DR);
|
FALLBACK_IF(!MSR.DR);
|
||||||
|
|
||||||
s32 offset = inst.SIMM_12;
|
s32 offset = inst.SIMM_12;
|
||||||
bool indexed = inst.OPCD == 4;
|
bool indexed = inst.OPCD == 4;
|
||||||
|
@ -114,7 +114,7 @@ void Jit64::psq_lXX(UGeckoInstruction inst)
|
||||||
JITDISABLE(bJITLoadStorePairedOff);
|
JITDISABLE(bJITLoadStorePairedOff);
|
||||||
|
|
||||||
// For performance, the AsmCommon routines assume address translation is on.
|
// For performance, the AsmCommon routines assume address translation is on.
|
||||||
FALLBACK_IF(!UReg_MSR(MSR).DR);
|
FALLBACK_IF(!MSR.DR);
|
||||||
|
|
||||||
s32 offset = inst.SIMM_12;
|
s32 offset = inst.SIMM_12;
|
||||||
bool indexed = inst.OPCD == 4;
|
bool indexed = inst.OPCD == 4;
|
||||||
|
|
|
@ -364,8 +364,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
FixupBranch exit;
|
FixupBranch exit;
|
||||||
bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || UReg_MSR(MSR).DR;
|
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || MSR.DR;
|
||||||
bool fast_check_address = !slowmem && dr_set;
|
const bool fast_check_address = !slowmem && dr_set;
|
||||||
if (fast_check_address)
|
if (fast_check_address)
|
||||||
{
|
{
|
||||||
FixupBranch slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse);
|
FixupBranch slow = CheckIfSafeAddress(R(reg_value), reg_addr, registersInUse);
|
||||||
|
@ -526,8 +526,8 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
||||||
}
|
}
|
||||||
|
|
||||||
FixupBranch exit;
|
FixupBranch exit;
|
||||||
bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || UReg_MSR(MSR).DR;
|
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || MSR.DR;
|
||||||
bool fast_check_address = !slowmem && dr_set;
|
const bool fast_check_address = !slowmem && dr_set;
|
||||||
if (fast_check_address)
|
if (fast_check_address)
|
||||||
{
|
{
|
||||||
FixupBranch slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse);
|
FixupBranch slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse);
|
||||||
|
|
|
@ -23,7 +23,7 @@ void JitArm64::psq_l(UGeckoInstruction inst)
|
||||||
FALLBACK_IF(jo.memcheck || !jo.fastmem);
|
FALLBACK_IF(jo.memcheck || !jo.fastmem);
|
||||||
|
|
||||||
// The asm routines assume address translation is on.
|
// The asm routines assume address translation is on.
|
||||||
FALLBACK_IF(!UReg_MSR(MSR).DR);
|
FALLBACK_IF(!MSR.DR);
|
||||||
|
|
||||||
// X30 is LR
|
// X30 is LR
|
||||||
// X0 contains the scale
|
// X0 contains the scale
|
||||||
|
@ -106,7 +106,7 @@ void JitArm64::psq_st(UGeckoInstruction inst)
|
||||||
FALLBACK_IF(jo.memcheck || !jo.fastmem);
|
FALLBACK_IF(jo.memcheck || !jo.fastmem);
|
||||||
|
|
||||||
// The asm routines assume address translation is on.
|
// The asm routines assume address translation is on.
|
||||||
FALLBACK_IF(!UReg_MSR(MSR).DR);
|
FALLBACK_IF(!MSR.DR);
|
||||||
|
|
||||||
// X30 is LR
|
// X30 is LR
|
||||||
// X0 contains the scale
|
// X0 contains the scale
|
||||||
|
|
|
@ -51,6 +51,6 @@ bool JitBase::CanMergeNextInstructions(int count) const
|
||||||
void JitBase::UpdateMemoryOptions()
|
void JitBase::UpdateMemoryOptions()
|
||||||
{
|
{
|
||||||
bool any_watchpoints = PowerPC::memchecks.HasAny();
|
bool any_watchpoints = PowerPC::memchecks.HasAny();
|
||||||
jo.fastmem = SConfig::GetInstance().bFastmem && (UReg_MSR(MSR).DR || !any_watchpoints);
|
jo.fastmem = SConfig::GetInstance().bFastmem && (MSR.DR || !any_watchpoints);
|
||||||
jo.memcheck = SConfig::GetInstance().bMMU || any_watchpoints;
|
jo.memcheck = SConfig::GetInstance().bMMU || any_watchpoints;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
||||||
JitBlock& b = block_map.emplace(physicalAddress, JitBlock())->second;
|
JitBlock& b = block_map.emplace(physicalAddress, JitBlock())->second;
|
||||||
b.effectiveAddress = em_address;
|
b.effectiveAddress = em_address;
|
||||||
b.physicalAddress = physicalAddress;
|
b.physicalAddress = physicalAddress;
|
||||||
b.msrBits = MSR & JIT_CACHE_MSR_MASK;
|
b.msrBits = MSR.Hex & JIT_CACHE_MSR_MASK;
|
||||||
b.linkData.clear();
|
b.linkData.clear();
|
||||||
b.fast_block_map_index = 0;
|
b.fast_block_map_index = 0;
|
||||||
return &b;
|
return &b;
|
||||||
|
@ -174,8 +174,8 @@ const u8* JitBaseBlockCache::Dispatch()
|
||||||
{
|
{
|
||||||
JitBlock* block = fast_block_map[FastLookupIndexForAddress(PC)];
|
JitBlock* block = fast_block_map[FastLookupIndexForAddress(PC)];
|
||||||
|
|
||||||
if (!block || block->effectiveAddress != PC || block->msrBits != (MSR & JIT_CACHE_MSR_MASK))
|
if (!block || block->effectiveAddress != PC || block->msrBits != (MSR.Hex & JIT_CACHE_MSR_MASK))
|
||||||
block = MoveBlockIntoFastCache(PC, MSR & JIT_CACHE_MSR_MASK);
|
block = MoveBlockIntoFastCache(PC, MSR.Hex & JIT_CACHE_MSR_MASK);
|
||||||
|
|
||||||
if (!block)
|
if (!block)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -141,12 +141,12 @@ int GetHostCode(u32* address, const u8** code, u32* code_size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
JitBlock* block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address, MSR);
|
JitBlock* block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address, MSR.Hex);
|
||||||
if (!block)
|
if (!block)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 500; i++)
|
for (int i = 0; i < 500; i++)
|
||||||
{
|
{
|
||||||
block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address - 4 * i, MSR);
|
block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address - 4 * i, MSR.Hex);
|
||||||
if (block)
|
if (block)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite);
|
||||||
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
|
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
|
||||||
static T ReadFromHardware(u32 em_address)
|
static T ReadFromHardware(u32 em_address)
|
||||||
{
|
{
|
||||||
if (!never_translate && UReg_MSR(MSR).DR)
|
if (!never_translate && MSR.DR)
|
||||||
{
|
{
|
||||||
auto translated_addr = TranslateAddress<flag>(em_address);
|
auto translated_addr = TranslateAddress<flag>(em_address);
|
||||||
if (!translated_addr.Success())
|
if (!translated_addr.Success())
|
||||||
|
@ -256,7 +256,7 @@ static T ReadFromHardware(u32 em_address)
|
||||||
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
|
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
|
||||||
static void WriteToHardware(u32 em_address, const T data)
|
static void WriteToHardware(u32 em_address, const T data)
|
||||||
{
|
{
|
||||||
if (!never_translate && UReg_MSR(MSR).DR)
|
if (!never_translate && MSR.DR)
|
||||||
{
|
{
|
||||||
auto translated_addr = TranslateAddress<flag>(em_address);
|
auto translated_addr = TranslateAddress<flag>(em_address);
|
||||||
if (!translated_addr.Success())
|
if (!translated_addr.Success())
|
||||||
|
@ -393,7 +393,7 @@ u32 Read_Opcode(u32 address)
|
||||||
TryReadInstResult TryReadInstruction(u32 address)
|
TryReadInstResult TryReadInstruction(u32 address)
|
||||||
{
|
{
|
||||||
bool from_bat = true;
|
bool from_bat = true;
|
||||||
if (UReg_MSR(MSR).IR)
|
if (MSR.IR)
|
||||||
{
|
{
|
||||||
auto tlb_addr = TranslateAddress<XCheckTLBFlag::Opcode>(address);
|
auto tlb_addr = TranslateAddress<XCheckTLBFlag::Opcode>(address);
|
||||||
if (!tlb_addr.Success())
|
if (!tlb_addr.Success())
|
||||||
|
@ -658,7 +658,7 @@ bool IsOptimizableRAMAddress(const u32 address)
|
||||||
if (PowerPC::memchecks.HasAny())
|
if (PowerPC::memchecks.HasAny())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!UReg_MSR(MSR).DR)
|
if (!MSR.DR)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TODO: This API needs to take an access size
|
// TODO: This API needs to take an access size
|
||||||
|
@ -694,14 +694,13 @@ static bool IsRAMAddress(u32 address, bool translate)
|
||||||
|
|
||||||
bool HostIsRAMAddress(u32 address)
|
bool HostIsRAMAddress(u32 address)
|
||||||
{
|
{
|
||||||
return IsRAMAddress<XCheckTLBFlag::NoException>(address, UReg_MSR(MSR).DR);
|
return IsRAMAddress<XCheckTLBFlag::NoException>(address, MSR.DR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HostIsInstructionRAMAddress(u32 address)
|
bool HostIsInstructionRAMAddress(u32 address)
|
||||||
{
|
{
|
||||||
// Instructions are always 32bit aligned.
|
// Instructions are always 32bit aligned.
|
||||||
return !(address & 3) &&
|
return !(address & 3) && IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, MSR.IR);
|
||||||
IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, UReg_MSR(MSR).IR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
|
void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
|
||||||
|
@ -779,7 +778,7 @@ void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
|
||||||
void ClearCacheLine(u32 address)
|
void ClearCacheLine(u32 address)
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT((address & 0x1F) == 0);
|
DEBUG_ASSERT((address & 0x1F) == 0);
|
||||||
if (UReg_MSR(MSR).DR)
|
if (MSR.DR)
|
||||||
{
|
{
|
||||||
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
|
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
|
||||||
if (translated_address.result == TranslateAddressResult::DIRECT_STORE_SEGMENT)
|
if (translated_address.result == TranslateAddressResult::DIRECT_STORE_SEGMENT)
|
||||||
|
@ -809,7 +808,7 @@ u32 IsOptimizableMMIOAccess(u32 address, u32 accessSize)
|
||||||
if (PowerPC::memchecks.HasAny())
|
if (PowerPC::memchecks.HasAny())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!UReg_MSR(MSR).DR)
|
if (!MSR.DR)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Translate address
|
// Translate address
|
||||||
|
@ -831,7 +830,7 @@ bool IsOptimizableGatherPipeWrite(u32 address)
|
||||||
if (PowerPC::memchecks.HasAny())
|
if (PowerPC::memchecks.HasAny())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!UReg_MSR(MSR).DR)
|
if (!MSR.DR)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Translate address, only check BAT mapping.
|
// Translate address, only check BAT mapping.
|
||||||
|
@ -846,7 +845,7 @@ bool IsOptimizableGatherPipeWrite(u32 address)
|
||||||
|
|
||||||
TranslateResult JitCache_TranslateAddress(u32 address)
|
TranslateResult JitCache_TranslateAddress(u32 address)
|
||||||
{
|
{
|
||||||
if (!UReg_MSR(MSR).IR)
|
if (!MSR.IR)
|
||||||
return TranslateResult{true, true, address};
|
return TranslateResult{true, true, address};
|
||||||
|
|
||||||
// TODO: We shouldn't use FLAG_OPCODE if the caller is the debugger.
|
// TODO: We shouldn't use FLAG_OPCODE if the caller is the debugger.
|
||||||
|
|
|
@ -394,15 +394,19 @@ void CheckExceptions()
|
||||||
u32 exceptions = ppcState.Exceptions;
|
u32 exceptions = ppcState.Exceptions;
|
||||||
|
|
||||||
// Example procedure:
|
// Example procedure:
|
||||||
// set SRR0 to either PC or NPC
|
// Set SRR0 to either PC or NPC
|
||||||
// SRR0 = NPC;
|
// SRR0 = NPC;
|
||||||
// save specified MSR bits
|
//
|
||||||
// SRR1 = MSR & 0x87C0FFFF;
|
// Save specified MSR bits
|
||||||
// copy ILE bit to LE
|
// SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
// MSR |= (MSR >> 16) & 1;
|
//
|
||||||
// clear MSR as specified
|
// Copy ILE bit to LE
|
||||||
// MSR &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
|
// MSR.LE |= MSR.ILE;
|
||||||
// set to exception type entry point
|
//
|
||||||
|
// Clear MSR as specified
|
||||||
|
// MSR.Hex &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
|
||||||
|
//
|
||||||
|
// Set to exception type entry point
|
||||||
// NPC = 0x00000x00;
|
// NPC = 0x00000x00;
|
||||||
|
|
||||||
// TODO(delroth): Exception priority is completely wrong here: depending on
|
// TODO(delroth): Exception priority is completely wrong here: depending on
|
||||||
|
@ -414,9 +418,9 @@ void CheckExceptions()
|
||||||
{
|
{
|
||||||
SRR0 = NPC;
|
SRR0 = NPC;
|
||||||
// Page fault occurred
|
// Page fault occurred
|
||||||
SRR1 = (MSR & 0x87C0FFFF) | (1 << 30);
|
SRR1 = (MSR.Hex & 0x87C0FFFF) | (1 << 30);
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000400;
|
PC = NPC = 0x00000400;
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "EXCEPTION_ISI");
|
DEBUG_LOG(POWERPC, "EXCEPTION_ISI");
|
||||||
|
@ -426,9 +430,9 @@ void CheckExceptions()
|
||||||
{
|
{
|
||||||
SRR0 = PC;
|
SRR0 = PC;
|
||||||
// say that it's a trap exception
|
// say that it's a trap exception
|
||||||
SRR1 = (MSR & 0x87C0FFFF) | 0x20000;
|
SRR1 = (MSR.Hex & 0x87C0FFFF) | 0x20000;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000700;
|
PC = NPC = 0x00000700;
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "EXCEPTION_PROGRAM");
|
DEBUG_LOG(POWERPC, "EXCEPTION_PROGRAM");
|
||||||
|
@ -437,9 +441,9 @@ void CheckExceptions()
|
||||||
else if (exceptions & EXCEPTION_SYSCALL)
|
else if (exceptions & EXCEPTION_SYSCALL)
|
||||||
{
|
{
|
||||||
SRR0 = NPC;
|
SRR0 = NPC;
|
||||||
SRR1 = MSR & 0x87C0FFFF;
|
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000C00;
|
PC = NPC = 0x00000C00;
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC);
|
DEBUG_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC);
|
||||||
|
@ -449,9 +453,9 @@ void CheckExceptions()
|
||||||
{
|
{
|
||||||
// This happens a lot - GameCube OS uses deferred FPU context switching
|
// This happens a lot - GameCube OS uses deferred FPU context switching
|
||||||
SRR0 = PC; // re-execute the instruction
|
SRR0 = PC; // re-execute the instruction
|
||||||
SRR1 = MSR & 0x87C0FFFF;
|
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000800;
|
PC = NPC = 0x00000800;
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
|
DEBUG_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
|
||||||
|
@ -464,9 +468,9 @@ void CheckExceptions()
|
||||||
else if (exceptions & EXCEPTION_DSI)
|
else if (exceptions & EXCEPTION_DSI)
|
||||||
{
|
{
|
||||||
SRR0 = PC;
|
SRR0 = PC;
|
||||||
SRR1 = MSR & 0x87C0FFFF;
|
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000300;
|
PC = NPC = 0x00000300;
|
||||||
// DSISR and DAR regs are changed in GenerateDSIException()
|
// DSISR and DAR regs are changed in GenerateDSIException()
|
||||||
|
|
||||||
|
@ -476,9 +480,9 @@ void CheckExceptions()
|
||||||
else if (exceptions & EXCEPTION_ALIGNMENT)
|
else if (exceptions & EXCEPTION_ALIGNMENT)
|
||||||
{
|
{
|
||||||
SRR0 = PC;
|
SRR0 = PC;
|
||||||
SRR1 = MSR & 0x87C0FFFF;
|
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000600;
|
PC = NPC = 0x00000600;
|
||||||
|
|
||||||
// TODO crazy amount of DSISR options to check out
|
// TODO crazy amount of DSISR options to check out
|
||||||
|
@ -499,15 +503,16 @@ void CheckExternalExceptions()
|
||||||
u32 exceptions = ppcState.Exceptions;
|
u32 exceptions = ppcState.Exceptions;
|
||||||
|
|
||||||
// EXTERNAL INTERRUPT
|
// EXTERNAL INTERRUPT
|
||||||
if (exceptions && (MSR & 0x0008000)) // Handling is delayed until MSR.EE=1.
|
// Handling is delayed until MSR.EE=1.
|
||||||
|
if (exceptions && MSR.EE)
|
||||||
{
|
{
|
||||||
if (exceptions & EXCEPTION_EXTERNAL_INT)
|
if (exceptions & EXCEPTION_EXTERNAL_INT)
|
||||||
{
|
{
|
||||||
// Pokemon gets this "too early", it hasn't a handler yet
|
// Pokemon gets this "too early", it hasn't a handler yet
|
||||||
SRR0 = NPC;
|
SRR0 = NPC;
|
||||||
SRR1 = MSR & 0x87C0FFFF;
|
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000500;
|
PC = NPC = 0x00000500;
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
DEBUG_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
||||||
|
@ -518,9 +523,9 @@ void CheckExternalExceptions()
|
||||||
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
|
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
|
||||||
{
|
{
|
||||||
SRR0 = NPC;
|
SRR0 = NPC;
|
||||||
SRR1 = MSR & 0x87C0FFFF;
|
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000F00;
|
PC = NPC = 0x00000F00;
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
DEBUG_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
||||||
|
@ -529,9 +534,9 @@ void CheckExternalExceptions()
|
||||||
else if (exceptions & EXCEPTION_DECREMENTER)
|
else if (exceptions & EXCEPTION_DECREMENTER)
|
||||||
{
|
{
|
||||||
SRR0 = NPC;
|
SRR0 = NPC;
|
||||||
SRR1 = MSR & 0x87C0FFFF;
|
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||||
MSR |= (MSR >> 16) & 1;
|
MSR.LE |= MSR.ILE;
|
||||||
MSR &= ~0x04EF36;
|
MSR.Hex &= ~0x04EF36;
|
||||||
PC = NPC = 0x00000900;
|
PC = NPC = 0x00000900;
|
||||||
|
|
||||||
DEBUG_LOG(POWERPC, "EXCEPTION_DECREMENTER");
|
DEBUG_LOG(POWERPC, "EXCEPTION_DECREMENTER");
|
||||||
|
|
|
@ -75,7 +75,7 @@ struct PowerPCState
|
||||||
// be manipulated bit by bit fairly easily.
|
// be manipulated bit by bit fairly easily.
|
||||||
u64 cr_val[8];
|
u64 cr_val[8];
|
||||||
|
|
||||||
u32 msr; // machine specific register
|
UReg_MSR msr; // machine state register
|
||||||
u32 fpscr; // floating point flags/status bits
|
u32 fpscr; // floating point flags/status bits
|
||||||
|
|
||||||
// Exception management.
|
// Exception management.
|
||||||
|
|
|
@ -296,8 +296,8 @@ void RegisterWidget::PopulateTable()
|
||||||
[](u64 value) { PowerPC::ppcState.fpscr = value; });
|
[](u64 value) { PowerPC::ppcState.fpscr = value; });
|
||||||
|
|
||||||
// MSR
|
// MSR
|
||||||
AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr; },
|
AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr.Hex; },
|
||||||
[](u64 value) { PowerPC::ppcState.msr = value; });
|
[](u64 value) { PowerPC::ppcState.msr.Hex = value; });
|
||||||
|
|
||||||
// SRR 0-1
|
// SRR 0-1
|
||||||
AddRegister(24, 5, RegisterType::srr, "SRR0", [] { return PowerPC::ppcState.spr[SPR_SRR0]; },
|
AddRegister(24, 5, RegisterType::srr, "SRR0", [] { return PowerPC::ppcState.spr[SPR_SRR0]; },
|
||||||
|
|
|
@ -82,7 +82,7 @@ u32 GetSpecialRegValue(int reg)
|
||||||
case 5:
|
case 5:
|
||||||
return PowerPC::ppcState.fpscr;
|
return PowerPC::ppcState.fpscr;
|
||||||
case 6:
|
case 6:
|
||||||
return PowerPC::ppcState.msr;
|
return PowerPC::ppcState.msr.Hex;
|
||||||
case 7:
|
case 7:
|
||||||
return PowerPC::ppcState.spr[SPR_SRR0];
|
return PowerPC::ppcState.spr[SPR_SRR0];
|
||||||
case 8:
|
case 8:
|
||||||
|
@ -127,7 +127,7 @@ void SetSpecialRegValue(int reg, u32 value)
|
||||||
PowerPC::ppcState.fpscr = value;
|
PowerPC::ppcState.fpscr = value;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
PowerPC::ppcState.msr = value;
|
PowerPC::ppcState.msr.Hex = value;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
PowerPC::ppcState.spr[SPR_SRR0] = value;
|
PowerPC::ppcState.spr[SPR_SRR0] = value;
|
||||||
|
|
Loading…
Reference in New Issue