Remove JitArmIL files from the project.

Due to how the new CR-flags work, it isn't possible without some hefty work in the JITIL backend to support this on 32bit systems.
This commit is contained in:
Ryan Houdek 2014-07-04 03:43:55 -05:00 committed by Pierre Bourdon
parent f27940478d
commit 3627bd21f1
14 changed files with 0 additions and 2010 deletions

View File

@ -137,7 +137,6 @@
<string name="jit64_recompiler">JIT64 Recompiler</string>
<string name="jitil_recompiler">JITIL Recompiler</string>
<string name="jit_arm_recompiler">JIT ARM Recompiler</string>
<string name="jitil_arm_recompiler">JITIL ARM Recompiler</string>
<string name="cpu_settings">CPU</string>
<string name="cpu_core">CPUコア</string>
<string name="cpu_core_desc">%s</string>

View File

@ -19,12 +19,10 @@
<string-array name="emuCoreEntriesARM" translatable="false">
<item>@string/interpreter</item>
<item>@string/jit_arm_recompiler</item>
<item>@string/jitil_arm_recompiler</item>
</string-array>
<string-array name="emuCoreValuesARM" translatable="false">
<item>0</item>
<item>3</item>
<item>4</item>
</string-array>
<!-- CPU core selection - Other -->

View File

@ -138,7 +138,6 @@
<string name="jit64_recompiler">JIT64 Recompiler</string>
<string name="jitil_recompiler">JITIL Recompiler</string>
<string name="jit_arm_recompiler">JIT ARM Recompiler</string>
<string name="jitil_arm_recompiler">JITIL ARM Recompiler</string>
<string name="cpu_settings">CPU</string>
<string name="cpu_core">CPU Core</string>
<string name="cpu_core_desc">%s</string>

View File

@ -218,12 +218,6 @@ if(_M_ARM_32)
PowerPC/JitArm32/JitArm_LoadStorePaired.cpp
PowerPC/JitArm32/JitArm_SystemRegisters.cpp
PowerPC/JitArm32/JitArm_LoadStoreFloating.cpp
#JitArmIL
PowerPC/JitArmIL/JitIL.cpp
PowerPC/JitArmIL/JitILAsm.cpp
PowerPC/JitArmIL/JitIL_Tables.cpp
PowerPC/JitArmIL/JitIL_Branch.cpp
PowerPC/JitArmIL/IR_Arm.cpp
)
endif()

View File

