Merge pull request #6760 from lioncash/msr
PowerPC: Make the PowerPCState's msr member variable a UReg_MSR instance
This commit is contained in:
commit
3f087e2ed5
|
@ -269,10 +269,9 @@ bool CBoot::Load_BS2(const std::string& boot_rom_filename)
|
|||
PowerPC::ppcState.gpr[4] = 0x00002030;
|
||||
PowerPC::ppcState.gpr[5] = 0x0000009c;
|
||||
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
MSR.FP = 1;
|
||||
MSR.DR = 1;
|
||||
MSR.IR = 1;
|
||||
|
||||
PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464;
|
||||
PowerPC::ppcState.spr[SPR_IBAT3U] = 0xfff0001f;
|
||||
|
|
|
@ -55,11 +55,10 @@ void CBoot::RunFunction(u32 address)
|
|||
|
||||
void CBoot::SetupMSR()
|
||||
{
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
MSR.FP = 1;
|
||||
MSR.DR = 1;
|
||||
MSR.IR = 1;
|
||||
MSR.EE = 1;
|
||||
}
|
||||
|
||||
void CBoot::SetupBAT(bool is_wii)
|
||||
|
|
|
@ -428,7 +428,7 @@ void FifoPlayer::LoadMemory()
|
|||
UReg_MSR newMSR;
|
||||
newMSR.DR = 1;
|
||||
newMSR.IR = 1;
|
||||
MSR = newMSR.Hex;
|
||||
MSR.Hex = newMSR.Hex;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
|
|
|
@ -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)
|
||||
// The state of other CPU registers (like the BAT registers) doesn't matter much
|
||||
// because the realmode code at 0x3400 initializes everything itself anyway.
|
||||
MSR = 0;
|
||||
MSR.Hex = 0;
|
||||
PC = 0x3400;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -65,7 +65,7 @@ bool Load()
|
|||
|
||||
const PowerPC::CoreMode core_mode = PowerPC::GetMode();
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
MSR = 0;
|
||||
MSR.Hex = 0;
|
||||
PC = 0x3400;
|
||||
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.
|
||||
static bool IsStackSane()
|
||||
{
|
||||
DEBUG_ASSERT(UReg_MSR(MSR).DR && UReg_MSR(MSR).IR);
|
||||
DEBUG_ASSERT(MSR.DR && MSR.IR);
|
||||
|
||||
// Check the stack pointer
|
||||
u32 SP = GPR(1);
|
||||
|
@ -220,13 +220,12 @@ bool ApplyFramePatches()
|
|||
// 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
|
||||
// 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(
|
||||
ACTIONREPLAY,
|
||||
"Need to retry later. CPU configuration is currently incorrect. PC = 0x%08X, MSR = 0x%08X",
|
||||
PC, MSR);
|
||||
PC, MSR.Hex);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,8 +150,7 @@ static void WriteBrokenBlockNPC(UGeckoInstruction data)
|
|||
|
||||
static bool CheckFPU(u32 data)
|
||||
{
|
||||
UReg_MSR msr{MSR};
|
||||
if (!msr.FP)
|
||||
if (!MSR.FP)
|
||||
{
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
||||
PowerPC::CheckExceptions();
|
||||
|
|
|
@ -446,7 +446,7 @@ static void gdb_read_register()
|
|||
wbe32hex(reply, PC);
|
||||
break;
|
||||
case 65:
|
||||
wbe32hex(reply, MSR);
|
||||
wbe32hex(reply, MSR.Hex);
|
||||
break;
|
||||
case 66:
|
||||
wbe32hex(reply, PowerPC::GetCR());
|
||||
|
@ -531,7 +531,7 @@ static void gdb_write_register()
|
|||
PC = re32hex(bufptr);
|
||||
break;
|
||||
case 65:
|
||||
MSR = re32hex(bufptr);
|
||||
MSR.Hex = re32hex(bufptr);
|
||||
break;
|
||||
case 66:
|
||||
PowerPC::SetCR(re32hex(bufptr));
|
||||
|
|
|
@ -378,7 +378,7 @@ union UReg_MSR
|
|||
u32 Hex = 0;
|
||||
|
||||
UReg_MSR() = default;
|
||||
UReg_MSR(u32 hex_) : Hex{hex_} {}
|
||||
explicit UReg_MSR(u32 hex_) : Hex{hex_} {}
|
||||
};
|
||||
|
||||
#define FPRF_SHIFT 12
|
||||
|
|
|
@ -96,8 +96,7 @@ static void Trace(UGeckoInstruction& inst)
|
|||
"INTER PC: %08x SRR0: %08x SRR1: %08x CRval: %016lx FPSCR: %08x MSR: %08x LR: "
|
||||
"%08x %s %08x %s",
|
||||
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,
|
||||
ppc_inst.c_str());
|
||||
MSR.Hex, PowerPC::ppcState.spr[8], regs.c_str(), inst.hex, ppc_inst.c_str());
|
||||
}
|
||||
|
||||
int Interpreter::SingleStepInner()
|
||||
|
@ -153,8 +152,7 @@ int Interpreter::SingleStepInner()
|
|||
|
||||
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);
|
||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||
|
|
|
@ -119,9 +119,9 @@ void Interpreter::rfi(UGeckoInstruction inst)
|
|||
// Restore saved bits from SRR1 to MSR.
|
||||
// Gecko/Broadway can save more bits than explicitly defined in ppc spec
|
||||
const int mask = 0x87C0FFFF;
|
||||
MSR = (MSR & ~mask) | (SRR1 & mask);
|
||||
MSR.Hex = (MSR.Hex & ~mask) | (SRR1 & mask);
|
||||
// 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
|
||||
// are set
|
||||
// if above is true, we'd do:
|
||||
|
|
|
@ -278,7 +278,7 @@ void Interpreter::lmw(UGeckoInstruction inst)
|
|||
{
|
||||
u32 address = Helper_Get_EA(inst);
|
||||
|
||||
if ((address & 0b11) != 0 || UReg_MSR{MSR}.LE)
|
||||
if ((address & 0b11) != 0 || MSR.LE)
|
||||
{
|
||||
GenerateAlignmentException(address);
|
||||
return;
|
||||
|
@ -306,7 +306,7 @@ void Interpreter::stmw(UGeckoInstruction inst)
|
|||
{
|
||||
u32 address = Helper_Get_EA(inst);
|
||||
|
||||
if ((address & 0b11) != 0 || UReg_MSR{MSR}.LE)
|
||||
if ((address & 0b11) != 0 || MSR.LE)
|
||||
{
|
||||
GenerateAlignmentException(address);
|
||||
return;
|
||||
|
@ -685,7 +685,7 @@ void Interpreter::lswx(UGeckoInstruction inst)
|
|||
{
|
||||
u32 EA = Helper_Get_EA_X(inst);
|
||||
|
||||
if (UReg_MSR{MSR}.LE)
|
||||
if (MSR.LE)
|
||||
{
|
||||
GenerateAlignmentException(EA);
|
||||
return;
|
||||
|
@ -867,7 +867,7 @@ void Interpreter::lswi(UGeckoInstruction inst)
|
|||
else
|
||||
EA = rGPR[inst.RA];
|
||||
|
||||
if (UReg_MSR{MSR}.LE)
|
||||
if (MSR.LE)
|
||||
{
|
||||
GenerateAlignmentException(EA);
|
||||
return;
|
||||
|
@ -918,7 +918,7 @@ void Interpreter::stswi(UGeckoInstruction inst)
|
|||
else
|
||||
EA = rGPR[inst.RA];
|
||||
|
||||
if (UReg_MSR{MSR}.LE)
|
||||
if (MSR.LE)
|
||||
{
|
||||
GenerateAlignmentException(EA);
|
||||
return;
|
||||
|
@ -958,7 +958,7 @@ void Interpreter::stswx(UGeckoInstruction inst)
|
|||
{
|
||||
u32 EA = Helper_Get_EA_X(inst);
|
||||
|
||||
if (UReg_MSR{MSR}.LE)
|
||||
if (MSR.LE)
|
||||
{
|
||||
GenerateAlignmentException(EA);
|
||||
return;
|
||||
|
|
|
@ -136,7 +136,7 @@ void Interpreter::mtcrf(UGeckoInstruction inst)
|
|||
void Interpreter::mfmsr(UGeckoInstruction inst)
|
||||
{
|
||||
// Privileged?
|
||||
rGPR[inst.RD] = MSR;
|
||||
rGPR[inst.RD] = MSR.Hex;
|
||||
}
|
||||
|
||||
void Interpreter::mfsr(UGeckoInstruction inst)
|
||||
|
@ -153,7 +153,7 @@ void Interpreter::mfsrin(UGeckoInstruction inst)
|
|||
void Interpreter::mtmsr(UGeckoInstruction inst)
|
||||
{
|
||||
// Privileged?
|
||||
MSR = rGPR[inst.RS];
|
||||
MSR.Hex = rGPR[inst.RS];
|
||||
PowerPC::CheckExceptions();
|
||||
m_end_block = true;
|
||||
}
|
||||
|
|
|
@ -565,8 +565,8 @@ void Jit64::Trace()
|
|||
#endif
|
||||
|
||||
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,
|
||||
PowerPC::ppcState.spr[8], regs.c_str(), fregs.c_str());
|
||||
PC, SRR0, SRR1, PowerPC::ppcState.fpscr, MSR.Hex, PowerPC::ppcState.spr[8],
|
||||
regs.c_str(), fregs.c_str());
|
||||
}
|
||||
|
||||
void Jit64::Jit(u32 em_address)
|
||||
|
|
|
@ -342,7 +342,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
|||
ADD(32, R(RSCRATCH), gpr.R(a));
|
||||
AND(32, R(RSCRATCH), Imm32(~31));
|
||||
|
||||
if (UReg_MSR(MSR).DR)
|
||||
if (MSR.DR)
|
||||
{
|
||||
// Perform lookup to see if we can use fast path.
|
||||
MOV(64, R(RSCRATCH2), ImmPtr(&PowerPC::dbat_table[0]));
|
||||
|
@ -367,7 +367,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
|||
ABI_CallFunctionR(PowerPC::ClearCacheLine, RSCRATCH);
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||
|
||||
if (UReg_MSR(MSR).DR)
|
||||
if (MSR.DR)
|
||||
{
|
||||
FixupBranch end = J(true);
|
||||
SwitchToNearCode();
|
||||
|
|
|
@ -24,7 +24,7 @@ void Jit64::psq_stXX(UGeckoInstruction inst)
|
|||
JITDISABLE(bJITLoadStorePairedOff);
|
||||
|
||||
// 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;
|
||||
bool indexed = inst.OPCD == 4;
|
||||
|
@ -114,7 +114,7 @@ void Jit64::psq_lXX(UGeckoInstruction inst)
|
|||
JITDISABLE(bJITLoadStorePairedOff);
|
||||
|
||||
// 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;
|
||||
bool indexed = inst.OPCD == 4;
|
||||
|
|
|
@ -364,8 +364,8 @@ void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress,
|
|||
}
|
||||
|
||||
FixupBranch exit;
|
||||
bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || UReg_MSR(MSR).DR;
|
||||
bool fast_check_address = !slowmem && dr_set;
|
||||
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || MSR.DR;
|
||||
const bool fast_check_address = !slowmem && dr_set;
|
||||
if (fast_check_address)
|
||||
{
|
||||
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;
|
||||
bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || UReg_MSR(MSR).DR;
|
||||
bool fast_check_address = !slowmem && dr_set;
|
||||
const bool dr_set = (flags & SAFE_LOADSTORE_DR_ON) || MSR.DR;
|
||||
const bool fast_check_address = !slowmem && dr_set;
|
||||
if (fast_check_address)
|
||||
{
|
||||
FixupBranch slow = CheckIfSafeAddress(reg_value, reg_addr, registersInUse);
|
||||
|
|
|
@ -23,7 +23,7 @@ void JitArm64::psq_l(UGeckoInstruction inst)
|
|||
FALLBACK_IF(jo.memcheck || !jo.fastmem);
|
||||
|
||||
// The asm routines assume address translation is on.
|
||||
FALLBACK_IF(!UReg_MSR(MSR).DR);
|
||||
FALLBACK_IF(!MSR.DR);
|
||||
|
||||
// X30 is LR
|
||||
// X0 contains the scale
|
||||
|
@ -106,7 +106,7 @@ void JitArm64::psq_st(UGeckoInstruction inst)
|
|||
FALLBACK_IF(jo.memcheck || !jo.fastmem);
|
||||
|
||||
// The asm routines assume address translation is on.
|
||||
FALLBACK_IF(!UReg_MSR(MSR).DR);
|
||||
FALLBACK_IF(!MSR.DR);
|
||||
|
||||
// X30 is LR
|
||||
// X0 contains the scale
|
||||
|
|
|
@ -51,6 +51,6 @@ bool JitBase::CanMergeNextInstructions(int count) const
|
|||
void JitBase::UpdateMemoryOptions()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
|||
JitBlock& b = block_map.emplace(physicalAddress, JitBlock())->second;
|
||||
b.effectiveAddress = em_address;
|
||||
b.physicalAddress = physicalAddress;
|
||||
b.msrBits = MSR & JIT_CACHE_MSR_MASK;
|
||||
b.msrBits = MSR.Hex & JIT_CACHE_MSR_MASK;
|
||||
b.linkData.clear();
|
||||
b.fast_block_map_index = 0;
|
||||
return &b;
|
||||
|
@ -174,8 +174,8 @@ const u8* JitBaseBlockCache::Dispatch()
|
|||
{
|
||||
JitBlock* block = fast_block_map[FastLookupIndexForAddress(PC)];
|
||||
|
||||
if (!block || block->effectiveAddress != PC || block->msrBits != (MSR & JIT_CACHE_MSR_MASK))
|
||||
block = MoveBlockIntoFastCache(PC, MSR & JIT_CACHE_MSR_MASK);
|
||||
if (!block || block->effectiveAddress != PC || block->msrBits != (MSR.Hex & JIT_CACHE_MSR_MASK))
|
||||
block = MoveBlockIntoFastCache(PC, MSR.Hex & JIT_CACHE_MSR_MASK);
|
||||
|
||||
if (!block)
|
||||
return nullptr;
|
||||
|
|
|
@ -141,12 +141,12 @@ int GetHostCode(u32* address, const u8** code, u32* code_size)
|
|||
return 1;
|
||||
}
|
||||
|
||||
JitBlock* block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address, MSR);
|
||||
JitBlock* block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address, MSR.Hex);
|
||||
if (!block)
|
||||
{
|
||||
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)
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ static void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite);
|
|||
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
|
||||
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);
|
||||
if (!translated_addr.Success())
|
||||
|
@ -256,7 +256,7 @@ static T ReadFromHardware(u32 em_address)
|
|||
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
|
||||
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);
|
||||
if (!translated_addr.Success())
|
||||
|
@ -393,7 +393,7 @@ u32 Read_Opcode(u32 address)
|
|||
TryReadInstResult TryReadInstruction(u32 address)
|
||||
{
|
||||
bool from_bat = true;
|
||||
if (UReg_MSR(MSR).IR)
|
||||
if (MSR.IR)
|
||||
{
|
||||
auto tlb_addr = TranslateAddress<XCheckTLBFlag::Opcode>(address);
|
||||
if (!tlb_addr.Success())
|
||||
|
@ -658,7 +658,7 @@ bool IsOptimizableRAMAddress(const u32 address)
|
|||
if (PowerPC::memchecks.HasAny())
|
||||
return false;
|
||||
|
||||
if (!UReg_MSR(MSR).DR)
|
||||
if (!MSR.DR)
|
||||
return false;
|
||||
|
||||
// TODO: This API needs to take an access size
|
||||
|
@ -694,14 +694,13 @@ static bool IsRAMAddress(u32 address, bool translate)
|
|||
|
||||
bool HostIsRAMAddress(u32 address)
|
||||
{
|
||||
return IsRAMAddress<XCheckTLBFlag::NoException>(address, UReg_MSR(MSR).DR);
|
||||
return IsRAMAddress<XCheckTLBFlag::NoException>(address, MSR.DR);
|
||||
}
|
||||
|
||||
bool HostIsInstructionRAMAddress(u32 address)
|
||||
{
|
||||
// Instructions are always 32bit aligned.
|
||||
return !(address & 3) &&
|
||||
IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, UReg_MSR(MSR).IR);
|
||||
return !(address & 3) && IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, MSR.IR);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
DEBUG_ASSERT((address & 0x1F) == 0);
|
||||
if (UReg_MSR(MSR).DR)
|
||||
if (MSR.DR)
|
||||
{
|
||||
auto translated_address = TranslateAddress<XCheckTLBFlag::Write>(address);
|
||||
if (translated_address.result == TranslateAddressResult::DIRECT_STORE_SEGMENT)
|
||||
|
@ -809,7 +808,7 @@ u32 IsOptimizableMMIOAccess(u32 address, u32 accessSize)
|
|||
if (PowerPC::memchecks.HasAny())
|
||||
return 0;
|
||||
|
||||
if (!UReg_MSR(MSR).DR)
|
||||
if (!MSR.DR)
|
||||
return 0;
|
||||
|
||||
// Translate address
|
||||
|
@ -831,7 +830,7 @@ bool IsOptimizableGatherPipeWrite(u32 address)
|
|||
if (PowerPC::memchecks.HasAny())
|
||||
return false;
|
||||
|
||||
if (!UReg_MSR(MSR).DR)
|
||||
if (!MSR.DR)
|
||||
return false;
|
||||
|
||||
// Translate address, only check BAT mapping.
|
||||
|
@ -846,7 +845,7 @@ bool IsOptimizableGatherPipeWrite(u32 address)
|
|||
|
||||
TranslateResult JitCache_TranslateAddress(u32 address)
|
||||
{
|
||||
if (!UReg_MSR(MSR).IR)
|
||||
if (!MSR.IR)
|
||||
return TranslateResult{true, true, address};
|
||||
|
||||
// TODO: We shouldn't use FLAG_OPCODE if the caller is the debugger.
|
||||
|
|
|
@ -144,7 +144,7 @@ static void ResetRegisters()
|
|||
SystemTimers::TimeBaseSet();
|
||||
|
||||
// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
|
||||
ppcState.msr = 0;
|
||||
ppcState.msr.Hex = 0;
|
||||
rDEC = 0xFFFFFFFF;
|
||||
SystemTimers::DecrementerSet();
|
||||
}
|
||||
|
@ -394,15 +394,19 @@ void CheckExceptions()
|
|||
u32 exceptions = ppcState.Exceptions;
|
||||
|
||||
// Example procedure:
|
||||
// set SRR0 to either PC or NPC
|
||||
// Set SRR0 to either PC or NPC
|
||||
// SRR0 = NPC;
|
||||
// save specified MSR bits
|
||||
// SRR1 = MSR & 0x87C0FFFF;
|
||||
// copy ILE bit to LE
|
||||
// MSR |= (MSR >> 16) & 1;
|
||||
// clear MSR as specified
|
||||
// MSR &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
|
||||
// set to exception type entry point
|
||||
//
|
||||
// Save specified MSR bits
|
||||
// SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
//
|
||||
// Copy ILE bit to LE
|
||||
// MSR.LE |= MSR.ILE;
|
||||
//
|
||||
// Clear MSR as specified
|
||||
// MSR.Hex &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
|
||||
//
|
||||
// Set to exception type entry point
|
||||
// NPC = 0x00000x00;
|
||||
|
||||
// TODO(delroth): Exception priority is completely wrong here: depending on
|
||||
|
@ -414,9 +418,9 @@ void CheckExceptions()
|
|||
{
|
||||
SRR0 = NPC;
|
||||
// Page fault occurred
|
||||
SRR1 = (MSR & 0x87C0FFFF) | (1 << 30);
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = (MSR.Hex & 0x87C0FFFF) | (1 << 30);
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000400;
|
||||
|
||||
DEBUG_LOG(POWERPC, "EXCEPTION_ISI");
|
||||
|
@ -426,9 +430,9 @@ void CheckExceptions()
|
|||
{
|
||||
SRR0 = PC;
|
||||
// say that it's a trap exception
|
||||
SRR1 = (MSR & 0x87C0FFFF) | 0x20000;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = (MSR.Hex & 0x87C0FFFF) | 0x20000;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000700;
|
||||
|
||||
DEBUG_LOG(POWERPC, "EXCEPTION_PROGRAM");
|
||||
|
@ -437,9 +441,9 @@ void CheckExceptions()
|
|||
else if (exceptions & EXCEPTION_SYSCALL)
|
||||
{
|
||||
SRR0 = NPC;
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000C00;
|
||||
|
||||
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
|
||||
SRR0 = PC; // re-execute the instruction
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000800;
|
||||
|
||||
DEBUG_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
|
||||
|
@ -464,9 +468,9 @@ void CheckExceptions()
|
|||
else if (exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
SRR0 = PC;
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000300;
|
||||
// DSISR and DAR regs are changed in GenerateDSIException()
|
||||
|
||||
|
@ -476,9 +480,9 @@ void CheckExceptions()
|
|||
else if (exceptions & EXCEPTION_ALIGNMENT)
|
||||
{
|
||||
SRR0 = PC;
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000600;
|
||||
|
||||
// TODO crazy amount of DSISR options to check out
|
||||
|
@ -499,15 +503,16 @@ void CheckExternalExceptions()
|
|||
u32 exceptions = ppcState.Exceptions;
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Pokemon gets this "too early", it hasn't a handler yet
|
||||
SRR0 = NPC;
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000500;
|
||||
|
||||
DEBUG_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
||||
|
@ -518,9 +523,9 @@ void CheckExternalExceptions()
|
|||
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
|
||||
{
|
||||
SRR0 = NPC;
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000F00;
|
||||
|
||||
DEBUG_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
||||
|
@ -529,9 +534,9 @@ void CheckExternalExceptions()
|
|||
else if (exceptions & EXCEPTION_DECREMENTER)
|
||||
{
|
||||
SRR0 = NPC;
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
MSR &= ~0x04EF36;
|
||||
SRR1 = MSR.Hex & 0x87C0FFFF;
|
||||
MSR.LE |= MSR.ILE;
|
||||
MSR.Hex &= ~0x04EF36;
|
||||
PC = NPC = 0x00000900;
|
||||
|
||||
DEBUG_LOG(POWERPC, "EXCEPTION_DECREMENTER");
|
||||
|
|
|
@ -75,8 +75,8 @@ struct PowerPCState
|
|||
// be manipulated bit by bit fairly easily.
|
||||
u64 cr_val[8];
|
||||
|
||||
u32 msr; // machine specific register
|
||||
u32 fpscr; // floating point flags/status bits
|
||||
UReg_MSR msr; // machine state register
|
||||
u32 fpscr; // floating point flags/status bits
|
||||
|
||||
// Exception management.
|
||||
u32 Exceptions;
|
||||
|
|
|
@ -296,8 +296,8 @@ void RegisterWidget::PopulateTable()
|
|||
[](u64 value) { PowerPC::ppcState.fpscr = value; });
|
||||
|
||||
// MSR
|
||||
AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr; },
|
||||
[](u64 value) { PowerPC::ppcState.msr = value; });
|
||||
AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr.Hex; },
|
||||
[](u64 value) { PowerPC::ppcState.msr.Hex = value; });
|
||||
|
||||
// SRR 0-1
|
||||
AddRegister(24, 5, RegisterType::srr, "SRR0", [] { return PowerPC::ppcState.spr[SPR_SRR0]; },
|
||||
|
|
|
@ -82,7 +82,7 @@ u32 GetSpecialRegValue(int reg)
|
|||
case 5:
|
||||
return PowerPC::ppcState.fpscr;
|
||||
case 6:
|
||||
return PowerPC::ppcState.msr;
|
||||
return PowerPC::ppcState.msr.Hex;
|
||||
case 7:
|
||||
return PowerPC::ppcState.spr[SPR_SRR0];
|
||||
case 8:
|
||||
|
@ -127,7 +127,7 @@ void SetSpecialRegValue(int reg, u32 value)
|
|||
PowerPC::ppcState.fpscr = value;
|
||||
break;
|
||||
case 6:
|
||||
PowerPC::ppcState.msr = value;
|
||||
PowerPC::ppcState.msr.Hex = value;
|
||||
break;
|
||||
case 7:
|
||||
PowerPC::ppcState.spr[SPR_SRR0] = value;
|
||||
|
|
Loading…
Reference in New Issue