Small WIP JIT improvement: implement stfs.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1782 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
7d08aed4c1
commit
96bab6bdd8
|
@ -1103,6 +1103,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
||||||
regMarkUse(RI, I, getOp1(I), 1);
|
regMarkUse(RI, I, getOp1(I), 1);
|
||||||
regMarkMemAddress(RI, I, getOp2(I), 2);
|
regMarkMemAddress(RI, I, getOp2(I), 2);
|
||||||
break;
|
break;
|
||||||
|
case StoreSingle:
|
||||||
case StorePaired:
|
case StorePaired:
|
||||||
regMarkUse(RI, I, getOp1(I), 1);
|
regMarkUse(RI, I, getOp1(I), 1);
|
||||||
regMarkUse(RI, I, getOp2(I), 2);
|
regMarkUse(RI, I, getOp2(I), 2);
|
||||||
|
@ -1433,6 +1434,21 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
||||||
regNormalRegClear(RI, I);
|
regNormalRegClear(RI, I);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case StoreSingle: {
|
||||||
|
regSpill(RI, EAX);
|
||||||
|
if (fregLocForInst(RI, getOp1(I)).IsSimpleReg()) {
|
||||||
|
Jit->MOVD_xmm(R(EAX), fregLocForInst(RI, getOp1(I)).GetSimpleReg());
|
||||||
|
} else {
|
||||||
|
Jit->MOV(32, R(EAX), fregLocForInst(RI, getOp1(I)));
|
||||||
|
}
|
||||||
|
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp2(I)));
|
||||||
|
RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0);
|
||||||
|
if (RI.IInfo[I - RI.FirstI] & 4)
|
||||||
|
fregClearInst(RI, getOp1(I));
|
||||||
|
if (RI.IInfo[I - RI.FirstI] & 8)
|
||||||
|
regClearInst(RI, getOp2(I));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case StorePaired: {
|
case StorePaired: {
|
||||||
regSpill(RI, EAX);
|
regSpill(RI, EAX);
|
||||||
regSpill(RI, EDX);
|
regSpill(RI, EDX);
|
||||||
|
|
|
@ -163,6 +163,7 @@ namespace IREmitter {
|
||||||
FPNeg,
|
FPNeg,
|
||||||
FResult_End,
|
FResult_End,
|
||||||
StorePaired,
|
StorePaired,
|
||||||
|
StoreSingle,
|
||||||
StoreFReg,
|
StoreFReg,
|
||||||
|
|
||||||
// "Trinary" operators
|
// "Trinary" operators
|
||||||
|
@ -376,6 +377,9 @@ namespace IREmitter {
|
||||||
InstLoc EmitLoadPaired(InstLoc addr, unsigned quantReg) {
|
InstLoc EmitLoadPaired(InstLoc addr, unsigned quantReg) {
|
||||||
return FoldUOp(LoadPaired, addr, quantReg);
|
return FoldUOp(LoadPaired, addr, quantReg);
|
||||||
}
|
}
|
||||||
|
InstLoc EmitStoreSingle(InstLoc value, InstLoc addr) {
|
||||||
|
return FoldBiOp(StoreSingle, value, addr);
|
||||||
|
}
|
||||||
InstLoc EmitStorePaired(InstLoc value, InstLoc addr, unsigned quantReg) {
|
InstLoc EmitStorePaired(InstLoc value, InstLoc addr, unsigned quantReg) {
|
||||||
return FoldBiOp(StorePaired, value, addr, quantReg);
|
return FoldBiOp(StorePaired, value, addr, quantReg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,78 +185,27 @@ void Jit64::stfd(UGeckoInstruction inst)
|
||||||
|
|
||||||
void Jit64::stfs(UGeckoInstruction inst)
|
void Jit64::stfs(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff)
|
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16),
|
||||||
{Default(inst); return;} // turn off from debugger
|
val = ibuild.EmitLoadFReg(inst.RS);
|
||||||
INSTRUCTION_START;
|
if (inst.RA)
|
||||||
|
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
||||||
bool update = inst.OPCD & 1;
|
if (inst.OPCD & 1)
|
||||||
int s = inst.RS;
|
ibuild.EmitStoreGReg(addr, inst.RA);
|
||||||
int a = inst.RA;
|
val = ibuild.EmitDoubleToSingle(val);
|
||||||
s32 offset = (s32)(s16)inst.SIMM_16;
|
ibuild.EmitStoreSingle(val, addr);
|
||||||
if (!a || update) {
|
return;
|
||||||
Default(inst);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gpr.R(a).IsImm())
|
|
||||||
{
|
|
||||||
u32 addr = (u32)(gpr.R(a).offset + offset);
|
|
||||||
if (Memory::IsRAMAddress(addr))
|
|
||||||
{
|
|
||||||
if (cpu_info.bSSSE3) {
|
|
||||||
CVTSD2SS(XMM0, fpr.R(s));
|
|
||||||
PSHUFB(XMM0, M((void *)bswapShuffle1x4));
|
|
||||||
WriteFloatToConstRamAddress(XMM0, addr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (addr == 0xCC008000)
|
|
||||||
{
|
|
||||||
// Float directly to write gather pipe! Fun!
|
|
||||||
CVTSD2SS(XMM0, fpr.R(s));
|
|
||||||
CALL((void*)asm_routines.fifoDirectWriteFloat);
|
|
||||||
// TODO
|
|
||||||
js.fifoBytesThisBlock += 4;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gpr.FlushLockX(ABI_PARAM1, ABI_PARAM2);
|
|
||||||
gpr.Lock(a);
|
|
||||||
fpr.Lock(s);
|
|
||||||
MOV(32, R(ABI_PARAM2), gpr.R(a));
|
|
||||||
ADD(32, R(ABI_PARAM2), Imm32(offset));
|
|
||||||
if (update && offset)
|
|
||||||
{
|
|
||||||
MOV(32, gpr.R(a), R(ABI_PARAM2));
|
|
||||||
}
|
|
||||||
CVTSD2SS(XMM0, fpr.R(s));
|
|
||||||
MOVSS(M(&temp32), XMM0);
|
|
||||||
MOV(32, R(ABI_PARAM1), M(&temp32));
|
|
||||||
SafeWriteRegToReg(ABI_PARAM1, ABI_PARAM2, 32, 0);
|
|
||||||
gpr.UnlockAll();
|
|
||||||
gpr.UnlockAllX();
|
|
||||||
fpr.UnlockAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Jit64::stfsx(UGeckoInstruction inst)
|
void Jit64::stfsx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff)
|
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB),
|
||||||
{Default(inst); return;} // turn off from debugger
|
val = ibuild.EmitLoadFReg(inst.RS);
|
||||||
INSTRUCTION_START;
|
|
||||||
|
|
||||||
// We can take a shortcut here - it's not likely that a hardware access would use this instruction.
|
|
||||||
gpr.FlushLockX(ABI_PARAM1);
|
|
||||||
fpr.Lock(inst.RS);
|
|
||||||
MOV(32, R(ABI_PARAM1), gpr.R(inst.RB));
|
|
||||||
if (inst.RA)
|
if (inst.RA)
|
||||||
ADD(32, R(ABI_PARAM1), gpr.R(inst.RA));
|
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
||||||
CVTSD2SS(XMM0, fpr.R(inst.RS));
|
val = ibuild.EmitDoubleToSingle(val);
|
||||||
MOVD_xmm(R(EAX), XMM0);
|
ibuild.EmitStoreSingle(val, addr);
|
||||||
UnsafeWriteRegToReg(EAX, ABI_PARAM1, 32, 0);
|
return;
|
||||||
gpr.UnlockAllX();
|
|
||||||
fpr.UnlockAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue