mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
Misc accumulated Jit64IL work; I don't recall whether any of these
changes individually led to perf improvements, although overall it's spending a lot less time in interpreter fallbacks. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1904 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
9cb25d6ba2
commit
ee2bf31e56
@ -38,7 +38,7 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Include
|
// Include
|
||||||
// ¯¯¯¯¯¯¯¯¯¯
|
// ¯¯¯¯¯¯¯¯¯¯
|
||||||
#ifdef JITTEST
|
#if JITTEST
|
||||||
#include "../Jit64IL/Jit.h"
|
#include "../Jit64IL/Jit.h"
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -1197,11 +1197,9 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
case RFIExit:
|
case RFIExit:
|
||||||
case InterpreterBranch:
|
case InterpreterBranch:
|
||||||
case IdleLoop:
|
case IdleLoop:
|
||||||
// No liveness effects
|
case ShortIdleLoop:
|
||||||
break;
|
|
||||||
case Tramp:
|
case Tramp:
|
||||||
if (thisUsed)
|
// No liveness effects
|
||||||
regMarkUse(RI, I, I - 1 - (*I >> 8), 1);
|
|
||||||
break;
|
break;
|
||||||
case SExt8:
|
case SExt8:
|
||||||
case SExt16:
|
case SExt16:
|
||||||
@ -1232,6 +1230,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
break;
|
break;
|
||||||
case StoreCR:
|
case StoreCR:
|
||||||
case StoreCarry:
|
case StoreCarry:
|
||||||
|
case StoreFPRF:
|
||||||
regMarkUse(RI, I, getOp1(I), 1);
|
regMarkUse(RI, I, getOp1(I), 1);
|
||||||
break;
|
break;
|
||||||
case StoreGReg:
|
case StoreGReg:
|
||||||
@ -1277,6 +1276,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
case FPMerge01:
|
case FPMerge01:
|
||||||
case FPMerge10:
|
case FPMerge10:
|
||||||
case FPMerge11:
|
case FPMerge11:
|
||||||
|
case FDCmpCR:
|
||||||
case InsertDoubleInMReg:
|
case InsertDoubleInMReg:
|
||||||
if (thisUsed) {
|
if (thisUsed) {
|
||||||
regMarkUse(RI, I, getOp1(I), 1);
|
regMarkUse(RI, I, getOp1(I), 1);
|
||||||
@ -1411,6 +1411,15 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
regNormalRegClear(RI, I);
|
regNormalRegClear(RI, I);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case StoreFPRF: {
|
||||||
|
Jit->MOV(32, R(ECX), regLocForInst(RI, getOp1(I)));
|
||||||
|
Jit->AND(32, R(ECX), Imm8(0x1F));
|
||||||
|
Jit->SHL(32, R(ECX), Imm8(12));
|
||||||
|
Jit->AND(32, M(&FPSCR), Imm32(~(0x1F << 12)));
|
||||||
|
Jit->OR(32, M(&FPSCR), R(ECX));
|
||||||
|
regNormalRegClear(RI, I);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Load8: {
|
case Load8: {
|
||||||
regEmitMemLoad(RI, I, 8);
|
regEmitMemLoad(RI, I, 8);
|
||||||
break;
|
break;
|
||||||
@ -1851,6 +1860,35 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
fregEmitBinInst(RI, I, &Jit64::SUBSD);
|
fregEmitBinInst(RI, I, &Jit64::SUBSD);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case FDCmpCR: {
|
||||||
|
X64Reg destreg = regFindFreeReg(RI);
|
||||||
|
// TODO: Add case for NaN (CC_P)
|
||||||
|
Jit->MOVSD(XMM0, fregLocForInst(RI, getOp1(I)));
|
||||||
|
Jit->UCOMISD(XMM0, fregLocForInst(RI, getOp2(I)));
|
||||||
|
FixupBranch pNan = Jit->J_CC(CC_P);
|
||||||
|
FixupBranch pEqual = Jit->J_CC(CC_Z);
|
||||||
|
FixupBranch pLesser = Jit->J_CC(CC_C);
|
||||||
|
// Greater
|
||||||
|
Jit->MOV(32, R(destreg), Imm32(0x4));
|
||||||
|
FixupBranch continue1 = Jit->J();
|
||||||
|
// NaN
|
||||||
|
Jit->SetJumpTarget(pNan);
|
||||||
|
Jit->MOV(32, R(destreg), Imm32(0x1));
|
||||||
|
FixupBranch continue2 = Jit->J();
|
||||||
|
// Equal
|
||||||
|
Jit->SetJumpTarget(pEqual);
|
||||||
|
Jit->MOV(32, R(destreg), Imm32(0x2));
|
||||||
|
FixupBranch continue3 = Jit->J();
|
||||||
|
// Less
|
||||||
|
Jit->SetJumpTarget(pLesser);
|
||||||
|
Jit->MOV(32, R(destreg), Imm32(0x8));
|
||||||
|
Jit->SetJumpTarget(continue1);
|
||||||
|
Jit->SetJumpTarget(continue2);
|
||||||
|
Jit->SetJumpTarget(continue3);
|
||||||
|
RI.regs[destreg] = I;
|
||||||
|
fregNormalRegClear(RI, I);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case FPAdd: {
|
case FPAdd: {
|
||||||
if (!thisUsed) break;
|
if (!thisUsed) break;
|
||||||
fregEmitBinInst(RI, I, &Jit64::ADDPS);
|
fregEmitBinInst(RI, I, &Jit64::ADDPS);
|
||||||
@ -1962,7 +2000,14 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
unsigned IdleParam = ibuild->GetImmValue(getOp1(I));
|
unsigned IdleParam = ibuild->GetImmValue(getOp1(I));
|
||||||
unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
|
unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
|
||||||
Jit->ABI_CallFunctionC((void *)&PowerPC::OnIdle, IdleParam);
|
Jit->ABI_CallFunctionC((void *)&PowerPC::OnIdle, IdleParam);
|
||||||
Jit->MOV(32, M(&PowerPC::ppcState.pc), Imm32(InstLoc + 12));
|
Jit->MOV(32, M(&PC), Imm32(InstLoc + 12));
|
||||||
|
Jit->JMP(asm_routines.testExceptions, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ShortIdleLoop: {
|
||||||
|
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
|
||||||
|
Jit->ABI_CallFunction((void *)&CoreTiming::Idle);
|
||||||
|
Jit->MOV(32, M(&PC), Imm32(InstLoc));
|
||||||
Jit->JMP(asm_routines.testExceptions, true);
|
Jit->JMP(asm_routines.testExceptions, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1998,25 +2043,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
Jit->WriteRfiExitDestInEAX();
|
Jit->WriteRfiExitDestInEAX();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Tramp: {
|
case Tramp: break;
|
||||||
if (!thisUsed) break;
|
|
||||||
// FIXME: Optimize!
|
|
||||||
InstLoc Op = I - 1 - (*I >> 8);
|
|
||||||
if (isFResult(*Op)) {
|
|
||||||
X64Reg reg = fregFindFreeReg(RI);
|
|
||||||
Jit->MOVAPD(reg, fregLocForInst(RI, Op));
|
|
||||||
RI.fregs[reg] = I;
|
|
||||||
if (RI.IInfo[I - RI.FirstI] & 4)
|
|
||||||
fregClearInst(RI, Op);
|
|
||||||
} else {
|
|
||||||
X64Reg reg = regFindFreeReg(RI);
|
|
||||||
Jit->MOV(32, R(reg), regLocForInst(RI, Op));
|
|
||||||
RI.regs[reg] = I;
|
|
||||||
if (RI.IInfo[I - RI.FirstI] & 4)
|
|
||||||
regClearInst(RI, Op);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Nop: break;
|
case Nop: break;
|
||||||
default:
|
default:
|
||||||
PanicAlert("Unknown JIT instruction; aborting!");
|
PanicAlert("Unknown JIT instruction; aborting!");
|
||||||
@ -2034,7 +2061,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UseProfile && RI.numSpills)
|
if (!RI.MakeProfile && RI.numSpills)
|
||||||
printf("Block: %x, numspills %d\n", Jit->js.blockStart, RI.numSpills);
|
printf("Block: %x, numspills %d\n", Jit->js.blockStart, RI.numSpills);
|
||||||
|
|
||||||
Jit->UD2();
|
Jit->UD2();
|
||||||
|
@ -54,6 +54,7 @@ namespace IREmitter {
|
|||||||
StoreCarry,
|
StoreCarry,
|
||||||
StoreCTR,
|
StoreCTR,
|
||||||
StoreMSR,
|
StoreMSR,
|
||||||
|
StoreFPRF,
|
||||||
// Arbitrary interpreter instruction
|
// Arbitrary interpreter instruction
|
||||||
InterpreterFallback,
|
InterpreterFallback,
|
||||||
|
|
||||||
@ -184,6 +185,7 @@ namespace IREmitter {
|
|||||||
StoreSingle,
|
StoreSingle,
|
||||||
StoreDouble,
|
StoreDouble,
|
||||||
StoreFReg,
|
StoreFReg,
|
||||||
|
FDCmpCR,
|
||||||
|
|
||||||
// "Trinary" operators
|
// "Trinary" operators
|
||||||
// FIXME: Need to change representation!
|
// FIXME: Need to change representation!
|
||||||
@ -197,7 +199,9 @@ namespace IREmitter {
|
|||||||
SystemCall,
|
SystemCall,
|
||||||
RFIExit,
|
RFIExit,
|
||||||
InterpreterBranch,
|
InterpreterBranch,
|
||||||
IdleLoop,
|
IdleLoop, // The "usual" idle loop, load+compare+branch
|
||||||
|
ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong,
|
||||||
|
// just a branch
|
||||||
|
|
||||||
// "Opcode" representing a register too far away to
|
// "Opcode" representing a register too far away to
|
||||||
// reference directly; this is a size optimization
|
// reference directly; this is a size optimization
|
||||||
@ -227,11 +231,19 @@ namespace IREmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InstLoc inline getOp1(InstLoc i) {
|
InstLoc inline getOp1(InstLoc i) {
|
||||||
return i - 1 - ((*i >> 8) & 255);
|
i = i - 1 - ((*i >> 8) & 255);
|
||||||
|
if (getOpcode(*i) == Tramp) {
|
||||||
|
i = i - 1 - (*i >> 8);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
InstLoc inline getOp2(InstLoc i) {
|
InstLoc inline getOp2(InstLoc i) {
|
||||||
return i - 1 - ((*i >> 16) & 255);
|
i = i - 1 - ((*i >> 16) & 255);
|
||||||
|
if (getOpcode(*i) == Tramp) {
|
||||||
|
i = i - 1 - (*i >> 8);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
class IRBuilder {
|
class IRBuilder {
|
||||||
@ -288,6 +300,9 @@ namespace IREmitter {
|
|||||||
InstLoc EmitStoreMSR(InstLoc val) {
|
InstLoc EmitStoreMSR(InstLoc val) {
|
||||||
return FoldUOp(StoreMSR, val);
|
return FoldUOp(StoreMSR, val);
|
||||||
}
|
}
|
||||||
|
InstLoc EmitStoreFPRF(InstLoc value) {
|
||||||
|
return FoldUOp(StoreFPRF, value);
|
||||||
|
}
|
||||||
InstLoc EmitLoadGReg(unsigned reg) {
|
InstLoc EmitLoadGReg(unsigned reg) {
|
||||||
return FoldZeroOp(LoadGReg, reg);
|
return FoldZeroOp(LoadGReg, reg);
|
||||||
}
|
}
|
||||||
@ -390,6 +405,9 @@ namespace IREmitter {
|
|||||||
InstLoc EmitInterpreterBranch() {
|
InstLoc EmitInterpreterBranch() {
|
||||||
return FoldZeroOp(InterpreterBranch, 0);
|
return FoldZeroOp(InterpreterBranch, 0);
|
||||||
}
|
}
|
||||||
|
InstLoc EmitLoadCarry() {
|
||||||
|
return FoldZeroOp(LoadCarry, 0);
|
||||||
|
}
|
||||||
InstLoc EmitStoreCarry(InstLoc op1) {
|
InstLoc EmitStoreCarry(InstLoc op1) {
|
||||||
return FoldUOp(StoreCarry, op1);
|
return FoldUOp(StoreCarry, op1);
|
||||||
}
|
}
|
||||||
@ -402,6 +420,9 @@ namespace IREmitter {
|
|||||||
InstLoc EmitIdleLoop(InstLoc idleParam, InstLoc pc) {
|
InstLoc EmitIdleLoop(InstLoc idleParam, InstLoc pc) {
|
||||||
return FoldBiOp(IdleLoop, idleParam, pc);
|
return FoldBiOp(IdleLoop, idleParam, pc);
|
||||||
}
|
}
|
||||||
|
InstLoc EmitShortIdleLoop(InstLoc pc) {
|
||||||
|
return FoldUOp(ShortIdleLoop, pc);
|
||||||
|
}
|
||||||
InstLoc EmitLoadSingle(InstLoc addr) {
|
InstLoc EmitLoadSingle(InstLoc addr) {
|
||||||
return FoldUOp(LoadSingle, addr);
|
return FoldUOp(LoadSingle, addr);
|
||||||
}
|
}
|
||||||
@ -498,6 +519,9 @@ namespace IREmitter {
|
|||||||
InstLoc EmitDoubleToSingle(InstLoc op1) {
|
InstLoc EmitDoubleToSingle(InstLoc op1) {
|
||||||
return FoldUOp(DoubleToSingle, op1);
|
return FoldUOp(DoubleToSingle, op1);
|
||||||
}
|
}
|
||||||
|
InstLoc EmitFDCmpCR(InstLoc op1, InstLoc op2) {
|
||||||
|
return FoldBiOp(FDCmpCR, op1, op2);
|
||||||
|
}
|
||||||
|
|
||||||
void StartBackPass() { curReadPtr = &InstList[InstList.size()]; }
|
void StartBackPass() { curReadPtr = &InstList[InstList.size()]; }
|
||||||
void StartForwardPass() { curReadPtr = &InstList[0]; }
|
void StartForwardPass() { curReadPtr = &InstList[0]; }
|
||||||
|
@ -280,11 +280,8 @@ public:
|
|||||||
void subfx(UGeckoInstruction inst);
|
void subfx(UGeckoInstruction inst);
|
||||||
void subfex(UGeckoInstruction inst);
|
void subfex(UGeckoInstruction inst);
|
||||||
|
|
||||||
void lbzx(UGeckoInstruction inst);
|
void lXzx(UGeckoInstruction inst);
|
||||||
void lwzx(UGeckoInstruction inst);
|
|
||||||
void lhax(UGeckoInstruction inst);
|
void lhax(UGeckoInstruction inst);
|
||||||
|
|
||||||
void lwzux(UGeckoInstruction inst);
|
|
||||||
|
|
||||||
void stXx(UGeckoInstruction inst);
|
void stXx(UGeckoInstruction inst);
|
||||||
|
|
||||||
|
@ -68,6 +68,11 @@ using namespace Gen;
|
|||||||
else
|
else
|
||||||
destination = js.compilerPC + SignExt26(inst.LI << 2);
|
destination = js.compilerPC + SignExt26(inst.LI << 2);
|
||||||
|
|
||||||
|
if (destination == js.compilerPC) {
|
||||||
|
ibuild.EmitShortIdleLoop(ibuild.EmitIntConst(js.compilerPC));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
|
ibuild.EmitBranchUncond(ibuild.EmitIntConst(destination));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +114,8 @@ using namespace Gen;
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!Test) {
|
if (!Test) {
|
||||||
PanicAlert("Unconditional conditional branch?!");
|
Test = ibuild.EmitIntConst(1);
|
||||||
|
//PanicAlert("Unconditional conditional branch?!");
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 destination;
|
u32 destination;
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
void Jit64::fp_arith_s(UGeckoInstruction inst)
|
void Jit64::fp_arith_s(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (inst.Rc || inst.OPCD != 59 || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) {
|
if (inst.Rc || (inst.SUBOP5 != 25 && inst.SUBOP5 != 20 && inst.SUBOP5 != 21)) {
|
||||||
Default(inst); return;
|
Default(inst); return;
|
||||||
}
|
}
|
||||||
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
|
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
|
||||||
@ -61,22 +61,24 @@
|
|||||||
|
|
||||||
void Jit64::fmaddXX(UGeckoInstruction inst)
|
void Jit64::fmaddXX(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
if (inst.Rc || inst.OPCD != 59) {
|
if (inst.Rc) {
|
||||||
Default(inst); return;
|
Default(inst); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool single_precision = inst.OPCD == 59;
|
|
||||||
|
|
||||||
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
|
IREmitter::InstLoc val = ibuild.EmitLoadFReg(inst.FA);
|
||||||
val = ibuild.EmitDoubleToSingle(val);
|
val = ibuild.EmitFDMul(val, ibuild.EmitLoadFReg(inst.FC));
|
||||||
val = ibuild.EmitFSMul(val, ibuild.EmitDoubleToSingle(ibuild.EmitLoadFReg(inst.FC)));
|
|
||||||
if (inst.SUBOP5 & 1)
|
if (inst.SUBOP5 & 1)
|
||||||
val = ibuild.EmitFSAdd(val, ibuild.EmitDoubleToSingle(ibuild.EmitLoadFReg(inst.FB)));
|
val = ibuild.EmitFDAdd(val, ibuild.EmitLoadFReg(inst.FB));
|
||||||
else
|
else
|
||||||
val = ibuild.EmitFSSub(val, ibuild.EmitDoubleToSingle(ibuild.EmitLoadFReg(inst.FB)));
|
val = ibuild.EmitFDSub(val, ibuild.EmitLoadFReg(inst.FB));
|
||||||
if (inst.SUBOP5 & 2)
|
if (inst.SUBOP5 & 2)
|
||||||
val = ibuild.EmitFSNeg(val);
|
val = ibuild.EmitFDNeg(val);
|
||||||
val = ibuild.EmitDupSingleToMReg(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);
|
ibuild.EmitStoreFReg(val, inst.FD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,6 +94,11 @@
|
|||||||
|
|
||||||
void Jit64::fcmpx(UGeckoInstruction inst)
|
void Jit64::fcmpx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
Default(inst);
|
printf("fcmpx at %x\n", js.compilerPC);
|
||||||
return;
|
IREmitter::InstLoc lhs, rhs, res;
|
||||||
|
lhs = ibuild.EmitLoadFReg(inst.FA);
|
||||||
|
rhs = ibuild.EmitLoadFReg(inst.FB);
|
||||||
|
res = ibuild.EmitFDCmpCR(lhs, rhs);
|
||||||
|
ibuild.EmitStoreFPRF(res);
|
||||||
|
ibuild.EmitStoreCR(res, inst.CRFD);
|
||||||
}
|
}
|
||||||
|
@ -211,19 +211,21 @@
|
|||||||
|
|
||||||
void Jit64::subfex(UGeckoInstruction inst)
|
void Jit64::subfex(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START;
|
if (inst.OE) PanicAlert("OE: subfex");
|
||||||
Default(inst);
|
IREmitter::InstLoc val, test, lhs, rhs, carry;
|
||||||
return;
|
rhs = ibuild.EmitLoadGReg(inst.RA);
|
||||||
/*
|
carry = ibuild.EmitLoadCarry();
|
||||||
u32 a = m_GPR[_inst.RA];
|
rhs = ibuild.EmitXor(rhs, ibuild.EmitIntConst(-1));
|
||||||
u32 b = m_GPR[_inst.RB];
|
rhs = ibuild.EmitAdd(rhs, carry);
|
||||||
int carry = GetCarry();
|
test = ibuild.EmitICmpEq(rhs, ibuild.EmitIntConst(0));
|
||||||
m_GPR[_inst.RD] = (~a) + b + carry;
|
test = ibuild.EmitAnd(test, carry);
|
||||||
SetCarry(Helper_Carry(~a, b) || Helper_Carry((~a) + b, carry));
|
lhs = ibuild.EmitLoadGReg(inst.RB);
|
||||||
|
val = ibuild.EmitAdd(lhs, rhs);
|
||||||
if (_inst.OE) PanicAlert("OE: subfcx");
|
ibuild.EmitStoreGReg(val, inst.RD);
|
||||||
if (_inst.Rc) Helper_UpdateCR0(m_GPR[_inst.RD]);
|
test = ibuild.EmitOr(test, ibuild.EmitICmpUgt(lhs, val));
|
||||||
*/
|
ibuild.EmitStoreCarry(test);
|
||||||
|
if (inst.Rc)
|
||||||
|
ComputeRC(ibuild, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::subfx(UGeckoInstruction inst)
|
void Jit64::subfx(UGeckoInstruction inst)
|
||||||
|
@ -39,24 +39,6 @@
|
|||||||
//#define INSTRUCTION_START Default(inst); return;
|
//#define INSTRUCTION_START Default(inst); return;
|
||||||
#define INSTRUCTION_START
|
#define INSTRUCTION_START
|
||||||
|
|
||||||
void Jit64::lbzx(UGeckoInstruction inst)
|
|
||||||
{
|
|
||||||
INSTRUCTION_START
|
|
||||||
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
|
|
||||||
if (inst.RA)
|
|
||||||
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
|
||||||
ibuild.EmitStoreGReg(ibuild.EmitLoad8(addr), inst.RD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Jit64::lwzx(UGeckoInstruction inst)
|
|
||||||
{
|
|
||||||
INSTRUCTION_START
|
|
||||||
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
|
|
||||||
if (inst.RA)
|
|
||||||
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
|
||||||
ibuild.EmitStoreGReg(ibuild.EmitLoad32(addr), inst.RD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Jit64::lhax(UGeckoInstruction inst)
|
void Jit64::lhax(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
@ -113,15 +95,24 @@ void Jit64::lha(UGeckoInstruction inst)
|
|||||||
ibuild.EmitStoreGReg(val, inst.RD);
|
ibuild.EmitStoreGReg(val, inst.RD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::lwzux(UGeckoInstruction inst)
|
void Jit64::lXzx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
|
IREmitter::InstLoc addr = ibuild.EmitLoadGReg(inst.RB);
|
||||||
if (inst.RA) {
|
if (inst.RA) {
|
||||||
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
||||||
ibuild.EmitStoreGReg(addr, inst.RA);
|
if (inst.SUBOP10 & 32)
|
||||||
|
ibuild.EmitStoreGReg(addr, inst.RA);
|
||||||
}
|
}
|
||||||
ibuild.EmitStoreGReg(ibuild.EmitLoad32(addr), inst.RD);
|
IREmitter::InstLoc val;
|
||||||
|
switch (inst.SUBOP10 & ~32)
|
||||||
|
{
|
||||||
|
default: PanicAlert("lXzx: invalid access size");
|
||||||
|
case 23: val = ibuild.EmitLoad32(addr); break; //lwzx
|
||||||
|
case 279: val = ibuild.EmitLoad16(addr); break; //lhzx
|
||||||
|
case 87: val = ibuild.EmitLoad8(addr); break; //lbzx
|
||||||
|
}
|
||||||
|
ibuild.EmitStoreGReg(val, inst.RD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zero cache line.
|
// Zero cache line.
|
||||||
@ -183,10 +174,28 @@ void Jit64::stXx(UGeckoInstruction inst)
|
|||||||
// A few games use these heavily in video codecs.
|
// A few games use these heavily in video codecs.
|
||||||
void Jit64::lmw(UGeckoInstruction inst)
|
void Jit64::lmw(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
Default(inst); return;
|
INSTRUCTION_START
|
||||||
|
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
|
||||||
|
if (inst.RA)
|
||||||
|
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
||||||
|
for (int i = inst.RD; i < 32; i++)
|
||||||
|
{
|
||||||
|
IREmitter::InstLoc val = ibuild.EmitLoad32(addr);
|
||||||
|
ibuild.EmitStoreGReg(val, i);
|
||||||
|
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit64::stmw(UGeckoInstruction inst)
|
void Jit64::stmw(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
Default(inst); return;
|
INSTRUCTION_START
|
||||||
|
IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16);
|
||||||
|
if (inst.RA)
|
||||||
|
addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA));
|
||||||
|
for (int i = inst.RD; i < 32; i++)
|
||||||
|
{
|
||||||
|
IREmitter::InstLoc val = ibuild.EmitLoadGReg(i);
|
||||||
|
ibuild.EmitStore32(val, addr);
|
||||||
|
addr = ibuild.EmitAdd(addr, ibuild.EmitIntConst(4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,12 +167,21 @@ static GekkoOPTemplate primarytable[] =
|
|||||||
{28, Interpreter::andi_rc, &Jit64::reg_imm, {"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
|
{28, Interpreter::andi_rc, &Jit64::reg_imm, {"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
|
||||||
{29, Interpreter::andis_rc, &Jit64::reg_imm, {"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
|
{29, Interpreter::andis_rc, &Jit64::reg_imm, {"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
|
||||||
|
|
||||||
|
#if JITTEST
|
||||||
|
{32, Interpreter::lwz, &Jit64::lXz, {"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
||||||
|
{33, Interpreter::lwzu, &Jit64::lXz, {"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
||||||
|
{34, Interpreter::lbz, &Jit64::lXz, {"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
||||||
|
{35, Interpreter::lbzu, &Jit64::lXz, {"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
||||||
|
{40, Interpreter::lhz, &Jit64::lXz, {"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
||||||
|
{41, Interpreter::lhzu, &Jit64::lXz, {"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
||||||
|
#else
|
||||||
{32, Interpreter::lwz, &Jit64::lXz, {"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
{32, Interpreter::lwz, &Jit64::lXz, {"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
||||||
{33, Interpreter::lwzu, &Jit64::Default, {"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
{33, Interpreter::lwzu, &Jit64::Default, {"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
||||||
{34, Interpreter::lbz, &Jit64::lXz, {"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
{34, Interpreter::lbz, &Jit64::lXz, {"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
||||||
{35, Interpreter::lbzu, &Jit64::Default, {"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
{35, Interpreter::lbzu, &Jit64::Default, {"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
||||||
{40, Interpreter::lhz, &Jit64::lXz, {"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
{40, Interpreter::lhz, &Jit64::lXz, {"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
||||||
{41, Interpreter::lhzu, &Jit64::Default, {"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
{41, Interpreter::lhzu, &Jit64::Default, {"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
||||||
|
#endif
|
||||||
{42, Interpreter::lha, &Jit64::lha, {"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
{42, Interpreter::lha, &Jit64::lha, {"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
|
||||||
{43, Interpreter::lhau, &Jit64::Default, {"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
{43, Interpreter::lhau, &Jit64::Default, {"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
|
||||||
|
|
||||||
@ -302,13 +311,33 @@ static GekkoOPTemplate table31[] =
|
|||||||
{24, Interpreter::slwx, &Jit64::slwx, {"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
|
{24, Interpreter::slwx, &Jit64::slwx, {"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
|
||||||
|
|
||||||
{54, Interpreter::dcbst, &Jit64::Default, {"dcbst", OPTYPE_DCACHE, 0, 4}},
|
{54, Interpreter::dcbst, &Jit64::Default, {"dcbst", OPTYPE_DCACHE, 0, 4}},
|
||||||
|
#if JITTEST
|
||||||
|
{86, Interpreter::dcbf, &Jit64::DoNothing, {"dcbf", OPTYPE_DCACHE, 0, 4}},
|
||||||
|
#else
|
||||||
{86, Interpreter::dcbf, &Jit64::Default, {"dcbf", OPTYPE_DCACHE, 0, 4}},
|
{86, Interpreter::dcbf, &Jit64::Default, {"dcbf", OPTYPE_DCACHE, 0, 4}},
|
||||||
|
#endif
|
||||||
{246, Interpreter::dcbtst, &Jit64::Default, {"dcbtst", OPTYPE_DCACHE, 0, 1}},
|
{246, Interpreter::dcbtst, &Jit64::Default, {"dcbtst", OPTYPE_DCACHE, 0, 1}},
|
||||||
{278, Interpreter::dcbt, &Jit64::Default, {"dcbt", OPTYPE_DCACHE, 0, 1}},
|
{278, Interpreter::dcbt, &Jit64::Default, {"dcbt", OPTYPE_DCACHE, 0, 1}},
|
||||||
{470, Interpreter::dcbi, &Jit64::Default, {"dcbi", OPTYPE_DCACHE, 0, 4}},
|
{470, Interpreter::dcbi, &Jit64::Default, {"dcbi", OPTYPE_DCACHE, 0, 4}},
|
||||||
{758, Interpreter::dcba, &Jit64::Default, {"dcba", OPTYPE_DCACHE, 0, 4}},
|
{758, Interpreter::dcba, &Jit64::Default, {"dcba", OPTYPE_DCACHE, 0, 4}},
|
||||||
{1014, Interpreter::dcbz, &Jit64::dcbz, {"dcbz", OPTYPE_DCACHE, 0, 4}},
|
{1014, Interpreter::dcbz, &Jit64::dcbz, {"dcbz", OPTYPE_DCACHE, 0, 4}},
|
||||||
|
#if JITTEST
|
||||||
|
//load word
|
||||||
|
{23, Interpreter::lwzx, &Jit64::lXzx, {"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
|
{55, Interpreter::lwzux, &Jit64::lXzx, {"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
||||||
|
|
||||||
|
//load halfword
|
||||||
|
{279, Interpreter::lhzx, &Jit64::lXzx, {"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
|
{311, Interpreter::lhzux, &Jit64::lXzx, {"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
||||||
|
|
||||||
|
//load halfword signextend
|
||||||
|
{343, Interpreter::lhax, &Jit64::lhax, {"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
|
{375, Interpreter::lhaux, &Jit64::Default, {"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
||||||
|
|
||||||
|
//load byte
|
||||||
|
{87, Interpreter::lbzx, &Jit64::lXzx, {"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
|
{119, Interpreter::lbzux, &Jit64::lXzx, {"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
||||||
|
#else
|
||||||
//load word
|
//load word
|
||||||
{23, Interpreter::lwzx, &Jit64::lwzx, {"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
{23, Interpreter::lwzx, &Jit64::lwzx, {"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
{55, Interpreter::lwzux, &Jit64::lwzux, {"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
{55, Interpreter::lwzux, &Jit64::lwzux, {"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
||||||
@ -324,7 +353,7 @@ static GekkoOPTemplate table31[] =
|
|||||||
//load byte
|
//load byte
|
||||||
{87, Interpreter::lbzx, &Jit64::lbzx, {"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
{87, Interpreter::lbzx, &Jit64::lbzx, {"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
{119, Interpreter::lbzux, &Jit64::Default, {"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
{119, Interpreter::lbzux, &Jit64::Default, {"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
|
||||||
|
#endif
|
||||||
//load byte reverse
|
//load byte reverse
|
||||||
{534, Interpreter::lwbrx, &Jit64::Default, {"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
{534, Interpreter::lwbrx, &Jit64::Default, {"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
{790, Interpreter::lhbrx, &Jit64::Default, {"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
{790, Interpreter::lhbrx, &Jit64::Default, {"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user