@ -1,744 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <algorithm>
#include "Common/ArmEmitter.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PPCTables.h"
#include "Core/PowerPC/JitArmIL/JitIL.h"
#include "Core/PowerPC/JitArmIL/JitILAsm.h"
#include "Core/PowerPC/JitILCommon/IR.h"
using namespace IREmitter;
using namespace ArmGen;
static const unsigned int MAX_NUMBER_OF_REGS = 32;
struct RegInfo {
JitArmIL *Jit;
IRBuilder* Build;
InstLoc FirstI;
std::vector<unsigned> IInfo;
std::vector<InstLoc> lastUsed;
InstLoc regs[MAX_NUMBER_OF_REGS];
InstLoc fregs[MAX_NUMBER_OF_REGS];
unsigned numSpills;
unsigned numFSpills;
unsigned exitNumber;
RegInfo(JitArmIL* j, InstLoc f, unsigned insts) : Jit(j), FirstI(f), IInfo(insts), lastUsed(insts) {
for (unsigned i = 0; i < MAX_NUMBER_OF_REGS; i++) {
regs[i] = 0;
fregs[i] = 0;
}
numSpills = 0;
numFSpills = 0;
exitNumber = 0;
}
private:
RegInfo(RegInfo&); // DO NOT IMPLEMENT
};
static const ARMReg RegAllocOrder[] = {R0, R1, R2, R3, R4, R5, R6, R7, R8};
static const int RegAllocSize = sizeof(RegAllocOrder) / sizeof(ARMReg);
static unsigned SlotSet[1000];
static void regMarkUse(RegInfo& R, InstLoc I, InstLoc Op, unsigned OpNum) {
unsigned& info = R.IInfo[Op - R.FirstI];
if (info == 0) R.IInfo[I - R.FirstI] |= 1 << (OpNum + 1);
if (info < 2) info++;
R.lastUsed[Op - R.FirstI] = std::max(R.lastUsed[Op - R.FirstI], I);
}
static void regClearInst(RegInfo& RI, InstLoc I) {
for (int i = 0; i < RegAllocSize; i++)
if (RI.regs[RegAllocOrder[i]] == I)
RI.regs[RegAllocOrder[i]] = 0;
}
static void regNormalRegClear(RegInfo& RI, InstLoc I) {
if (RI.IInfo[I - RI.FirstI] & 4)
regClearInst(RI, getOp1(I));
if (RI.IInfo[I - RI.FirstI] & 8)
regClearInst(RI, getOp2(I));
}
static unsigned regReadUse(RegInfo& R, InstLoc I) {
return R.IInfo[I - R.FirstI] & 3;
}
static u32 regLocForSlot(RegInfo& RI, unsigned slot) {
return (u32)&SlotSet[slot - 1];
}
static unsigned regCreateSpill(RegInfo& RI, InstLoc I) {
unsigned newSpill = ++RI.numSpills;
RI.IInfo[I - RI.FirstI] |= newSpill << 16;
return newSpill;
}
static unsigned regGetSpill(RegInfo& RI, InstLoc I) {
return RI.IInfo[I - RI.FirstI] >> 16;
}
static void regSpill(RegInfo& RI, ARMReg reg) {
if (!RI.regs[reg]) return;
unsigned slot = regGetSpill(RI, RI.regs[reg]);
if (!slot) {
slot = regCreateSpill(RI, RI.regs[reg]);
RI.Jit->MOVI2R(R14, regLocForSlot(RI, slot));
RI.Jit->STR(reg, R14, 0);
}
RI.regs[reg] = 0;
}
static ARMReg regFindFreeReg(RegInfo& RI) {
for (int i = 0; i < RegAllocSize; i++)
if (RI.regs[RegAllocOrder[i]] == 0)
return RegAllocOrder[i];
int bestIndex = -1;
InstLoc bestEnd = 0;
for (int i = 0; i < RegAllocSize; ++i) {
const InstLoc start = RI.regs[RegAllocOrder[i]];
const InstLoc end = RI.lastUsed[start - RI.FirstI];
if (bestEnd < end) {
bestEnd = end;
bestIndex = i;
}
}
ARMReg reg = RegAllocOrder[bestIndex];
regSpill(RI, reg);
return reg;
}
static ARMReg regLocForInst(RegInfo& RI, InstLoc I) {
for (int i = 0; i < RegAllocSize; i++)
if (RI.regs[RegAllocOrder[i]] == I)
return RegAllocOrder[i];
if (regGetSpill(RI, I) == 0)
PanicAlert("Retrieving unknown spill slot?!");
RI.Jit->MOVI2R(R14, regLocForSlot(RI, regGetSpill(RI, I)));
ARMReg reg = regFindFreeReg(RI);
RI.Jit->LDR(reg, R14, 0);
return reg;
}
static ARMReg regBinLHSReg(RegInfo& RI, InstLoc I) {
ARMReg reg = regFindFreeReg(RI);
RI.Jit->MOV(reg, regLocForInst(RI, getOp1(I)));
return reg;
}
// If the lifetime of the register used by an operand ends at I,
// return the register. Otherwise return a free register.
static ARMReg regBinReg(RegInfo& RI, InstLoc I) {
// FIXME: When regLocForInst() is extracted as a local variable,
// "Retrieving unknown spill slot?!" is shown.
if (RI.IInfo[I - RI.FirstI] & 4)
return regLocForInst(RI, getOp1(I));
else if (RI.IInfo[I - RI.FirstI] & 8)
return regLocForInst(RI, getOp2(I));
return regFindFreeReg(RI);
}
static void regSpillCallerSaved(RegInfo& RI) {
regSpill(RI, R0);
regSpill(RI, R1);
regSpill(RI, R2);
regSpill(RI, R3);
}
static ARMReg regEnsureInReg(RegInfo& RI, InstLoc I) {
return regLocForInst(RI, I);
}
static void regWriteExit(RegInfo& RI, InstLoc dest) {
if (isImm(*dest)) {
RI.exitNumber++;
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
} else {
RI.Jit->WriteExitDestInReg(regLocForInst(RI, dest));
}
}
static void regStoreInstToPPCState(RegInfo& RI, unsigned width, InstLoc I, s32 offset) {
void (JitArmIL::*op)(ARMReg, ARMReg, Operand2, bool);
switch (width)
{
case 32:
op = &JitArmIL::STR;
break;
case 8:
op = &JitArmIL::STRB;
break;
default:
PanicAlert("Not implemented!");
return;
break;
}
if (isImm(*I)) {
RI.Jit->MOVI2R(R12, RI.Build->GetImmValue(I));
(RI.Jit->*op)(R12, R9, offset, true);
return;
}
ARMReg reg = regEnsureInReg(RI, I);
(RI.Jit->*op)(reg, R9, offset, true);
}
//
// Mark and calculation routines for profiled load/store addresses
// Could be extended to unprofiled addresses.
static void regMarkMemAddress(RegInfo& RI, InstLoc I, InstLoc AI, unsigned OpNum) {
if (isImm(*AI)) {
unsigned addr = RI.Build->GetImmValue(AI);
if (Memory::IsRAMAddress(addr))
return;
}
if (getOpcode(*AI) == Add && isImm(*getOp2(AI))) {
regMarkUse(RI, I, getOp1(AI), OpNum);
return;
}
regMarkUse(RI, I, AI, OpNum);
}
// Binary ops
void JitArmIL::BIN_XOR(ARMReg reg, Operand2 op2)
{
EOR(reg, reg, op2);
}
void JitArmIL::BIN_OR(ARMReg reg, Operand2 op2)
{
ORR(reg, reg, op2);
}
void JitArmIL::BIN_AND(ARMReg reg, Operand2 op2)
{
AND(reg, reg, op2);
}
void JitArmIL::BIN_ADD(ARMReg reg, Operand2 op2)
{
ADD(reg, reg, op2);
}
static void regEmitShiftInst(RegInfo& RI, InstLoc I, void (JitArmIL::*op)(ARMReg, ARMReg, Operand2))
{
ARMReg reg = regBinLHSReg(RI, I);
if (isImm(*getOp2(I))) {
unsigned RHS = RI.Build->GetImmValue(getOp2(I));
(RI.Jit->*op)(reg, reg, RHS);
RI.regs[reg] = I;
return;
}
(RI.Jit->*op)(reg, reg, regLocForInst(RI, getOp2(I)));
RI.regs[reg] = I;
regNormalRegClear(RI, I);
}
static void regEmitBinInst(RegInfo& RI, InstLoc I,
void (JitArmIL::*op)(ARMReg, Operand2),
bool commutable = false) {
ARMReg reg;
bool commuted = false;
if (RI.IInfo[I - RI.FirstI] & 4) {
reg = regEnsureInReg(RI, getOp1(I));
} else if (commutable && (RI.IInfo[I - RI.FirstI] & 8)) {
reg = regEnsureInReg(RI, getOp2(I));
commuted = true;
} else {
reg = regFindFreeReg(RI);
RI.Jit->MOV(reg, regLocForInst(RI, getOp1(I)));
}
if (isImm(*getOp2(I))) {
unsigned RHS = RI.Build->GetImmValue(getOp2(I));
Operand2 RHSop;
if (TryMakeOperand2(RHS, RHSop))
(RI.Jit->*op)(reg, RHSop);
else
{
RI.Jit->MOVI2R(R12, RHS);
(RI.Jit->*op)(reg, R12);
}
} else if (commuted) {
(RI.Jit->*op)(reg, regLocForInst(RI, getOp1(I)));
} else {
(RI.Jit->*op)(reg, regLocForInst(RI, getOp2(I)));
}
RI.regs[reg] = I;
regNormalRegClear(RI, I);
}
static void regEmitCmp(RegInfo& RI, InstLoc I) {
if (isImm(*getOp2(I))) {
unsigned RHS = RI.Build->GetImmValue(getOp2(I));
Operand2 op;
if (TryMakeOperand2(RHS, op))
RI.Jit->CMP(regLocForInst(RI, getOp1(I)), op);
else
{
RI.Jit->MOVI2R(R12, RHS);
RI.Jit->CMP(regLocForInst(RI, getOp1(I)), R12);
}
} else {
ARMReg reg = regEnsureInReg(RI, getOp1(I));
RI.Jit->CMP(reg, regLocForInst(RI, getOp2(I)));
}
}
static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) {
RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
RI.Build = ibuild;
// Pass to compute liveness
ibuild->StartBackPass();
for (unsigned int index = (unsigned int)RI.IInfo.size() - 1; index != -1U; --index) {
InstLoc I = ibuild->ReadBackward();
unsigned int op = getOpcode(*I);
bool thisUsed = regReadUse(RI, I) ? true : false;
switch (op) {
default:
PanicAlert("Unexpected inst!");
case Nop:
case CInt16:
case CInt32:
case LoadGReg:
case LoadLink:
case LoadCR:
case LoadCarry:
case LoadCTR:
case LoadMSR:
case LoadFReg:
case LoadFRegDENToZero:
case LoadGQR:
case BlockEnd:
case BlockStart:
case FallBackToInterpreter:
case SystemCall:
case RFIExit:
case InterpreterBranch:
case ShortIdleLoop:
case FPExceptionCheck:
case DSIExceptionCheck:
case ISIException:
case ExtExceptionCheck:
case BreakPointCheck:
case Int3:
case Tramp:
// No liveness effects
break;
case SExt8:
case SExt16:
case BSwap32:
case BSwap16:
case Cntlzw:
case Not:
case DupSingleToMReg:
case DoubleToSingle:
case ExpandPackedToMReg:
case CompactMRegToPacked:
case FPNeg:
case FPDup0:
case FPDup1:
case FSNeg:
case FDNeg:
if (thisUsed)
regMarkUse(RI, I, getOp1(I), 1);
break;
case Load8:
case Load16:
case Load32:
regMarkMemAddress(RI, I, getOp1(I), 1);
break;
case LoadDouble:
case LoadSingle:
case LoadPaired:
if (thisUsed)
regMarkUse(RI, I, getOp1(I), 1);
break;
case StoreCR:
case StoreCarry:
case StoreFPRF:
regMarkUse(RI, I, getOp1(I), 1);
break;
case StoreGReg:
case StoreLink:
case StoreCTR:
case StoreMSR:
case StoreGQR:
case StoreSRR:
case StoreFReg:
if (!isImm(*getOp1(I)))
regMarkUse(RI, I, getOp1(I), 1);
break;
case Add:
case Sub:
case And:
case Or:
case Xor:
case Mul:
case MulHighUnsigned:
case Rol:
case Shl:
case Shrl:
case Sarl:
case ICmpCRUnsigned:
case ICmpCRSigned:
case ICmpEq:
case ICmpNe:
case ICmpUgt:
case ICmpUlt:
case ICmpUge:
case ICmpUle:
case ICmpSgt:
case ICmpSlt:
case ICmpSge:
case ICmpSle:
case FSMul:
case FSAdd:
case FSSub:
case FDMul:
case FDAdd:
case FDSub:
case FPAdd:
case FPMul:
case FPSub:
case FPMerge00:
case FPMerge01:
case FPMerge10:
case FPMerge11:
case FDCmpCR:
case InsertDoubleInMReg:
if (thisUsed) {
regMarkUse(RI, I, getOp1(I), 1);
if (!isImm(*getOp2(I)))
regMarkUse(RI, I, getOp2(I), 2);
}
break;
case Store8:
case Store16:
case Store32:
if (!isImm(*getOp1(I)))
regMarkUse(RI, I, getOp1(I), 1);
regMarkMemAddress(RI, I, getOp2(I), 2);
break;
case StoreSingle:
case StoreDouble:
case StorePaired:
regMarkUse(RI, I, getOp1(I), 1);
regMarkUse(RI, I, getOp2(I), 2);
break;
case BranchUncond:
if (!isImm(*getOp1(I)))
regMarkUse(RI, I, getOp1(I), 1);
break;
case IdleBranch:
regMarkUse(RI, I, getOp1(getOp1(I)), 1);
break;
case BranchCond: {
if (isICmp(*getOp1(I)) &&
isImm(*getOp2(getOp1(I)))) {
regMarkUse(RI, I, getOp1(getOp1(I)), 1);
} else {
regMarkUse(RI, I, getOp1(I), 1);
}
if (!isImm(*getOp2(I)))
regMarkUse(RI, I, getOp2(I), 2);
break;
}
}
}
ibuild->StartForwardPass();
for (unsigned i = 0; i != RI.IInfo.size(); i++) {
InstLoc I = ibuild->ReadForward();
bool thisUsed = regReadUse(RI, I) ? true : false;
if (thisUsed) {
// Needed for IR Writer
ibuild->SetMarkUsed(I);
}
switch (getOpcode(*I)) {
case CInt32:
case CInt16: {
if (!thisUsed) break;
ARMReg reg = regFindFreeReg(RI);
Jit->MOVI2R(reg, ibuild->GetImmValue(I));
RI.regs[reg] = I;
break;
}
case BranchUncond: {
regWriteExit(RI, getOp1(I));
regNormalRegClear(RI, I);
break;
}
case BranchCond: {
if (isICmp(*getOp1(I)) &&
isImm(*getOp2(getOp1(I)))) {
unsigned imm = RI.Build->GetImmValue(getOp2(getOp1(I)));
if (imm > 255)
{
Jit->MOVI2R(R14, imm);
Jit->CMP(regLocForInst(RI, getOp1(getOp1(I))), R14);
}
else
Jit->CMP(regLocForInst(RI, getOp1(getOp1(I))), imm);
CCFlags flag;
switch (getOpcode(*getOp1(I))) {
case ICmpEq: flag = CC_NEQ; break;
case ICmpNe: flag = CC_EQ; break;
case ICmpUgt: flag = CC_LS; break;
case ICmpUlt: flag = CC_HI; break;
case ICmpUge: flag = CC_HS; break;
case ICmpUle: flag = CC_LO; break;
case ICmpSgt: flag = CC_LT; break;
case ICmpSlt: flag = CC_GT; break;
case ICmpSge: flag = CC_LE; break;
case ICmpSle: flag = CC_GE; break;
default: PanicAlert("cmpXX"); flag = CC_AL; break;
}
FixupBranch cont = Jit->B_CC(flag);
regWriteExit(RI, getOp2(I));
Jit->SetJumpTarget(cont);
if (RI.IInfo[I - RI.FirstI] & 4)
regClearInst(RI, getOp1(getOp1(I)));
} else {
Jit->CMP(regLocForInst(RI, getOp1(I)), 0);
FixupBranch cont = Jit->B_CC(CC_EQ);
regWriteExit(RI, getOp2(I));
Jit->SetJumpTarget(cont);
if (RI.IInfo[I - RI.FirstI] & 4)
regClearInst(RI, getOp1(I));
}
if (RI.IInfo[I - RI.FirstI] & 8)
regClearInst(RI, getOp2(I));
break;
}
case StoreGReg: {
unsigned ppcreg = *I >> 16;
regStoreInstToPPCState(RI, 32, getOp1(I), PPCSTATE_OFF(gpr[ppcreg]));
regNormalRegClear(RI, I);
break;
}
case StoreCR: {
unsigned ppcreg = *I >> 16;
regStoreInstToPPCState(RI, 8, getOp1(I), PPCSTATE_OFF(cr_fast[ppcreg]));
regNormalRegClear(RI, I);
break;
}
case StoreLink: {
regStoreInstToPPCState(RI, 32, getOp1(I), PPCSTATE_OFF(spr[SPR_LR]));
regNormalRegClear(RI, I);
break;
}
case StoreCTR: {
regStoreInstToPPCState(RI, 32, getOp1(I), PPCSTATE_OFF(spr[SPR_CTR]));
regNormalRegClear(RI, I);
break;
}
case StoreMSR: {
regStoreInstToPPCState(RI, 32, getOp1(I), PPCSTATE_OFF(msr));
regNormalRegClear(RI, I);
break;
}
case LoadGReg: {
if (!thisUsed) break;
ARMReg reg = regFindFreeReg(RI);
unsigned ppcreg = *I >> 8;
Jit->LDR(reg, R9, PPCSTATE_OFF(gpr[ppcreg]));
RI.regs[reg] = I;
break;
}
case LoadCR: {
if (!thisUsed) break;
ARMReg reg = regFindFreeReg(RI);
unsigned ppcreg = *I >> 8;
Jit->LDRB(reg, R9, PPCSTATE_OFF(cr_fast[ppcreg]));
RI.regs[reg] = I;
break;
}
case LoadCTR: {
if (!thisUsed) break;
ARMReg reg = regFindFreeReg(RI);
Jit->LDR(reg, R9, PPCSTATE_OFF(spr[SPR_CTR]));
RI.regs[reg] = I;
break;
}
case LoadLink: {
if (!thisUsed) break;
ARMReg reg = regFindFreeReg(RI);
Jit->LDR(reg, R9, PPCSTATE_OFF(spr[SPR_LR]));
RI.regs[reg] = I;
break;
}
case FallBackToInterpreter: {
unsigned InstCode = ibuild->GetImmValue(getOp1(I));
unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
// There really shouldn't be anything live across an
// interpreter call at the moment, but optimizing interpreter
// calls isn't completely out of the question...
regSpillCallerSaved(RI);
Jit->MOVI2R(R14, InstLoc);
Jit->STR(R14, R9, PPCSTATE_OFF(pc));
Jit->MOVI2R(R14, InstLoc + 4);
Jit->STR(R14, R9, PPCSTATE_OFF(npc));
Jit->MOVI2R(R0, InstCode);
Jit->MOVI2R(R14, (u32)GetInterpreterOp(InstCode));
Jit->BL(R14);
break;
}
case SystemCall: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->MOVI2R(R14, InstLoc + 4);
Jit->STR(R14, R9, PPCSTATE_OFF(pc));
Jit->LDR(R14, R9, PPCSTATE_OFF(Exceptions));
Jit->ORR(R14, R14, EXCEPTION_SYSCALL);
Jit->STR(R14, R9, PPCSTATE_OFF(Exceptions));
Jit->WriteExceptionExit();
break;
}
case ShortIdleLoop: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->MOVI2R(R14, (u32)&CoreTiming::Idle);
Jit->BL(R14);
Jit->MOVI2R(R14, InstLoc);
Jit->STR(R14, R9, PPCSTATE_OFF(pc));
Jit->WriteExceptionExit();
break;
}
case InterpreterBranch: {
Jit->LDR(R14, R9, PPCSTATE_OFF(npc));
Jit->WriteExitDestInReg(R14);
break;
}
case RFIExit: {
const u32 mask = 0x87C0FFFF;
const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13]
// MSR = ((MSR & ~mask) | (SRR1 & mask)) & clearMSR13;
// R0 = MSR location
// R1 = MSR contents
// R2 = Mask
// R3 = Mask
ARMReg rA = R14;
ARMReg rB = R12;
ARMReg rC = R11;
ARMReg rD = R10;
Jit->MOVI2R(rB, (~mask) & clearMSR13);
Jit->MOVI2R(rC, mask & clearMSR13);
Jit->LDR(rD, R9, PPCSTATE_OFF(msr));
Jit->AND(rD, rD, rB); // rD = Masked MSR
Jit->LDR(rB, R9, PPCSTATE_OFF(spr[SPR_SRR1])); // rB contains SRR1 here
Jit->AND(rB, rB, rC); // rB contains masked SRR1 here
Jit->ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1
Jit->STR(rB, R9, PPCSTATE_OFF(msr)); // STR rB in to rA
Jit->LDR(rA, R9, PPCSTATE_OFF(spr[SPR_SRR0]));
Jit->WriteRfiExitDestInR(rA); // rA gets unlocked here
break;
}
case Shl: {
if (!thisUsed) break;
regEmitShiftInst(RI, I, &JitArmIL::LSL);
break;
}
case Shrl: {
if (!thisUsed) break;
regEmitShiftInst(RI, I, &JitArmIL::LSR);
break;
}
case Sarl: {
if (!thisUsed) break;
regEmitShiftInst(RI, I, &JitArmIL::ASR);
break;
}
case And: {
if (!thisUsed) break;
regEmitBinInst(RI, I, &JitArmIL::BIN_AND, true);
break;
}
case Not: {
if (!thisUsed) break;
ARMReg reg = regBinLHSReg(RI, I);
Jit->MVN(reg, reg);
RI.regs[reg] = I;
regNormalRegClear(RI, I);
break;
}
case Or: {
if (!thisUsed) break;
regEmitBinInst(RI, I, &JitArmIL::BIN_OR, true);
break;
}
case Xor: {
if (!thisUsed) break;
regEmitBinInst(RI, I, &JitArmIL::BIN_XOR, true);
break;
}
case Add: {
if (!thisUsed) break;
regEmitBinInst(RI, I, &JitArmIL::BIN_ADD, true);
break;
}
case ICmpCRUnsigned: {
if (!thisUsed) break;
regEmitCmp(RI, I);
ARMReg reg = regBinReg(RI, I);
Jit->MOV(reg, 0x2); // Result == 0
Jit->SetCC(CC_LO); Jit->MOV(reg, 0x8); // Result < 0
Jit->SetCC(CC_HI); Jit->MOV(reg, 0x4); // Result > 0
Jit->SetCC();
RI.regs[reg] = I;
regNormalRegClear(RI, I);
break;
}
case ICmpCRSigned: {
if (!thisUsed) break;
regEmitCmp(RI, I);
ARMReg reg = regBinReg(RI, I);
Jit->MOV(reg, 0x2); // Result == 0
Jit->SetCC(CC_LT); Jit->MOV(reg, 0x8); // Result < 0
Jit->SetCC(CC_GT); Jit->MOV(reg, 0x4); // Result > 0
Jit->SetCC();
RI.regs[reg] = I;
regNormalRegClear(RI, I);
break;
}
case Int3:
Jit->BKPT(0x321);
break;
case Tramp: break;
case Nop: break;
default:
PanicAlert("Unknown JIT instruction; aborting!");
ibuild->WriteToFile(0);
exit(1);
}
}
for (unsigned i = 0; i < MAX_NUMBER_OF_REGS; i++) {
if (RI.regs[i]) {
// Start a game in Burnout 2 to get this. Or animal crossing.
PanicAlert("Incomplete cleanup! (regs)");
exit(1);
}
if (RI.fregs[i]) {
PanicAlert("Incomplete cleanup! (fregs)");
exit(1);
}
}
Jit->WriteExit(exitAddress);
Jit->BKPT(0x111);
}
void JitArmIL::WriteCode(u32 exitAddress) {
DoWriteCode(&ibuild, this, exitAddress);
}

