Skip to content

Commit

Permalink
Interpreter_SystemRegisters: Ensure FPSCR modifying instructions don'…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
lioncash committed Jun 5, 2018
1 parent 36ff2a2 commit 11a35d4
Showing 1 changed file with 29 additions and 10 deletions.
Expand Up @@ -58,26 +58,39 @@ void Interpreter::mtfsb0x(UGeckoInstruction inst)
Helper_UpdateCR1(); Helper_UpdateCR1();
} }


// This instruction can affect FX
void Interpreter::mtfsb1x(UGeckoInstruction inst) void Interpreter::mtfsb1x(UGeckoInstruction inst)
{ {
// this instruction can affect FX const u32 bit = inst.CRBD;
u32 b = 0x80000000 >> inst.CRBD;
if (b & FPSCR_ANY_X) // Bit 20 in the FPSCR is reserved and defined as zero,
SetFPException(b); // so we ensure that we don't set it.
else if (bit != 20)
FPSCR.Hex |= b; {
FPSCRtoFPUSettings(FPSCR); const u32 b = 0x80000000 >> bit;

if (b & FPSCR_ANY_X)
SetFPException(b);
else
FPSCR.Hex |= b;

FPSCRtoFPUSettings(FPSCR);
}


if (inst.Rc) if (inst.Rc)
Helper_UpdateCR1(); Helper_UpdateCR1();
} }


void Interpreter::mtfsfix(UGeckoInstruction inst) void Interpreter::mtfsfix(UGeckoInstruction inst)
{ {
u32 mask = (0xF0000000 >> (4 * inst.CRFD)); // Bit 20 of the FPSCR is reserved and defined as zero on hardware,
u32 imm = (inst.hex << 16) & 0xF0000000; // 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); FPSCRtoFPUSettings(FPSCR);


Expand All @@ -95,6 +108,12 @@ void Interpreter::mtfsfx(UGeckoInstruction inst)
m |= (0xFU << (i * 4)); 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.Hex = (FPSCR.Hex & ~m) | (static_cast<u32>(riPS0(inst.FB)) & m);
FPSCRtoFPUSettings(FPSCR); FPSCRtoFPUSettings(FPSCR);


Expand Down

0 comments on commit 11a35d4

Please sign in to comment.