JITIL: Disable all load/store instructions in 64-bit mode. This actually makes a lot of games work - but slowly. Investigation needed. Reindent a bunch of code.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3405 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2009-06-10 19:43:47 +00:00
parent 46f8178ab1
commit 759263351a
10 changed files with 1664 additions and 1639 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -71,6 +71,14 @@ struct CONTEXT
Core::g_CoreStartupParameter.bJIT##type##Off) \
{Default(inst); return;}
#ifdef _M_X64
#define DISABLE64 \
{Default(inst); return;}
#else
#define DISABLE64
#endif
class TrampolineCache : public Gen::XCodeBlock
{
public:
@@ -45,150 +45,149 @@
using namespace Gen;
void Jit64::sc(UGeckoInstruction inst)
{
ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC));
void Jit64::sc(UGeckoInstruction inst)
{
ibuild.EmitSystemCall(ibuild.EmitIntConst(js.compilerPC));
}
void Jit64::rfi(UGeckoInstruction inst)
{
ibuild.EmitRFIExit();
}
void Jit64::bx(UGeckoInstruction inst)
{
NORMALBRANCH_START
INSTRUCTION_START;
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
u32 destination;
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = js.compilerPC + SignExt26(inst.LI << 2);
if (destination == js.compilerPC) {
ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC));
return;
}
void Jit64::rfi(UGeckoInstruction inst)
ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
}
static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst) {
IREmitter::InstLoc CRTest = 0, CTRTest = 0;
if ((inst.BO & 16) == 0) // Test a CR bit
{
ibuild.EmitRFIExit();
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
CRTest = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
CRTest = ibuild.EmitXor(CRTest, CRCmp);
}
void Jit64::bx(UGeckoInstruction inst)
{
NORMALBRANCH_START
INSTRUCTION_START;
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
u32 destination;
if (inst.AA)
destination = SignExt26(inst.LI << 2);
else
destination = js.compilerPC + SignExt26(inst.LI << 2);
if (destination == js.compilerPC) {
ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC));
return;
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
}
static IREmitter::InstLoc TestBranch(IREmitter::IRBuilder& ibuild, UGeckoInstruction inst) {
IREmitter::InstLoc CRTest = 0, CTRTest = 0;
if ((inst.BO & 16) == 0) // Test a CR bit
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
CRTest = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
CRTest = ibuild.EmitXor(CRTest, CRCmp);
}
if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
if (inst.BO & 2) {
CTRTest = ibuild.EmitICmpEq(c,
ibuild.EmitIntConst(0));
} else {
CTRTest = c;
}
}
IREmitter::InstLoc Test = CRTest;
if (CTRTest) {
if (Test)
Test = ibuild.EmitAnd(Test, CTRTest);
else
Test = CTRTest;
}
if (!Test) {
Test = ibuild.EmitIntConst(1);
}
return Test;
}
void Jit64::bcx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (inst.LK)
ibuild.EmitStoreLink(
ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc Test = TestBranch(ibuild, inst);
u32 destination;
if(inst.AA)
destination = SignExt16(inst.BD << 2);
else
destination = js.compilerPC + SignExt16(inst.BD << 2);
if (Core::GetStartupParameter().bSkipIdle &&
inst.hex == 0x4182fff8 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 ||
(Core::GetStartupParameter().bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000))
)
{
ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination));
}
else
{
ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination));
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
void Jit64::bcctrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
}
IREmitter::InstLoc test;
if ((inst.BO & 16) == 0) // Test a CR bit
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
test = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
test = ibuild.EmitXor(test, CRCmp);
if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
if (inst.BO & 2) {
CTRTest = ibuild.EmitICmpEq(c,
ibuild.EmitIntConst(0));
} else {
test = ibuild.EmitIntConst(1);
CTRTest = c;
}
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc destination = ibuild.EmitLoadCTR();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
void Jit64::bclrx(UGeckoInstruction inst)
IREmitter::InstLoc Test = CRTest;
if (CTRTest) {
if (Test)
Test = ibuild.EmitAnd(Test, CTRTest);
else
Test = CTRTest;
}
if (!Test) {
Test = ibuild.EmitIntConst(1);
}
return Test;
}
void Jit64::bcx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (inst.LK)
ibuild.EmitStoreLink(
ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc Test = TestBranch(ibuild, inst);
u32 destination;
if(inst.AA)
destination = SignExt16(inst.BD << 2);
else
destination = js.compilerPC + SignExt16(inst.BD << 2);
if (Core::GetStartupParameter().bSkipIdle &&
inst.hex == 0x4182fff8 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 ||
(Core::GetStartupParameter().bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000))
)
{
ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination));
}
else
{
NORMALBRANCH_START
if (inst.hex == 0x4e800020) {
ibuild.EmitBranchUncond(ibuild.EmitLoadLink());
return;
}
IREmitter::InstLoc test = TestBranch(ibuild, inst);
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc destination = ibuild.EmitLoadLink();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination));
}
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
}
void Jit64::bcctrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if ((inst.BO & 4) == 0) {
IREmitter::InstLoc c = ibuild.EmitLoadCTR();
c = ibuild.EmitSub(c, ibuild.EmitIntConst(1));
ibuild.EmitStoreCTR(c);
}
IREmitter::InstLoc test;
if ((inst.BO & 16) == 0) // Test a CR bit
{
IREmitter::InstLoc CRReg = ibuild.EmitLoadCR(inst.BI >> 2);
IREmitter::InstLoc CRCmp = ibuild.EmitIntConst(8 >> (inst.BI & 3));
test = ibuild.EmitAnd(CRReg, CRCmp);
if (!(inst.BO & 8))
test = ibuild.EmitXor(test, CRCmp);
} else {
test = ibuild.EmitIntConst(1);
}
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc destination = ibuild.EmitLoadCTR();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
void Jit64::bclrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (inst.hex == 0x4e800020) {
ibuild.EmitBranchUncond(ibuild.EmitLoadLink());
return;
}
IREmitter::InstLoc test = TestBranch(ibuild, inst);
test = ibuild.EmitICmpEq(test, ibuild.EmitIntConst(0));
ibuild.EmitBranchCond(test, ibuild.EmitIntConst(js.compilerPC + 4));
IREmitter::InstLoc destination = ibuild.EmitLoadLink();
destination = ibuild.EmitAnd(destination, ibuild.EmitIntConst(-4));
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
ibuild.EmitBranchUncond(destination);
}
@@ -28,86 +28,86 @@
//#define INSTRUCTION_START Default(inst); return;
#define INSTRUCTION_START
void Jit64::fp_arith_s(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
if (inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
switch (inst.SUBOP5)
{
case 25: //mul
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
break;
case 18: //div
case 20: //sub
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 21: //add
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 23: //sel
case 24: //res
default:
_assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!");
}
if (inst.OPCD == 59) {
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
} else {
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
void Jit64::fp_arith_s(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
if (inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) {
Default(inst); return;
}
void Jit64::fmaddXX(UGeckoInstruction inst)
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
switch (inst.SUBOP5)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
case 25: //mul
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
if (inst.SUBOP5 & 1)
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
else
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
if (inst.SUBOP5 & 2)
val = ibuild.EmitFDNeg(val);
if (inst.OPCD == 59) {
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
} else {
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::fmrx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FB);
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
ibuild.EmitStoreFReg(val, inst.FD);
break;
case 18: //div
case 20: //sub
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 21: //add
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
break;
case 23: //sel
case 24: //res
default:
_assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!");
}
void Jit64::fcmpx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
IREmitter::InstLoc lhs, rhs, res;
lhs = ibuild.EmitLoadFRegDENToZero(inst.FA);
rhs = ibuild.EmitLoadFRegDENToZero(inst.FB);
res = ibuild.EmitFDCmpCR(lhs, rhs);
ibuild.EmitStoreFPRF(res);
ibuild.EmitStoreCR(res, inst.CRFD);
if (inst.OPCD == 59) {
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
} else {
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::fmaddXX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
if (inst.SUBOP5 & 1)
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
else
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
if (inst.SUBOP5 & 2)
val = ibuild.EmitFDNeg(val);
if (inst.OPCD == 59) {
val = ibuild.EmitDoubleToSingle(val);
val = ibuild.EmitDupSingleToMReg(val);
} else {
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
}
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::fmrx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FB);
val = ibuild.EmitInsertDoubleInMReg(val, ibuild.EmitLoadFReg(inst.FD));
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::fcmpx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
IREmitter::InstLoc lhs, rhs, res;
lhs = ibuild.EmitLoadFRegDENToZero(inst.FA);
rhs = ibuild.EmitLoadFRegDENToZero(inst.FB);
res = ibuild.EmitFDCmpCR(lhs, rhs);
ibuild.EmitStoreFPRF(res);
ibuild.EmitStoreCR(res, inst.CRFD);
}
File diff suppressed because it is too large Load Diff
@@ -41,6 +41,7 @@
void Jit64::lhax(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA)
@@ -53,6 +54,7 @@ void Jit64::lhax(UGeckoInstruction inst)
void Jit64::lXz(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
@@ -73,6 +75,7 @@ void Jit64::lXz(UGeckoInstruction inst)
void Jit64::lha(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr =
ibuild.EmitIntConst((s32)(s16)inst.SIMM_16);
@@ -86,6 +89,7 @@ void Jit64::lha(UGeckoInstruction inst)
void Jit64::lXzx(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
if (inst.RA) {
@@ -108,6 +112,8 @@ void Jit64::lXzx(UGeckoInstruction inst)
void Jit64::dcbz(UGeckoInstruction inst)
{
Default(inst); return;
// TODO!
#if 0
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff)
{Default(inst); return;} // turn off from debugger
@@ -131,6 +137,7 @@ void Jit64::dcbz(UGeckoInstruction inst)
void Jit64::stX(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16),
value = ibuild.EmitLoadGReg(inst.RS);
@@ -150,6 +157,7 @@ void Jit64::stX(UGeckoInstruction inst)
void Jit64::stXx(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB),
value = ibuild.EmitLoadGReg(inst.RS);
@@ -169,6 +177,7 @@ void Jit64::stXx(UGeckoInstruction inst)
void Jit64::lmw(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
@@ -184,6 +193,7 @@ void Jit64::lmw(UGeckoInstruction inst)
void Jit64::stmw(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStore)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
if (inst.RA)
@@ -45,6 +45,7 @@
void Jit64::lfs(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStoreFloating)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val;
if (inst.RA)
@@ -58,6 +59,7 @@ void Jit64::lfs(UGeckoInstruction inst)
void Jit64::lfd(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStoreFloating)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16), val;
if (inst.RA)
@@ -72,6 +74,7 @@ void Jit64::lfd(UGeckoInstruction inst)
void Jit64::stfd(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStoreFloating)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16),
val = ibuild.EmitLoadFReg(inst.RS);
@@ -87,6 +90,7 @@ void Jit64::stfd(UGeckoInstruction inst)
void Jit64::stfs(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStoreFloating)
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16),
val = ibuild.EmitLoadFReg(inst.RS);
@@ -103,6 +107,7 @@ void Jit64::stfs(UGeckoInstruction inst)
void Jit64::stfsx(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStoreFloating)
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB),
val = ibuild.EmitLoadFReg(inst.RS);
@@ -117,6 +122,7 @@ void Jit64::stfsx(UGeckoInstruction inst)
void Jit64::lfsx(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStoreFloating)
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB), val;
if (inst.RA)
@@ -44,6 +44,7 @@
void Jit64::psq_st(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStorePaired)
if (inst.W || !Core::GetStartupParameter().bOptimizeQuantizers) {Default(inst); return;}
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val;
@@ -59,6 +60,7 @@ void Jit64::psq_st(UGeckoInstruction inst)
void Jit64::psq_l(UGeckoInstruction inst)
{
INSTRUCTION_START
DISABLE64
JITDISABLE(LoadStorePaired)
if (inst.W || !Core::GetStartupParameter().bOptimizeQuantizers) {Default(inst); return;}
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_12), val;
@@ -26,193 +26,193 @@
#include "Jit.h"
#include "JitRegCache.h"
void Jit64::ps_mr(UGeckoInstruction inst)
{
void Jit64::ps_mr(UGeckoInstruction inst)
{
Default(inst); return;
}
void Jit64::ps_sel(UGeckoInstruction inst)
{
Default(inst); return;
}
void Jit64::ps_sign(UGeckoInstruction inst)
{
Default(inst); return;
}
void Jit64::ps_rsqrte(UGeckoInstruction inst)
{
Default(inst); return;
}
void Jit64::ps_arith(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc || (inst.SUBOP5 != 21 && inst.SUBOP5 != 20 && inst.SUBOP5 != 25)) {
Default(inst); return;
}
void Jit64::ps_sel(UGeckoInstruction inst)
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), rhs;
if (inst.SUBOP5 == 25)
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
else
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitCompactMRegToPacked(val);
switch (inst.SUBOP5)
{
Default(inst); return;
}
void Jit64::ps_sign(UGeckoInstruction inst)
{
Default(inst); return;
}
void Jit64::ps_rsqrte(UGeckoInstruction inst)
{
Default(inst); return;
}
void Jit64::ps_arith(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc || (inst.SUBOP5 != 21 && inst.SUBOP5 != 20 && inst.SUBOP5 != 25)) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), rhs;
if (inst.SUBOP5 == 25)
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
else
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitCompactMRegToPacked(val);
switch (inst.SUBOP5)
{
case 20:
val = ibuild.EmitFPSub(val, rhs);
break;
case 21:
val = ibuild.EmitFPAdd(val, rhs);
break;
case 25:
val = ibuild.EmitFPMul(val, rhs);
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::ps_sum(UGeckoInstruction inst)
{
// FIXME: This operation strikes me as a bit strange...
// perhaps we can optimize it depending on the users?
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc || inst.SUBOP5 != 10) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), temp;
val = ibuild.EmitCompactMRegToPacked(val);
val = ibuild.EmitFPDup0(val);
temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, temp);
temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMerge11(val, temp);
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::ps_muls(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA),
rhs = ibuild.EmitLoadFReg(inst.FC);
val = ibuild.EmitCompactMRegToPacked(val);
rhs = ibuild.EmitCompactMRegToPacked(rhs);
if (inst.SUBOP5 == 12)
rhs = ibuild.EmitFPDup0(rhs);
else
rhs = ibuild.EmitFPDup1(rhs);
case 20:
val = ibuild.EmitFPSub(val, rhs);
break;
case 21:
val = ibuild.EmitFPAdd(val, rhs);
break;
case 25:
val = ibuild.EmitFPMul(val, rhs);
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::ps_sum(UGeckoInstruction inst)
{
// FIXME: This operation strikes me as a bit strange...
// perhaps we can optimize it depending on the users?
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc || inst.SUBOP5 != 10) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), temp;
val = ibuild.EmitCompactMRegToPacked(val);
val = ibuild.EmitFPDup0(val);
temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, temp);
temp = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMerge11(val, temp);
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::ps_muls(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA),
rhs = ibuild.EmitLoadFReg(inst.FC);
val = ibuild.EmitCompactMRegToPacked(val);
rhs = ibuild.EmitCompactMRegToPacked(rhs);
if (inst.SUBOP5 == 12)
rhs = ibuild.EmitFPDup0(rhs);
else
rhs = ibuild.EmitFPDup1(rhs);
val = ibuild.EmitFPMul(val, rhs);
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
//TODO: find easy cases and optimize them, do a breakout like ps_arith
void Jit64::ps_mergeXX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FA)),
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
//TODO: find easy cases and optimize them, do a breakout like ps_arith
void Jit64::ps_mergeXX(UGeckoInstruction inst)
switch (inst.SUBOP10)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FA)),
rhs = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
switch (inst.SUBOP10)
{
case 528:
val = ibuild.EmitFPMerge00(val, rhs);
break; //00
case 560:
val = ibuild.EmitFPMerge01(val, rhs);
break; //01
case 592:
val = ibuild.EmitFPMerge10(val, rhs);
break; //10
case 624:
val = ibuild.EmitFPMerge11(val, rhs);
break; //11
default:
_assert_msg_(DYNA_REC, 0, "ps_merge - invalid op");
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
case 528:
val = ibuild.EmitFPMerge00(val, rhs);
break; //00
case 560:
val = ibuild.EmitFPMerge01(val, rhs);
break; //01
case 592:
val = ibuild.EmitFPMerge10(val, rhs);
break; //10
case 624:
val = ibuild.EmitFPMerge11(val, rhs);
break; //11
default:
_assert_msg_(DYNA_REC, 0, "ps_merge - invalid op");
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}
void Jit64::ps_maddXX(UGeckoInstruction inst)
void Jit64::ps_maddXX(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), op2, op3;
val = ibuild.EmitCompactMRegToPacked(val);
switch (inst.SUBOP5)
{
INSTRUCTION_START
JITDISABLE(Paired)
if (inst.Rc) {
Default(inst); return;
}
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA), op2, op3;
val = ibuild.EmitCompactMRegToPacked(val);
switch (inst.SUBOP5)
{
case 14: {//madds0
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
op2 = ibuild.EmitFPDup0(op2);
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 15: {//madds1
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
op2 = ibuild.EmitFPDup1(op2);
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 28: {//msub
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPSub(val, op3);
break;
}
case 29: {//madd
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 30: {//nmsub
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPSub(val, op3);
val = ibuild.EmitFPNeg(val);
break;
}
case 31: {//nmadd
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
val = ibuild.EmitFPNeg(val);
break;
}
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
case 14: {//madds0
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
op2 = ibuild.EmitFPDup0(op2);
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 15: {//madds1
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
op2 = ibuild.EmitFPDup1(op2);
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 28: {//msub
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPSub(val, op3);
break;
}
case 29: {//madd
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
break;
}
case 30: {//nmsub
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPSub(val, op3);
val = ibuild.EmitFPNeg(val);
break;
}
case 31: {//nmadd
op2 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FC));
val = ibuild.EmitFPMul(val, op2);
op3 = ibuild.EmitCompactMRegToPacked(ibuild.EmitLoadFReg(inst.FB));
val = ibuild.EmitFPAdd(val, op3);
val = ibuild.EmitFPNeg(val);
break;
}
}
val = ibuild.EmitExpandPackedToMReg(val);
ibuild.EmitStoreFReg(val, inst.FD);
}