View File

@ -1 +0,0 @@

View File

@ -1,345 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <map>
#include "Common/ArmEmitter.h"
#include "Common/Common.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/PatchEngine.h"
#include "Core/HLE/HLE.h"
#include "Core/HW/GPFifo.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PPCTables.h"
#include "Core/PowerPC/Profiler.h"
#include "Core/PowerPC/JitArmIL/JitIL.h"
#include "Core/PowerPC/JitArmIL/JitIL_Tables.h"
using namespace ArmGen;
using namespace PowerPC;
static int CODE_SIZE = 1024*1024*32;
void JitArmIL::Init()
{
AllocCodeSpace(CODE_SIZE);
blocks.Init();
asm_routines.Init();
code_block.m_stats = &js.st;
code_block.m_gpa = &js.gpa;
code_block.m_fpa = &js.fpa;
}
void JitArmIL::ClearCache()
{
ClearCodeSpace();
blocks.Clear();
}
void JitArmIL::Shutdown()
{
FreeCodeSpace();
blocks.Shutdown();
asm_routines.Shutdown();
}
void JitArmIL::unknown_instruction(UGeckoInstruction inst)
{
// CCPU::Break();
PanicAlert("unknown_instruction %08x - Fix me ;)", inst.hex);
}
void JitArmIL::FallBackToInterpreter(UGeckoInstruction _inst)
{
ibuild.EmitFallBackToInterpreter(
ibuild.EmitIntConst(_inst.hex),
ibuild.EmitIntConst(js.compilerPC));
}
void JitArmIL::HLEFunction(UGeckoInstruction _inst)
{
// XXX
}
void JitArmIL::DoNothing(UGeckoInstruction _inst)
{
// Yup, just don't do anything.
}
void JitArmIL::Break(UGeckoInstruction _inst)
{
ibuild.EmitINT3();
}
void JitArmIL::DoDownCount()
{
ARMReg rA = R12;
LDR(rA, R9, PPCSTATE_OFF(downcount));
if (js.downcountAmount < 255) // We can enlarge this if we used rotations
{
SUBS(rA, rA, js.downcountAmount);
}
else
{
ARMReg rB = R11;
MOVI2R(rB, js.downcountAmount);
SUBS(rA, rA, rB);
}
STR(rA, R9, PPCSTATE_OFF(downcount));
}
void JitArmIL::WriteExitDestInReg(ARMReg Reg)
{
STR(Reg, R9, PPCSTATE_OFF(pc));
DoDownCount();
MOVI2R(Reg, (u32)asm_routines.dispatcher);
B(Reg);
}
void JitArmIL::WriteRfiExitDestInR(ARMReg Reg)
{
STR(Reg, R9, PPCSTATE_OFF(pc));
DoDownCount();
LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R0, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(pc));
MOVI2R(R0, (u32)asm_routines.dispatcher);
B(R0);
}
void JitArmIL::WriteExceptionExit()
{
DoDownCount();
LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R0, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(pc));
MOVI2R(R0, (u32)asm_routines.dispatcher);
B(R0);
}
void JitArmIL::WriteExit(u32 destination)
{
DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
// Link opportunity!
int block;
if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0)
{
// It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry);
linkData.linkStatus = true;
}
else
{
MOVI2R(R14, destination);
STR(R14, R9, PPCSTATE_OFF(pc));
MOVI2R(R14, (u32)asm_routines.dispatcher);
B(R14);
}
b->linkData.push_back(linkData);
}
void JitArmIL::PrintDebug(UGeckoInstruction inst, u32 level)
{
if (level > 0)
printf("Start: %08x OP '%s' Info\n", (u32)GetCodePtr(), PPCTables::GetInstructionName(inst));
if (level > 1)
{
GekkoOPInfo* Info = GetOpInfo(inst.hex);
printf("\tOuts\n");
if (Info->flags & FL_OUT_A)
printf("\t-OUT_A: %x\n", inst.RA);
if (Info->flags & FL_OUT_D)
printf("\t-OUT_D: %x\n", inst.RD);
printf("\tIns\n");
// A, AO, B, C, S
if (Info->flags & FL_IN_A)
printf("\t-IN_A: %x\n", inst.RA);
if (Info->flags & FL_IN_A0)
printf("\t-IN_A0: %x\n", inst.RA);
if (Info->flags & FL_IN_B)
printf("\t-IN_B: %x\n", inst.RB);
if (Info->flags & FL_IN_C)
printf("\t-IN_C: %x\n", inst.RC);
if (Info->flags & FL_IN_S)
printf("\t-IN_S: %x\n", inst.RS);
}
}
void STACKALIGN JitArmIL::Run()
{
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
pExecAddr();
}
void JitArmIL::SingleStep()
{
CompiledCode pExecAddr = (CompiledCode)asm_routines.enterCode;
pExecAddr();
}
void STACKALIGN JitArmIL::Jit(u32 em_address)
{
if (GetSpaceLeft() < 0x10000 || blocks.IsFull() || Core::g_CoreStartupParameter.bJITNoBlockCache)
{
ClearCache();
}
int block_num = blocks.AllocateBlock(PowerPC::ppcState.pc);
JitBlock *b = blocks.GetBlock(block_num);
const u8* BlockPtr = DoJit(PowerPC::ppcState.pc, &code_buffer, b);
blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr);
}
const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlock *b)
{
int blockSize = code_buf->GetSize();
if (Core::g_CoreStartupParameter.bEnableDebugging)
{
// Comment out the following to disable breakpoints (speed-up)
blockSize = 1;
}
if (em_address == 0)
{
Core::SetState(Core::CORE_PAUSE);
PanicAlert("ERROR: Compiling at 0. LR=%08x CTR=%08x", LR, CTR);
}
js.isLastInstruction = false;
js.blockStart = em_address;
js.fifoBytesThisBlock = 0;
js.curBlock = b;
u32 nextPC = em_address;
// Analyze the block, collect all instructions it is made of (including inlining,
// if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
nextPC = analyzer.Analyze(em_address, &code_block, code_buf, blockSize);
PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
const u8 *start = GetCodePtr();
b->checkedEntry = start;
b->runCount = 0;
// Downcount flag check, Only valid for linked blocks
{
// XXX
}
const u8 *normalEntry = GetCodePtr();
b->normalEntry = normalEntry;
if (js.fpa.any)
{
// XXX
// This block uses FPU - needs to add FP exception bailout
}
js.rewriteStart = (u8*)GetCodePtr();
u64 codeHash = -1;
{
// For profiling and IR Writer
for (u32 i = 0; i < code_block.m_num_instructions; i++)
{
const u64 inst = ops[i].inst.hex;
// Ported from boost::hash
codeHash ^= inst + (codeHash << 6) + (codeHash >> 2);
}
}
// Conditionally add profiling code.
if (Profiler::g_ProfileBlocks) {
// XXX
}
// Start up IR builder (structure that collects the
// instruction processed by the JIT routines)
ibuild.Reset();
js.downcountAmount = 0;
if (!Core::g_CoreStartupParameter.bEnableDebugging)
js.downcountAmount += PatchEngine::GetSpeedhackCycles(em_address);
js.skipnext = false;
js.compilerPC = nextPC;
// Translate instructions
for (u32 i = 0; i < code_block.m_num_instructions; i++)
{
js.compilerPC = ops[i].address;
js.op = &ops[i];
js.instructionNumber = i;
const GekkoOPInfo *opinfo = ops[i].opinfo;
js.downcountAmount += opinfo->numCycles;
if (i == (code_block.m_num_instructions - 1))
{
// WARNING - cmp->branch merging will screw this up.
js.isLastInstruction = true;
js.next_inst = 0;
if (Profiler::g_ProfileBlocks) {
// CAUTION!!! push on stack regs you use, do your stuff, then pop
PROFILER_VPUSH;
// get end tic
PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStop);
// tic counter += (end tic - start tic)
PROFILER_ADD_DIFF_LARGE_INTEGER(&b->ticCounter, &b->ticStop, &b->ticStart);
PROFILER_VPOP;
}
}
else
{
// help peephole optimizations
js.next_inst = ops[i + 1].inst;
js.next_compilerPC = ops[i + 1].address;
}
if (!ops[i].skip)
{
PrintDebug(ops[i].inst, 0);
if (js.memcheck && (opinfo->flags & FL_USE_FPU))
{
// Don't do this yet
BKPT(0x7777);
}
JitArmILTables::CompileInstruction(ops[i]);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE))
{
// Don't do this yet
BKPT(0x666);
}
}
}
if (code_block.m_memory_exception)
BKPT(0x500);
if (code_block.m_broken)
{
printf("Broken Block going to 0x%08x\n", nextPC);
WriteExit(nextPC);
}
// Perform actual code generation
WriteCode(nextPC);
b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = code_block.m_num_instructions;;
FlushIcache();
return start;
}

