Interpreter_SystemRegisters: Ensure FPSCR modifying instructions don't set bit 20
Bit 20 is defined as being reserved and attempts to set it are ignored by hardware, so we should be doing the same thing.
This commit is contained in:
parent
36ff2a20d5
commit
11a35d47ef
|
@ -58,15 +58,24 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst)
|
|||
Helper_UpdateCR1();
|
||||
}
|
||||
|
||||
// This instruction can affect FX
|
||||
void Interpreter::mtfsb1x(UGeckoInstruction inst)
|
||||
{
|
||||
// this instruction can affect FX
|
||||
u32 b = 0x80000000 >> inst.CRBD;
|
||||
if (b & FPSCR_ANY_X)
|
||||
SetFPException(b);
|
||||
else
|
||||
FPSCR.Hex |= b;
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
const u32 bit = inst.CRBD;
|
||||
|
||||
// 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;
|
||||
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
}
|
||||
|
||||
if (inst.Rc)
|
||||
Helper_UpdateCR1();
|
||||
|
@ -74,10 +83,14 @@ void Interpreter::mtfsb1x(UGeckoInstruction inst)
|
|||
|
||||
void Interpreter::mtfsfix(UGeckoInstruction inst)
|
||||
{
|
||||
u32 mask = (0xF0000000 >> (4 * inst.CRFD));
|
||||
u32 imm = (inst.hex << 16) & 0xF0000000;
|
||||
// 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 mask = (pre_shifted_mask >> (4 * field));
|
||||
const u32 imm = (inst.hex << 16) & pre_shifted_mask;
|
||||
|
||||
FPSCR.Hex = (FPSCR.Hex & ~mask) | (imm >> (4 * inst.CRFD));
|
||||
FPSCR.Hex = (FPSCR.Hex & ~mask) | (imm >> (4 * field));
|
||||
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
|
||||
|
@ -95,6 +108,12 @@ 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);
|
||||
FPSCRtoFPUSettings(FPSCR);
|
||||
|
||||
|
|
Loading…
Reference in New Issue