Skip to content

Commit

Permalink
Jit64: implement FPSCR related instructions
Browse files Browse the repository at this point in the history
  • Loading branch information
Tilka committed Aug 17, 2015
1 parent 1b2074e commit 818142f
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 6 deletions.
7 changes: 7 additions & 0 deletions Source/Core/Core/PowerPC/Jit64/Jit.h
Expand Up @@ -148,6 +148,7 @@ class Jit64 : public Jitx86Base
void (Gen::XEmitter::*sseOp)(Gen::X64Reg, const Gen::OpArg&),
bool packed, bool preserve_inputs, bool roundRHS = false);
void FloatCompare(UGeckoInstruction inst, bool upper = false);
void UpdateRoundingMode();

// OPCODES
void FallBackToInterpreter(UGeckoInstruction _inst);
Expand Down Expand Up @@ -190,6 +191,12 @@ class Jit64 : public Jitx86Base
void mfcr(UGeckoInstruction inst);
void mcrf(UGeckoInstruction inst);
void mcrxr(UGeckoInstruction inst);
void mcrfs(UGeckoInstruction inst);
void mffsx(UGeckoInstruction inst);
void mtfsb0x(UGeckoInstruction inst);
void mtfsb1x(UGeckoInstruction inst);
void mtfsfix(UGeckoInstruction inst);
void mtfsfx(UGeckoInstruction inst);

void boolX(UGeckoInstruction inst);
void crXXX(UGeckoInstruction inst);
Expand Down
12 changes: 6 additions & 6 deletions Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp
Expand Up @@ -337,12 +337,12 @@ static GekkoOPTemplate table63[] =
{40, &Jit64::fsign}, // fnegx
{12, &Jit64::frspx}, // frspx

{64, &Jit64::FallBackToInterpreter}, // mcrfs
{583, &Jit64::FallBackToInterpreter}, // mffsx
{70, &Jit64::FallBackToInterpreter}, // mtfsb0x
{38, &Jit64::FallBackToInterpreter}, // mtfsb1x
{134, &Jit64::FallBackToInterpreter}, // mtfsfix
{711, &Jit64::FallBackToInterpreter}, // mtfsfx
{64, &Jit64::mcrfs}, // mcrfs
{583, &Jit64::mffsx}, // mffsx
{70, &Jit64::mtfsb0x}, // mtfsb0x
{38, &Jit64::mtfsb1x}, // mtfsb1x
{134, &Jit64::mtfsfix}, // mtfsfix
{711, &Jit64::mtfsfx}, // mtfsfx
};

static GekkoOPTemplate table63_2[] =
Expand Down
183 changes: 183 additions & 0 deletions Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp
Expand Up @@ -556,3 +556,186 @@ void Jit64::crXXX(UGeckoInstruction inst)
// Store result bit in CRBD
SetCRFieldBit(inst.CRBD >> 2, 3 - (inst.CRBD & 3), RSCRATCH);
}

void Jit64::mcrfs(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff);

u8 shift = 4 * (7 - inst.CRFS);
u32 mask = 0xF << shift;

// Only clear exception bits (but not FEX/VX).
mask &= 0x9FF87000;

MOV(32, R(RSCRATCH), PPCSTATE(fpscr));
if (cpu_info.bBMI1)
{
MOV(32, R(RSCRATCH2), Imm32((4 << 8) | shift));
BEXTR(32, RSCRATCH2, R(RSCRATCH), RSCRATCH2);
}
else
{
MOV(32, R(RSCRATCH2), R(RSCRATCH));
SHR(32, R(RSCRATCH2), Imm8(shift));
AND(32, R(RSCRATCH2), Imm32(0xF));
}
AND(32, R(RSCRATCH), Imm32(mask));
MOV(32, PPCSTATE(fpscr), R(RSCRATCH));
LEA(64, RSCRATCH, M(&m_crTable));
MOV(64, R(RSCRATCH), MComplex(RSCRATCH, RSCRATCH2, SCALE_8, 0));
MOV(64, PPCSTATE(cr_val[inst.CRFD]), R(RSCRATCH));
}

void Jit64::mffsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff);
FALLBACK_IF(inst.Rc);

MOV(32, R(RSCRATCH), PPCSTATE(fpscr));

// FPSCR.FEX = 0 (and VX for below)
AND(32, R(RSCRATCH), Imm32(~0x60000000));