View File

@ -1,91 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "Common/ArmEmitter.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/JitArm32/JitArmCache.h"
#include "Core/PowerPC/JitArmIL/JitILAsm.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/JitILCommon/IR.h"
#include "Core/PowerPC/JitILCommon/JitILBase.h"
#define PPCSTATE_OFF(elem) ((s32)STRUCT_OFF(PowerPC::ppcState, elem) - (s32)STRUCT_OFF(PowerPC::ppcState, spr[0]))
class JitArmIL : public JitILBase, public ArmGen::ARMCodeBlock
{
private:
JitArmBlockCache blocks;
JitArmILAsmRoutineManager asm_routines;
void PrintDebug(UGeckoInstruction inst, u32 level);
void DoDownCount();
public:
// Initialization, etc
JitArmIL() {}
~JitArmIL() {}
void Init();
void Shutdown();
// Jit!
void Jit(u32 em_address);
const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buffer, JitBlock *b);
JitBaseBlockCache *GetBlockCache() { return &blocks; }
const u8 *BackPatch(u8 *codePtr, u32 em_address, void *ctx) { return nullptr; }
bool IsInCodeSpace(u8 *ptr) { return IsInSpace(ptr); }
void ClearCache();
const u8 *GetDispatcher() {
return asm_routines.dispatcher; // asm_routines.dispatcher
}
const CommonAsmRoutinesBase *GetAsmRoutines() {
return &asm_routines;
}
const char *GetName() {
return "JITARMIL";
}
// Run!
void Run();
void SingleStep();
//
void WriteCode(u32 exitAddress);
void WriteExit(u32 destination);
void WriteExitDestInReg(ArmGen::ARMReg Reg);
void WriteRfiExitDestInR(ArmGen::ARMReg Reg);
void WriteExceptionExit();
// OPCODES
void unknown_instruction(UGeckoInstruction inst);
void FallBackToInterpreter(UGeckoInstruction inst);
void DoNothing(UGeckoInstruction inst);
void HLEFunction(UGeckoInstruction inst);
void Break(UGeckoInstruction inst);
void DynaRunTable4(UGeckoInstruction inst);
void DynaRunTable19(UGeckoInstruction inst);
void DynaRunTable31(UGeckoInstruction inst);
void DynaRunTable59(UGeckoInstruction inst);
void DynaRunTable63(UGeckoInstruction inst);
// Binary ops
void BIN_AND(ArmGen::ARMReg reg, ArmGen::Operand2 op2);
void BIN_XOR(ArmGen::ARMReg reg, ArmGen::Operand2 op2);
void BIN_OR(ArmGen::ARMReg reg, ArmGen::Operand2 op2);
void BIN_ADD(ArmGen::ARMReg reg, ArmGen::Operand2 op2);
// Branches
void bx(UGeckoInstruction inst);
void bcx(UGeckoInstruction inst);
void bclrx(UGeckoInstruction inst);
void bcctrx(UGeckoInstruction inst);
};

