Permalink
Browse files

Gekko: Centralize bitmasking of the FPSCR within UReg_FPSCR

Rather than introduce this handling in every system instruction that modifies
the FPSCR directly, we can instead just handle it within the data structure
instead, which avoids duplicating mask handling across instructions.

This also allows handling proper masking from the debugger register
windows themselves without duplicating masking behavior there either.
  • Loading branch information...
lioncash committed Jun 12, 2018
1 parent 8a3679b commit 0049ef3a2a879d785872b02c87ef8fc740974a63
@@ -474,8 +474,37 @@ union UReg_FPSCR
};
u32 Hex = 0;
// The FPSCR's 20th bit (11th from a little endian perspective)
// is defined as reserved and set to zero. Attempts to modify it
// are ignored by hardware, so we do the same.
static constexpr u32 mask = 0xFFFFF7FF;
UReg_FPSCR() = default;
explicit UReg_FPSCR(u32 hex_) : Hex{hex_} {}
explicit UReg_FPSCR(u32 hex_) : Hex{hex_ & mask} {}
UReg_FPSCR& operator=(u32 value)
{
Hex = value & mask;
return *this;
}
UReg_FPSCR& operator|=(u32 value)
{
Hex |= value & mask;
return *this;
}
UReg_FPSCR& operator&=(u32 value)
{
Hex &= value;
return *this;
}
UReg_FPSCR& operator^=(u32 value)
{
Hex ^= value & mask;
return *this;
}
void ClearFIFR()
{
@@ -62,35 +62,27 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst)
void Interpreter::mtfsb1x(UGeckoInstruction inst)
{
const u32 bit = inst.CRBD;
const u32 b = 0x80000000 >> bit;
// Bit 20 in the FPSCR is reserved and defined as zero,
// so we ensure that we don't set it.
if (bit != 20)
{
const u32 b = 0x80000000 >> bit;
if (b & FPSCR_ANY_X)
SetFPException(b);
else
FPSCR.Hex |= b;
if (b & FPSCR_ANY_X)
SetFPException(b);
else
FPSCR |= b;
FPSCRtoFPUSettings(FPSCR);
}
FPSCRtoFPUSettings(FPSCR);
if (inst.Rc)
Helper_UpdateCR1();
}
void Interpreter::mtfsfix(UGeckoInstruction inst)
{
// Bit 20 of the FPSCR is reserved and defined as zero on hardware,
// so ensure that we don't set it.
const u32 field = inst.CRFD;
const u32 pre_shifted_mask = field == 4 ? 0x70000000 : 0xF0000000;
const u32 pre_shifted_mask = 0xF0000000;
const u32 mask = (pre_shifted_mask >> (4 * field));
const u32 imm = (inst.hex << 16) & pre_shifted_mask;
FPSCR.Hex = (FPSCR.Hex & ~mask) | (imm >> (4 * field));
FPSCR = (FPSCR.Hex & ~mask) | (imm >> (4 * field));
FPSCRtoFPUSettings(FPSCR);
@@ -108,13 +100,7 @@ void Interpreter::mtfsfx(UGeckoInstruction inst)
m |= (0xFU << (i * 4));
}
// Bit 20 of the FPSCR is defined as always being zero
// (bit 11 in a little endian context), so ensure that
// we don't actually set that bit.
if ((fm & 0b100) != 0)
m &= 0xFFFFF7FF;
FPSCR.Hex = (FPSCR.Hex & ~m) | (static_cast<u32>(riPS0(inst.FB)) & m);
FPSCR = (FPSCR.Hex & ~m) | (static_cast<u32>(riPS0(inst.FB)) & m);
FPSCRtoFPUSettings(FPSCR);
if (inst.Rc)
@@ -290,7 +290,7 @@ void RegisterWidget::PopulateTable()
// FPSCR
AddRegister(22, 5, RegisterType::fpscr, "FPSCR", [] { return PowerPC::ppcState.fpscr.Hex; },
[](u64 value) { PowerPC::ppcState.fpscr.Hex = value; });
[](u64 value) { PowerPC::ppcState.fpscr = static_cast<u32>(value); });
// MSR
AddRegister(23, 5, RegisterType::msr, "MSR", [] { return PowerPC::ppcState.msr.Hex; },
@@ -124,7 +124,7 @@ void SetSpecialRegValue(int reg, u32 value)
PowerPC::SetXER(UReg_XER(value));
break;
case 5:
PowerPC::ppcState.fpscr.Hex = value;
PowerPC::ppcState.fpscr = value;
break;
case 6:
PowerPC::ppcState.msr.Hex = value;

0 comments on commit 0049ef3

Please sign in to comment.