// FPSCR.VX = (FPSCR.Hex & FPSCR_VX_ANY) != 0;
XOR(32, R(RSCRATCH2), R(RSCRATCH2));
TEST(32, R(RSCRATCH), Imm32(FPSCR_VX_ANY));
SETcc(CC_NZ, R(RSCRATCH2));
SHL(32, R(RSCRATCH2), Imm8(31 - 2));
OR(32, R(RSCRATCH), R(RSCRATCH2));

MOV(32, PPCSTATE(fpscr), R(RSCRATCH));

int d = inst.FD;
fpr.BindToRegister(d, false, true);
MOVQ_xmm(XMM0, R(RSCRATCH));
MOVSD(fpr.RX(d), R(XMM0));
}

static const u32 s_rn_to_rc[] = { 0 << 13, 3 << 13, 2 << 13, 1 << 13 };

void Jit64::UpdateRoundingMode()
{
static u32 csr;
STMXCSR(M(&csr));
MOV(32, R(RSCRATCH), PPCSTATE(fpscr));
AND(32, R(RSCRATCH), Imm32(3));
LEA(64, RSCRATCH2, M(&s_rn_to_rc));
MOV(32, R(RSCRATCH), MComplex(RSCRATCH2, RSCRATCH, SCALE_4, 0));
OR(32, M(&csr), R(RSCRATCH));
LDMXCSR(M(&csr));
}

void Jit64::mtfsb0x(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff);
FALLBACK_IF(inst.Rc);

AND(32, PPCSTATE(fpscr), Imm32(~(0x80000000 >> inst.CRBD)));

switch (inst.CRBD)
{
case 29:
// NI
static u32 csr;
STMXCSR(M(&csr));
AND(32, M(&csr), Imm32(~(1 << 15)));
LDMXCSR(M(&csr));
break;
case 30:
case 31:
// RN
UpdateRoundingMode();
break;
default:
break;
}
}

void Jit64::mtfsb1x(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff);
FALLBACK_IF(inst.Rc);

OR(32, PPCSTATE(fpscr), Imm32(0x80000000 >> inst.CRBD));

switch (inst.CRBD)
{
case 29:
// NI
static u32 csr;
STMXCSR(M(&csr));
OR(32, M(&csr), Imm32(1 << 15));
LDMXCSR(M(&csr));
break;
case 30:
case 31:
// RN
UpdateRoundingMode();
break;
default:
break;
}
}

void Jit64::mtfsfix(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff);
FALLBACK_IF(inst.Rc);

u8 imm = inst.hex >> (31 - 19);

MOV(32, R(RSCRATCH), PPCSTATE(fpscr));
AND(32, R(RSCRATCH), Imm32(~0xF));
OR(32, R(RSCRATCH), Imm32(imm << (28 - 4 * inst.CRFD)));
MOV(32, PPCSTATE(fpscr), R(RSCRATCH));

// XE, NI, RN
if (inst.CRFD == 7)
{
u32 ftz_bit = (imm & 4) << 13;
u32 rc_mask = s_rn_to_rc[imm & 3];
u32 or_mask = ftz_bit | rc_mask;
u32 all_bits = 7 << 13;
u32 and_mask = all_bits & ~(ftz_bit | rc_mask);

static u32 csr;
STMXCSR(M(&csr));
if (or_mask)
OR(32, M(&csr), Imm32(or_mask));
if (and_mask != all_bits)
AND(32, M(&csr), Imm32(~and_mask));
LDMXCSR(M(&csr));
}
}

void Jit64::mtfsfx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITSystemRegistersOff);
FALLBACK_IF(inst.Rc);

u32 mask = 0;
for (int i = 0; i < 8; i++)
{
if (inst.FM & (1 << i))
mask |= 0xF << (4 * i);
}

int b = inst.FB;
X64Reg xmm = XMM0;
if (fpr.R(b).IsSimpleReg())
xmm = fpr.RX(b);
else
MOVSD(XMM0, fpr.R(b));
MOVQ_xmm(R(RSCRATCH), fpr.RX(inst.FB));
AND(32, R(RSCRATCH), Imm32(mask));
MOV(32, R(RSCRATCH2), PPCSTATE(fpscr));
AND(32, R(RSCRATCH2), Imm32(~mask));
OR(32, R(RSCRATCH), R(RSCRATCH2));
MOV(32, PPCSTATE(fpscr), R(RSCRATCH));
}

0 comments on commit 818142f

Please sign in to comment.