View File

@ -1,106 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "Common/ArmEmitter.h"
#include "Common/MemoryUtil.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/HW/GPFifo.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/JitArmIL/JitIL.h"
#include "Core/PowerPC/JitArmIL/JitILAsm.h"
#include "Core/PowerPC/JitCommon/JitCache.h"
using namespace ArmGen;
void JitArmILAsmRoutineManager::Generate()
{
enterCode = GetCodePtr();
PUSH(9, R4, R5, R6, R7, R8, R9, R10, R11, _LR);
// Take care to 8-byte align stack for function calls.
// We are misaligned here because of an odd number of args for PUSH.
// It's not like x86 where you need to account for an extra 4 bytes
// consumed by CALL.
SUB(_SP, _SP, 4);
MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);
FixupBranch skipToRealDispatcher = B();
dispatcher = GetCodePtr();
printf("ILDispatcher is %p\n", dispatcher);
// Downcount Check
// The result of slice decrementation should be in flags if somebody jumped here
// IMPORTANT - We jump on negative, not carry!!!
FixupBranch bail = B_CC(CC_MI);
SetJumpTarget(skipToRealDispatcher);
dispatcherNoCheck = GetCodePtr();
// This block of code gets the address of the compiled block of code
// It runs though to the compiling portion if it isn't found
LDR(R12, R9, PPCSTATE_OFF(pc));// Load the current PC into R12
Operand2 iCacheMask = Operand2(0xE, 2); // JIT_ICACHE_MASK
BIC(R12, R12, iCacheMask); // R12 contains PC & JIT_ICACHE_MASK here.
MOVI2R(R14, (u32)jit->GetBlockCache()->iCache);
LDR(R12, R14, R12); // R12 contains iCache[PC & JIT_ICACHE_MASK] here
// R12 Confirmed this is the correct iCache Location loaded.
TST(R12, 0x80); // Test to see if it is a JIT block.
SetCC(CC_EQ);
// Success, it is our Jitblock.
MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers());
// LDR R14 right here to get CodePointers()[0] pointer.
LSL(R12, R12, 2); // Multiply by four because address locations are u32 in size
LDR(R14, R14, R12); // Load the block address in to R14
B(R14);
// No need to jump anywhere after here, the block will go back to dispatcher start
SetCC();
// If we get to this point, that means that we don't have the block cached to execute
// So call ArmJit to compile the block and then execute it.
MOVI2R(R14, (u32)&Jit);
BL(R14);
B(dispatcherNoCheck);
SetJumpTarget(bail);
doTiming = GetCodePtr();
// XXX: In JIT64, Advance() gets called /after/ the exception checking
// once it jumps back to the start of outerLoop
QuickCallFunction(R14, (void*)&CoreTiming::Advance);
// Does exception checking
LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(pc));
// Check the state pointer to see if we are exiting
// Gets checked on every exception check
MOVI2R(R0, (u32)PowerPC::GetStatePtr());
MVN(R1, 0);
LDR(R0, R0);
TST(R0, R1);
FixupBranch Exit = B_CC(CC_NEQ);
B(dispatcher);
SetJumpTarget(Exit);
ADD(_SP, _SP, 4);
POP(9, R4, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns
GenerateCommon();
FlushIcache();
}

View File

@ -1,27 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "Common/ArmEmitter.h"
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
class JitArmILAsmRoutineManager : public CommonAsmRoutinesBase, public ArmGen::ARMCodeBlock
{
private:
void Generate();
void GenerateCommon() {}
public:
void Init() {
AllocCodeSpace(8192);
Generate();
WriteProtect();
}
void Shutdown() {
FreeCodeSpace();
}
};

View File

@ -1,168 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "Common/Common.h"
#include "Core/ConfigManager.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/PPCTables.h"
#include "Core/PowerPC/JitArmIL/JitIL.h"
// FIXME
#define NORMALBRANCH_START FallBackToInterpreter(inst); ibuild.EmitInterpreterBranch(); return;
//#define NORMALBRANCH_START
void JitArmIL::bx(UGeckoInstruction inst)
{
//NORMALBRANCH_START
INSTRUCTION_START;
// We must always process the following sentence
// even if the blocks are merged by PPCAnalyst::Flatten().
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
// If this is not the last instruction of a block,
// we will skip the rest process.
// Because PPCAnalyst::Flatten() merged the blocks.
if (!js.isLastInstruction) {
return;
}
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(CRCmp, CRTest);
}
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 JitArmIL::bclrx(UGeckoInstruction inst)
{
NORMALBRANCH_START
if (!js.isLastInstruction &&
(inst.BO & (1 << 4)) && (inst.BO & (1 << 2))) {
if (inst.LK)
ibuild.EmitStoreLink(ibuild.EmitIntConst(js.compilerPC + 4));
return;
}
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);
}
void JitArmIL::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 (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
inst.hex == 0x4182fff8 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 &&
(Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 ||
(SConfig::GetInstance().m_LocalCoreStartupParameter.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 JitArmIL::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);
}

View File

@ -1,492 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/JitArmIL/JitIL.h"
#include "Core/PowerPC/JitArmIL/JitIL_Tables.h"
// Should be moved in to the Jit class
typedef void (JitArmIL::*_Instruction) (UGeckoInstruction instCode);
static _Instruction dynaOpTable[64];
static _Instruction dynaOpTable4[1024];
static _Instruction dynaOpTable19[1024];
static _Instruction dynaOpTable31[1024];
static _Instruction dynaOpTable59[32];
static _Instruction dynaOpTable63[1024];
void JitArmIL::DynaRunTable4(UGeckoInstruction _inst) {(this->*dynaOpTable4 [_inst.SUBOP10])(_inst);}
void JitArmIL::DynaRunTable19(UGeckoInstruction _inst) {(this->*dynaOpTable19[_inst.SUBOP10])(_inst);}
void JitArmIL::DynaRunTable31(UGeckoInstruction _inst) {(this->*dynaOpTable31[_inst.SUBOP10])(_inst);}
void JitArmIL::DynaRunTable59(UGeckoInstruction _inst) {(this->*dynaOpTable59[_inst.SUBOP5 ])(_inst);}
void JitArmIL::DynaRunTable63(UGeckoInstruction _inst) {(this->*dynaOpTable63[_inst.SUBOP10])(_inst);}
struct GekkoOPTemplate
{
int opcode;
_Instruction Inst;
//GekkoOPInfo opinfo; // Doesn't need opinfo, Interpreter fills it out
};
static GekkoOPTemplate primarytable[] =
{
{4, &JitArmIL::DynaRunTable4}, //"RunTable4", OPTYPE_SUBTABLE | (4<<24), 0}},
{19, &JitArmIL::DynaRunTable19}, //"RunTable19", OPTYPE_SUBTABLE | (19<<24), 0}},
{31, &JitArmIL::DynaRunTable31}, //"RunTable31", OPTYPE_SUBTABLE | (31<<24), 0}},
{59, &JitArmIL::DynaRunTable59}, //"RunTable59", OPTYPE_SUBTABLE | (59<<24), 0}},
{63, &JitArmIL::DynaRunTable63}, //"RunTable63", OPTYPE_SUBTABLE | (63<<24), 0}},
{16, &JitArmIL::bcx}, //"bcx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{18, &JitArmIL::bx}, //"bx", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{1, &JitArmIL::HLEFunction}, //"HLEFunction", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{2, &JitArmIL::FallBackToInterpreter}, //"DynaBlock", OPTYPE_SYSTEM, 0}},
{3, &JitArmIL::Break}, //"twi", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{17, &JitArmIL::sc}, //"sc", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
{7, &JitArmIL::FallBackToInterpreter}, //"mulli", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_RC_BIT, 2}},
{8, &JitArmIL::FallBackToInterpreter}, //"subfic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{10, &JitArmIL::cmpXX}, //"cmpli", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{11, &JitArmIL::cmpXX}, //"cmpi", OPTYPE_INTEGER, FL_IN_A | FL_SET_CRn}},
{12, &JitArmIL::FallBackToInterpreter}, //"addic", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CA}},
{13, &JitArmIL::FallBackToInterpreter}, //"addic_rc", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A | FL_SET_CR0}},
{14, &JitArmIL::reg_imm}, //"addi", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{15, &JitArmIL::reg_imm}, //"addis", OPTYPE_INTEGER, FL_OUT_D | FL_IN_A0}},
{20, &JitArmIL::FallBackToInterpreter}, //"rlwimix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT}},
{21, &JitArmIL::FallBackToInterpreter}, //"rlwinmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{23, &JitArmIL::FallBackToInterpreter}, //"rlwnmx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_IN_B | FL_RC_BIT}},
{24, &JitArmIL::reg_imm}, //"ori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{25, &JitArmIL::reg_imm}, //"oris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{26, &JitArmIL::reg_imm}, //"xori", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{27, &JitArmIL::reg_imm}, //"xoris", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S}},
{28, &JitArmIL::reg_imm}, //"andi_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{29, &JitArmIL::reg_imm}, //"andis_rc", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_SET_CR0}},
{32, &JitArmIL::FallBackToInterpreter}, //"lwz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{33, &JitArmIL::FallBackToInterpreter}, //"lwzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{34, &JitArmIL::FallBackToInterpreter}, //"lbz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{35, &JitArmIL::FallBackToInterpreter}, //"lbzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{40, &JitArmIL::FallBackToInterpreter}, //"lhz", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{41, &JitArmIL::FallBackToInterpreter}, //"lhzu", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{42, &JitArmIL::FallBackToInterpreter}, //"lha", OPTYPE_LOAD, FL_OUT_D | FL_IN_A}},
{43, &JitArmIL::FallBackToInterpreter}, //"lhau", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A}},
{44, &JitArmIL::FallBackToInterpreter}, //"sth", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{45, &JitArmIL::FallBackToInterpreter}, //"sthu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{36, &JitArmIL::FallBackToInterpreter}, //"stw", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{37, &JitArmIL::FallBackToInterpreter}, //"stwu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{38, &JitArmIL::FallBackToInterpreter}, //"stb", OPTYPE_STORE, FL_IN_A | FL_IN_S}},
{39, &JitArmIL::FallBackToInterpreter}, //"stbu", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_S}},
{46, &JitArmIL::FallBackToInterpreter}, //"lmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
{47, &JitArmIL::FallBackToInterpreter}, //"stmw", OPTYPE_SYSTEM, FL_EVIL, 10}},
{48, &JitArmIL::FallBackToInterpreter}, //"lfs", OPTYPE_LOADFP, FL_IN_A}},
{49, &JitArmIL::FallBackToInterpreter}, //"lfsu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{50, &JitArmIL::FallBackToInterpreter}, //"lfd", OPTYPE_LOADFP, FL_IN_A}},
{51, &JitArmIL::FallBackToInterpreter}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{52, &JitArmIL::FallBackToInterpreter}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
{53, &JitArmIL::FallBackToInterpreter}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{54, &JitArmIL::FallBackToInterpreter}, //"stfd", OPTYPE_STOREFP, FL_IN_A}},
{55, &JitArmIL::FallBackToInterpreter}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{56, &JitArmIL::FallBackToInterpreter}, //"psq_l", OPTYPE_PS, FL_IN_A}},
{57, &JitArmIL::FallBackToInterpreter}, //"psq_lu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
{60, &JitArmIL::FallBackToInterpreter}, //"psq_st", OPTYPE_PS, FL_IN_A}},
{61, &JitArmIL::FallBackToInterpreter}, //"psq_stu", OPTYPE_PS, FL_OUT_A | FL_IN_A}},
//missing: 0, 5, 6, 9, 22, 30, 62, 58
{0, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{5, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{6, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{9, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{22, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{30, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{62, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
{58, &JitArmIL::FallBackToInterpreter}, //"unknown_instruction", OPTYPE_UNKNOWN, 0}},
};
static GekkoOPTemplate table4[] =
{ //SUBOP10
{0, &JitArmIL::FallBackToInterpreter}, //"ps_cmpu0", OPTYPE_PS, FL_SET_CRn}},
{32, &JitArmIL::FallBackToInterpreter}, //"ps_cmpo0", OPTYPE_PS, FL_SET_CRn}},
{40, &JitArmIL::FallBackToInterpreter}, //"ps_neg", OPTYPE_PS, FL_RC_BIT}},
{136, &JitArmIL::FallBackToInterpreter}, //"ps_nabs", OPTYPE_PS, FL_RC_BIT}},
{264, &JitArmIL::FallBackToInterpreter}, //"ps_abs", OPTYPE_PS, FL_RC_BIT}},
{64, &JitArmIL::FallBackToInterpreter}, //"ps_cmpu1", OPTYPE_PS, FL_RC_BIT}},
{72, &JitArmIL::FallBackToInterpreter}, //"ps_mr", OPTYPE_PS, FL_RC_BIT}},
{96, &JitArmIL::FallBackToInterpreter}, //"ps_cmpo1", OPTYPE_PS, FL_RC_BIT}},
{528, &JitArmIL::FallBackToInterpreter}, //"ps_merge00", OPTYPE_PS, FL_RC_BIT}},
{560, &JitArmIL::FallBackToInterpreter}, //"ps_merge01", OPTYPE_PS, FL_RC_BIT}},
{592, &JitArmIL::FallBackToInterpreter}, //"ps_merge10", OPTYPE_PS, FL_RC_BIT}},
{624, &JitArmIL::FallBackToInterpreter}, //"ps_merge11", OPTYPE_PS, FL_RC_BIT}},
{1014, &JitArmIL::FallBackToInterpreter}, //"dcbz_l", OPTYPE_SYSTEM, 0}},
};
static GekkoOPTemplate table4_2[] =
{
{10, &JitArmIL::FallBackToInterpreter}, //"ps_sum0", OPTYPE_PS, 0}},
{11, &JitArmIL::FallBackToInterpreter}, //"ps_sum1", OPTYPE_PS, 0}},
{12, &JitArmIL::FallBackToInterpreter}, //"ps_muls0", OPTYPE_PS, 0}},
{13, &JitArmIL::FallBackToInterpreter}, //"ps_muls1", OPTYPE_PS, 0}},
{14, &JitArmIL::FallBackToInterpreter}, //"ps_madds0", OPTYPE_PS, 0}},
{15, &JitArmIL::FallBackToInterpreter}, //"ps_madds1", OPTYPE_PS, 0}},
{18, &JitArmIL::FallBackToInterpreter}, //"ps_div", OPTYPE_PS, 0, 16}},
{20, &JitArmIL::FallBackToInterpreter}, //"ps_sub", OPTYPE_PS, 0}},
{21, &JitArmIL::FallBackToInterpreter}, //"ps_add", OPTYPE_PS, 0}},
{23, &JitArmIL::FallBackToInterpreter}, //"ps_sel", OPTYPE_PS, 0}},
{24, &JitArmIL::FallBackToInterpreter}, //"ps_res", OPTYPE_PS, 0}},
{25, &JitArmIL::FallBackToInterpreter}, //"ps_mul", OPTYPE_PS, 0}},
{26, &JitArmIL::FallBackToInterpreter}, //"ps_rsqrte", OPTYPE_PS, 0, 1}},
{28, &JitArmIL::FallBackToInterpreter}, //"ps_msub", OPTYPE_PS, 0}},
{29, &JitArmIL::FallBackToInterpreter}, //"ps_madd", OPTYPE_PS, 0}},
{30, &JitArmIL::FallBackToInterpreter}, //"ps_nmsub", OPTYPE_PS, 0}},
{31, &JitArmIL::FallBackToInterpreter}, //"ps_nmadd", OPTYPE_PS, 0}},
};
static GekkoOPTemplate table4_3[] =
{
{6, &JitArmIL::FallBackToInterpreter}, //"psq_lx", OPTYPE_PS, 0}},
{7, &JitArmIL::FallBackToInterpreter}, //"psq_stx", OPTYPE_PS, 0}},
{38, &JitArmIL::FallBackToInterpreter}, //"psq_lux", OPTYPE_PS, 0}},
{39, &JitArmIL::FallBackToInterpreter}, //"psq_stux", OPTYPE_PS, 0}},
};
static GekkoOPTemplate table19[] =
{
{528, &JitArmIL::bcctrx}, //"bcctrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{16, &JitArmIL::bclrx}, //"bclrx", OPTYPE_BRANCH, FL_ENDBLOCK}},
{257, &JitArmIL::crXX}, //"crand", OPTYPE_CR, FL_EVIL}},
{129, &JitArmIL::crXX}, //"crandc", OPTYPE_CR, FL_EVIL}},
{289, &JitArmIL::crXX}, //"creqv", OPTYPE_CR, FL_EVIL}},
{225, &JitArmIL::crXX}, //"crnand", OPTYPE_CR, FL_EVIL}},
{33, &JitArmIL::crXX}, //"crnor", OPTYPE_CR, FL_EVIL}},
{449, &JitArmIL::crXX}, //"cror", OPTYPE_CR, FL_EVIL}},
{417, &JitArmIL::crXX}, //"crorc", OPTYPE_CR, FL_EVIL}},
{193, &JitArmIL::crXX}, //"crxor", OPTYPE_CR, FL_EVIL}},
{150, &JitArmIL::FallBackToInterpreter}, //"isync", OPTYPE_ICACHE, FL_EVIL}},
{0, &JitArmIL::FallBackToInterpreter}, //"mcrf", OPTYPE_SYSTEM, FL_EVIL}},
{50, &JitArmIL::rfi}, //"rfi", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS, 1}},
{18, &JitArmIL::Break}, //"rfid", OPTYPE_SYSTEM, FL_ENDBLOCK | FL_CHECKEXCEPTIONS}}
};
static GekkoOPTemplate table31[] =
{
{28, &JitArmIL::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{60, &JitArmIL::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{444, &JitArmIL::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{124, &JitArmIL::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{316, &JitArmIL::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{412, &JitArmIL::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{476, &JitArmIL::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{284, &JitArmIL::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
{0, &JitArmIL::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{32, &JitArmIL::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
{26, &JitArmIL::FallBackToInterpreter}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{922, &JitArmIL::FallBackToInterpreter}, //"extshx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{954, &JitArmIL::FallBackToInterpreter}, //"extsbx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
{536, &JitArmIL::FallBackToInterpreter}, //"srwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{792, &JitArmIL::FallBackToInterpreter}, //"srawx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{824, &JitArmIL::FallBackToInterpreter}, //"srawix", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{24, &JitArmIL::FallBackToInterpreter}, //"slwx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_B | FL_IN_S | FL_RC_BIT}},
{54, &JitArmIL::FallBackToInterpreter}, //"dcbst", OPTYPE_DCACHE, 0, 4}},
{86, &JitArmIL::FallBackToInterpreter}, //"dcbf", OPTYPE_DCACHE, 0, 4}},
{246, &JitArmIL::FallBackToInterpreter}, //"dcbtst", OPTYPE_DCACHE, 0, 1}},
{278, &JitArmIL::FallBackToInterpreter}, //"dcbt", OPTYPE_DCACHE, 0, 1}},
{470, &JitArmIL::FallBackToInterpreter}, //"dcbi", OPTYPE_DCACHE, 0, 4}},
{758, &JitArmIL::FallBackToInterpreter}, //"dcba", OPTYPE_DCACHE, 0, 4}},
{1014, &JitArmIL::FallBackToInterpreter}, //"dcbz", OPTYPE_DCACHE, 0, 4}},
//load word
{23, &JitArmIL::FallBackToInterpreter}, //"lwzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{55, &JitArmIL::FallBackToInterpreter}, //"lwzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load halfword
{279, &JitArmIL::FallBackToInterpreter}, //"lhzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{311, &JitArmIL::FallBackToInterpreter}, //"lhzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load halfword signextend
{343, &JitArmIL::FallBackToInterpreter}, //"lhax", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{375, &JitArmIL::FallBackToInterpreter}, //"lhaux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load byte
{87, &JitArmIL::FallBackToInterpreter}, //"lbzx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{119, &JitArmIL::FallBackToInterpreter}, //"lbzux", OPTYPE_LOAD, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_IN_B}},
//load byte reverse
{534, &JitArmIL::FallBackToInterpreter}, //"lwbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
{790, &JitArmIL::FallBackToInterpreter}, //"lhbrx", OPTYPE_LOAD, FL_OUT_D | FL_IN_A0 | FL_IN_B}},
// Conditional load/store (Wii SMP)
{150, &JitArmIL::FallBackToInterpreter}, //"stwcxd", OPTYPE_STORE, FL_EVIL | FL_SET_CR0}},
{20, &JitArmIL::FallBackToInterpreter}, //"lwarx", OPTYPE_LOAD, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0}},
//load string (interpret these)
{533, &JitArmIL::FallBackToInterpreter}, //"lswx", OPTYPE_LOAD, FL_EVIL | FL_IN_A | FL_OUT_D}},
{597, &JitArmIL::FallBackToInterpreter}, //"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}},
//store word
{151, &JitArmIL::FallBackToInterpreter}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{183, &JitArmIL::FallBackToInterpreter}, //"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
//store halfword
{407, &JitArmIL::FallBackToInterpreter}, //"sthx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{439, &JitArmIL::FallBackToInterpreter}, //"sthux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
//store byte
{215, &JitArmIL::FallBackToInterpreter}, //"stbx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{247, &JitArmIL::FallBackToInterpreter}, //"stbux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
//store bytereverse
{662, &JitArmIL::FallBackToInterpreter}, //"stwbrx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{918, &JitArmIL::FallBackToInterpreter}, //"sthbrx", OPTYPE_STORE, FL_IN_A | FL_IN_B}},
{661, &JitArmIL::FallBackToInterpreter}, //"stswx", OPTYPE_STORE, FL_EVIL}},
{725, &JitArmIL::FallBackToInterpreter}, //"stswi", OPTYPE_STORE, FL_EVIL}},
// fp load/store
{535, &JitArmIL::FallBackToInterpreter}, //"lfsx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
{567, &JitArmIL::FallBackToInterpreter}, //"lfsux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
{599, &JitArmIL::FallBackToInterpreter}, //"lfdx", OPTYPE_LOADFP, FL_IN_A0 | FL_IN_B}},
{631, &JitArmIL::FallBackToInterpreter}, //"lfdux", OPTYPE_LOADFP, FL_IN_A | FL_IN_B}},
{663, &JitArmIL::FallBackToInterpreter}, //"stfsx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{695, &JitArmIL::FallBackToInterpreter}, //"stfsux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
{727, &JitArmIL::FallBackToInterpreter}, //"stfdx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{759, &JitArmIL::FallBackToInterpreter}, //"stfdux", OPTYPE_STOREFP, FL_IN_A | FL_IN_B}},
{983, &JitArmIL::FallBackToInterpreter}, //"stfiwx", OPTYPE_STOREFP, FL_IN_A0 | FL_IN_B}},
{19, &JitArmIL::FallBackToInterpreter}, //"mfcr", OPTYPE_SYSTEM, FL_OUT_D}},
{83, &JitArmIL::FallBackToInterpreter}, //"mfmsr", OPTYPE_SYSTEM, FL_OUT_D}},
{144, &JitArmIL::FallBackToInterpreter}, //"mtcrf", OPTYPE_SYSTEM, 0}},
{146, &JitArmIL::mtmsr}, //"mtmsr", OPTYPE_SYSTEM, FL_ENDBLOCK}},
{210, &JitArmIL::FallBackToInterpreter}, //"mtsr", OPTYPE_SYSTEM, 0}},
{242, &JitArmIL::FallBackToInterpreter}, //"mtsrin", OPTYPE_SYSTEM, 0}},
{339, &JitArmIL::FallBackToInterpreter}, //"mfspr", OPTYPE_SPR, FL_OUT_D}},
{467, &JitArmIL::FallBackToInterpreter}, //"mtspr", OPTYPE_SPR, 0, 2}},
{371, &JitArmIL::FallBackToInterpreter}, //"mftb", OPTYPE_SYSTEM, FL_OUT_D | FL_TIMER}},
{512, &JitArmIL::FallBackToInterpreter}, //"mcrxr", OPTYPE_SYSTEM, 0}},
{595, &JitArmIL::FallBackToInterpreter}, //"mfsr", OPTYPE_SYSTEM, FL_OUT_D, 2}},
{659, &JitArmIL::FallBackToInterpreter}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
{4, &JitArmIL::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
{598, &JitArmIL::FallBackToInterpreter}, //"sync", OPTYPE_SYSTEM, 0, 2}},
{982, &JitArmIL::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}},
// Unused instructions on GC
{310, &JitArmIL::FallBackToInterpreter}, //"eciwx", OPTYPE_INTEGER, FL_RC_BIT}},
{438, &JitArmIL::FallBackToInterpreter}, //"ecowx", OPTYPE_INTEGER, FL_RC_BIT}},
{854, &JitArmIL::FallBackToInterpreter}, //"eieio", OPTYPE_INTEGER, FL_RC_BIT}},
{306, &JitArmIL::FallBackToInterpreter}, //"tlbie", OPTYPE_SYSTEM, 0}},
{370, &JitArmIL::FallBackToInterpreter}, //"tlbia", OPTYPE_SYSTEM, 0}},
{566, &JitArmIL::FallBackToInterpreter}, //"tlbsync", OPTYPE_SYSTEM, 0}},
};
static GekkoOPTemplate table31_2[] =
{
{266, &JitArmIL::FallBackToInterpreter}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{778, &JitArmIL::FallBackToInterpreter}, //"addx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{10, &JitArmIL::FallBackToInterpreter}, //"addcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{522, &JitArmIL::FallBackToInterpreter}, //"addcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{138, &JitArmIL::FallBackToInterpreter}, //"addex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{650, &JitArmIL::FallBackToInterpreter}, //"addeox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{234, &JitArmIL::FallBackToInterpreter}, //"addmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{202, &JitArmIL::FallBackToInterpreter}, //"addzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{491, &JitArmIL::FallBackToInterpreter}, //"divwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{1003, &JitArmIL::FallBackToInterpreter}, //"divwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{459, &JitArmIL::FallBackToInterpreter}, //"divwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{971, &JitArmIL::FallBackToInterpreter}, //"divwuox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 39}},
{75, &JitArmIL::FallBackToInterpreter}, //"mulhwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{11, &JitArmIL::FallBackToInterpreter}, //"mulhwux", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{235, &JitArmIL::FallBackToInterpreter}, //"mullwx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{747, &JitArmIL::FallBackToInterpreter}, //"mullwox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 4}},
{104, &JitArmIL::FallBackToInterpreter}, //"negx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{40, &JitArmIL::FallBackToInterpreter}, //"subfx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{552, &JitArmIL::FallBackToInterpreter}, //"subox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_RC_BIT}},
{8, &JitArmIL::FallBackToInterpreter}, //"subfcx", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{520, &JitArmIL::FallBackToInterpreter}, //"subfcox", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT}},
{136, &JitArmIL::FallBackToInterpreter}, //"subfex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{232, &JitArmIL::FallBackToInterpreter}, //"subfmex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
{200, &JitArmIL::FallBackToInterpreter}, //"subfzex", OPTYPE_INTEGER, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT}},
};
static GekkoOPTemplate table59[] =
{
{18, &JitArmIL::FallBackToInterpreter}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{20, &JitArmIL::FallBackToInterpreter}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitArmIL::FallBackToInterpreter}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
// {22, &JitArmIL::FallBackToInterpreter}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}},
{24, &JitArmIL::FallBackToInterpreter}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArmIL::FallBackToInterpreter}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitArmIL::FallBackToInterpreter}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitArmIL::FallBackToInterpreter}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
{30, &JitArmIL::FallBackToInterpreter}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{31, &JitArmIL::FallBackToInterpreter}, //"fnmaddsx", OPTYPE_FPU, FL_RC_BIT_F}},
};
static GekkoOPTemplate table63[] =
{
{264, &JitArmIL::FallBackToInterpreter}, //"fabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{32, &JitArmIL::FallBackToInterpreter}, //"fcmpo", OPTYPE_FPU, FL_RC_BIT_F}},
{0, &JitArmIL::FallBackToInterpreter}, //"fcmpu", OPTYPE_FPU, FL_RC_BIT_F}},
{14, &JitArmIL::FallBackToInterpreter}, //"fctiwx", OPTYPE_FPU, FL_RC_BIT_F}},
{15, &JitArmIL::FallBackToInterpreter}, //"fctiwzx", OPTYPE_FPU, FL_RC_BIT_F}},
{72, &JitArmIL::FallBackToInterpreter}, //"fmrx", OPTYPE_FPU, FL_RC_BIT_F}},
{136, &JitArmIL::FallBackToInterpreter}, //"fnabsx", OPTYPE_FPU, FL_RC_BIT_F}},
{40, &JitArmIL::FallBackToInterpreter}, //"fnegx", OPTYPE_FPU, FL_RC_BIT_F}},
{12, &JitArmIL::FallBackToInterpreter}, //"frspx", OPTYPE_FPU, FL_RC_BIT_F}},
{64, &JitArmIL::FallBackToInterpreter}, //"mcrfs", OPTYPE_SYSTEMFP, 0}},
{583, &JitArmIL::FallBackToInterpreter}, //"mffsx", OPTYPE_SYSTEMFP, 0}},
{70, &JitArmIL::FallBackToInterpreter}, //"mtfsb0x", OPTYPE_SYSTEMFP, 0, 2}},
{38, &JitArmIL::FallBackToInterpreter}, //"mtfsb1x", OPTYPE_SYSTEMFP, 0, 2}},
{134, &JitArmIL::FallBackToInterpreter}, //"mtfsfix", OPTYPE_SYSTEMFP, 0, 2}},
{711, &JitArmIL::FallBackToInterpreter}, //"mtfsfx", OPTYPE_SYSTEMFP, 0, 2}},
};
static GekkoOPTemplate table63_2[] =
{
{18, &JitArmIL::FallBackToInterpreter}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}},
{20, &JitArmIL::FallBackToInterpreter}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, &JitArmIL::FallBackToInterpreter}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}},
{22, &JitArmIL::FallBackToInterpreter}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}},
{23, &JitArmIL::FallBackToInterpreter}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, &JitArmIL::FallBackToInterpreter}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}},
{26, &JitArmIL::FallBackToInterpreter}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}},
{28, &JitArmIL::FallBackToInterpreter}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{29, &JitArmIL::FallBackToInterpreter}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
{30, &JitArmIL::FallBackToInterpreter}, //"fnmsubx", OPTYPE_FPU, FL_RC_BIT_F}},
{31, &JitArmIL::FallBackToInterpreter}, //"fnmaddx", OPTYPE_FPU, FL_RC_BIT_F}},
};
namespace JitArmILTables
{
void CompileInstruction(PPCAnalyst::CodeOp & op)
{
JitArmIL *jitarm = (JitArmIL *)jit;
(jitarm->*dynaOpTable[op.inst.OPCD])(op.inst);
GekkoOPInfo *info = op.opinfo;
if (info) {
#ifdef OPLOG
if (!strcmp(info->opname, OP_TO_LOG)){ ///"mcrfs"
rsplocations.push_back(jit.js.compilerPC);
}
#endif
info->compileCount++;
info->lastUse = jit->js.compilerPC;
}
}
void InitTables()
{
// once initialized, tables are read-only
static bool initialized = false;
if (initialized)
return;
//clear
for (int i = 0; i < 32; i++)
{
dynaOpTable59[i] = &JitArmIL::unknown_instruction;
}
for (int i = 0; i < 1024; i++)
{
dynaOpTable4 [i] = &JitArmIL::unknown_instruction;
dynaOpTable19[i] = &JitArmIL::unknown_instruction;
dynaOpTable31[i] = &JitArmIL::unknown_instruction;
dynaOpTable63[i] = &JitArmIL::unknown_instruction;
}
for (int i = 0; i < (int)(sizeof(primarytable) / sizeof(GekkoOPTemplate)); i++)
{
dynaOpTable[primarytable[i].opcode] = primarytable[i].Inst;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (int j = 0; j < (int)(sizeof(table4_2) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill+table4_2[j].opcode;
dynaOpTable4[op] = table4_2[j].Inst;
}
}
for (int i = 0; i < 16; i++)
{
int fill = i << 6;
for (int j = 0; j < (int)(sizeof(table4_3) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill+table4_3[j].opcode;
dynaOpTable4[op] = table4_3[j].Inst;
}
}
for (int i = 0; i < (int)(sizeof(table4) / sizeof(GekkoOPTemplate)); i++)
{
int op = table4[i].opcode;
dynaOpTable4[op] = table4[i].Inst;
}
for (int i = 0; i < (int)(sizeof(table31) / sizeof(GekkoOPTemplate)); i++)
{
int op = table31[i].opcode;
dynaOpTable31[op] = table31[i].Inst;
}
for (int i = 0; i < 1; i++)
{
int fill = i << 9;
for (int j = 0; j < (int)(sizeof(table31_2) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill + table31_2[j].opcode;
dynaOpTable31[op] = table31_2[j].Inst;
}
}
for (int i = 0; i < (int)(sizeof(table19) / sizeof(GekkoOPTemplate)); i++)
{
int op = table19[i].opcode;
dynaOpTable19[op] = table19[i].Inst;
}
for (int i = 0; i < (int)(sizeof(table59) / sizeof(GekkoOPTemplate)); i++)
{
int op = table59[i].opcode;
dynaOpTable59[op] = table59[i].Inst;
}
for (int i = 0; i < (int)(sizeof(table63) / sizeof(GekkoOPTemplate)); i++)
{
int op = table63[i].opcode;
dynaOpTable63[op] = table63[i].Inst;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (int j = 0; j < (int)(sizeof(table63_2) / sizeof(GekkoOPTemplate)); j++)
{
int op = fill + table63_2[j].opcode;
dynaOpTable63[op] = table63_2[j].Inst;
}
}
initialized = true;
}
} // namespace

View File

@ -1,14 +0,0 @@
// Copyright 2014 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/PPCTables.h"
namespace JitArmILTables
{
void CompileInstruction(PPCAnalyst::CodeOp & op);
void InitTables();
}

View File

@ -27,8 +27,6 @@
#if _M_ARM_32
#include "Core/PowerPC/JitArm32/Jit.h"
#include "Core/PowerPC/JitArm32/JitArm_Tables.h"
#include "Core/PowerPC/JitArmIL/JitIL.h"
#include "Core/PowerPC/JitArmIL/JitIL_Tables.h"
#endif
static bool bFakeVMEM = false;
@ -67,11 +65,6 @@ namespace JitInterface
ptr = new JitArm();
break;
}
case 4:
{
ptr = new JitArmIL();
break;
}
#endif
default:
{
@ -106,11 +99,6 @@ namespace JitInterface
JitArmTables::InitTables();
break;
}
case 4:
{
JitArmILTables::InitTables();
break;
}
#endif
default:
{