More armjit work

This commit is contained in:
Henrik Rydgard 2013-01-08 00:26:42 +01:00
parent a2ff416534
commit 5a7f4acc06
11 changed files with 141 additions and 79 deletions

View file

@ -112,6 +112,8 @@ enum OpType
TYPE_MEM
};
// This is no longer a proper operand2 class. Need to split up.
class Operand2
{
friend class ARMXEmitter;

View file

@ -56,7 +56,8 @@ static bool enableDebug = false;
// STATIC ALLOCATION ARM:
// R11 : Memory base pointer.
// R10 : MIPS state
// R9 :
extern volatile CoreState coreState;
void Jit()
@ -64,54 +65,73 @@ void Jit()
MIPSComp::jit->Compile(currentMIPS->pc);
}
void ImHere() {
static int i = 0;
i++;
INFO_LOG(HLE, "I'm too here %i", i);
}
void ImHere2(u32 hej) {
static int i = 0;
i++;
INFO_LOG(HLE, "I'm here2 %i %08x", i, hej);
}
// PLAN: no more block numbers - crazy opcodes just contain offset within
// dynarec buffer
// At this offset - 4, there is an int specifying the block number.
void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit)
void ArmAsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit)
{
enterCode = AlignCode16();
PUSH(8, R5, R6, R7, R8, R9, R10, R11, _LR);
SetCC(CC_AL);
PUSH(8, R5, R6, R7, R8, R9, R10, R11, _LR);
// Fixed registers, these are always kept when in Jit context.
// R13 cannot be used as it's the stack pointer.
ARMABI_MOVI2R(R11, (u32)Memory::base);
ARMABI_MOVI2R(R12, (u32)currentMIPS);
ARMABI_MOVI2R(R14, (u32)jit->GetBlockCache()->GetCodePointers());
ARMABI_MOVI2R(R10, (u32)mips);
ARMABI_MOVI2R(R9, (u32)jit->GetBlockCache()->GetCodePointers());
// PROVEN: We Get Here
ARMABI_CallFunction((void *)&ImHere);
outerLoop = GetCodePtr();
//ARMABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
ARMABI_CallFunction((void *)&CoreTiming::Advance);
FixupBranch skipToRealDispatch = B(); //skip the sync and compare first time
dispatcherCheckCoreState = GetCodePtr();
//TODO: critical
//CMP(32, M((void*)&coreState), Imm32(0));
FixupBranch badCoreState; // = J_CC(CC_NZ, true);
// TODO: critical
ARMABI_MOVI2R(R0, (u32)&coreState);
LDR(R0, R0);
CMP(R0, 0);
FixupBranch badCoreState = B_CC(CC_NEQ);
// At this point : flags = EQ. Fine for the next check, no need to jump over it.
dispatcher = GetCodePtr();
// The result of slice decrementation should be in flags if somebody jumped here
// IMPORTANT - We jump on negative, not carry!!!
SetCC(CC_LT);
FixupBranch bail = B();
SetCC(CC_AL);
FixupBranch bail = B_CC(CC_LT);
SetJumpTarget(skipToRealDispatch);
//INT3();
dispatcherNoCheck = GetCodePtr();
// LDR(R0, R11, R0, M(&mips->pc));
dispatcherPcInR0 = GetCodePtr();
_assert_msg_(CPU, Memory::base != 0, "Memory base bogus");
//ARMABI_MOVIMM32(R1, Memory::MEMVIEW32_MASK + 1);
// Debug
ARMABI_MOVI2R(R0, (u32)&mips->pc);
LDR(R0, R0);
ARMABI_MOVI2R(R1, Memory::MEMVIEW32_MASK); // can be done with single MOVN instruction
AND(R0, R0, R1);
LDR(R0, R11, R0);
AND(R1, R0, Operand2(0xFC, 24));
BIC(R0, R0, Operand2(0xFC, 24));
CMP(R1, Operand2(MIPS_EMUHACK_OPCODE >> 24, 24));
ARMABI_CallFunction((void *)&ImHere2);
LDR(R0, R11, R(R0));
AND(R1, R0, Operand2(0xFC, 4)); // rotation is to the right, in 2-bit increments.
BIC(R0, R0, Operand2(0xFC, 4));
CMP(R1, Operand2(MIPS_EMUHACK_OPCODE >> 24, 4));
FixupBranch notfound = B_CC(CC_NEQ);
// IDEA - we have 24 bits, why not just use offsets from base of code?
if (enableDebug)
@ -119,24 +139,32 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit)
//ADD(32, M(&mips->debugCount), Imm8(1));
}
// grab from list and jump to it
ADD(R0, R10, Operand2(2, ST_LSL, R0));
ADD(R0, R14, Operand2(2, ST_LSL, R0));
LDR(R0, R0);
B(R0);
SetJumpTarget(notfound);
ARMABI_CallFunction((void *)&ImHere);
//Ok, no block, let's jit
ARMABI_CallFunction((void *)&Jit);
B(dispatcherNoCheck); // no point in special casing this
SetJumpTarget(bail);
SetJumpTarget(badCoreState);
// TODO: critical
ARMABI_MOVI2R(R0, (u32)&coreState);
LDR(R0, R0);
CMP(R0, 0);
B_CC(CC_EQ, outerLoop);
//CMP(M((void*)&coreState), Imm8(0));
SetCC(CC_EQ);
//B(outerLoop);
SetCC(CC_AL);
SetJumpTarget(badCoreState);
//Landing pad for drec space
ARMABI_CallFunction((void *)&ImHere);
PUSH(8, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns
//Landing pad for drec space
POP(8, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns
}

View file

@ -28,16 +28,20 @@ namespace MIPSComp
class Jit;
}
class AsmRoutineManager : public ArmGen::ARMXCodeBlock
class ArmAsmRoutineManager : public ArmGen::ARMXCodeBlock
{
private:
void Generate(MIPSState *mips, MIPSComp::Jit *jit);
void GenerateCommon();
public:
AsmRoutineManager()
ArmAsmRoutineManager()
{
}
~ArmAsmRoutineManager()
{
FreeCodeSpace();
}
void Init(MIPSState *mips, MIPSComp::Jit *jit)
{
@ -45,10 +49,6 @@ public:
Generate(mips, jit);
WriteProtect();
}
~AsmRoutineManager()
{
FreeCodeSpace();
}
const u8 *enterCode;
@ -56,7 +56,8 @@ public:
const u8 *dispatcherCheckCoreState;
const u8 *dispatcher;
const u8 *dispatcherNoCheck;
const u8 *dispatcherPcInR0;
const u8 *breakpointBailout;
};
#endif // _JIT64ASM_H

View file

@ -193,7 +193,6 @@ void Jit::Comp_RelBranchRI(u32 op)
js.compiling = false;
}
// If likely is set, discard the branch slot if NOT taken.
void Jit::BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely)
{
@ -209,9 +208,9 @@ void Jit::BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely)
}
FlushAll();
ARMABI_MOVI2R(R0, (u32)&(mips_->fcr31));
ARMABI_MOVI2R(R0, (u32)&(mips_->fpcond));
LDR(R0, R0, Operand2(0, TYPE_IMM));
TST(R0, Operand2(1 << 23, TYPE_IMM));
TST(R0, Operand2(1, TYPE_IMM));
ArmGen::FixupBranch ptr;
js.inDelaySlot = true;
if (!likely)
@ -259,29 +258,68 @@ void Jit::Comp_FPUBranch(u32 op)
js.compiling = false;
}
// If likely is set, discard the branch slot if NOT taken.
void Jit::BranchVFPUFlag(u32 op, ArmGen::CCFlags cc, bool likely)
{
int offset = (signed short)(op & 0xFFFF) << 2;
u32 targetAddr = js.compilerPC + offset + 4;
u32 delaySlotOp = Memory::ReadUnchecked_U32(js.compilerPC + 4);
bool delaySlotIsNice = IsDelaySlotNice(op, delaySlotOp);
if (!delaySlotIsNice)
{
ERROR_LOG(CPU, "Not nice delay slot in BranchFPFlag :(");
}
FlushAll();
ARMABI_MOVI2R(R0, (u32)&(mips_->vfpuCtrl[VFPU_CTRL_CC]));
LDR(R0, R0, Operand2(0, TYPE_IMM));
int imm3 = (op >> 18) & 7;
TST(R0, Operand2(1 << imm3, TYPE_IMM));
ArmGen::FixupBranch ptr;
js.inDelaySlot = true;
if (!likely)
{
MRS(R0); // Save flags register
PUSH(1, R0);
CompileAt(js.compilerPC + 4);
FlushAll();
// POPF(); // restore flag!
POP(1, R0);
_MSR(true, false, R0); // Restore flags register
ptr = B_CC(cc);
}
else
{
ptr = B_CC(cc);
CompileAt(js.compilerPC + 4);
FlushAll();
}
js.inDelaySlot = false;
// Take the branch
WriteExit(targetAddr, 0);
SetJumpTarget(ptr);
// Not taken
WriteExit(js.compilerPC + 8, 1);
js.compiling = false;
}
void Jit::Comp_VBranch(u32 op)
{
/*
Comp_Generic(op + 4);
Comp_Generic(op);
js.compiling = false;
return;
int imm = (signed short)(op&0xFFFF)<<2;
u32 targetAddr = js.compilerPC + imm + 4;
int imm3 = (op >> 18) & 7;
int val = (mips_->vfpuCtrl[VFPU_CTRL_CC] >> imm3) & 1;
switch ((op >> 16) & 3)
{
//case 0: if (!val) DelayBranchTo(addr); else PC += 4; break; //bvf
//case 1: if ( val) DelayBranchTo(addr); else PC += 4; break; //bvt
//case 2: if (!val) DelayBranchTo(addr); else PC += 8; break; //bvfl
//case 3: if ( val) DelayBranchTo(addr); else PC += 8; break; //bvtl
//TODO
}
*/
case 0: BranchVFPUFlag(op, CC_NEQ, false); break; // bvf
case 1: BranchVFPUFlag(op, CC_EQ, false); break; // bvt
case 2: BranchVFPUFlag(op, CC_NEQ, true); break; // bvfl
case 3: BranchVFPUFlag(op, CC_EQ, true); break; // bvtl
}
js.compiling = false;
}

View file

@ -105,6 +105,7 @@ void Jit::RunLoopUntil(u64 globalticks)
{
// TODO: copy globalticks somewhere
((void (*)())asm_.enterCode)();
INFO_LOG(DYNA_REC, "Left asm code");
}
const u8 *Jit::DoJit(u32 em_address, ArmJitBlock *b)

View file

@ -88,7 +88,7 @@ public:
void Comp_mxc1(u32 op);
ArmJitBlockCache *GetBlockCache() { return &blocks; }
AsmRoutineManager &Asm() { return asm_; }
ArmAsmRoutineManager &Asm() { return asm_; }
void ClearCache();
@ -103,6 +103,7 @@ private:
// Utility compilation functions
void BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely);
void BranchVFPUFlag(u32 op, ArmGen::CCFlags cc, bool likely);
void BranchRSZeroComp(u32 op, ArmGen::CCFlags cc, bool likely);
void BranchRSRTComp(u32 op, ArmGen::CCFlags cc, bool likely);
@ -123,7 +124,7 @@ private:
ArmRegCache gpr;
// FPURegCache fpr;
AsmRoutineManager asm_;
ArmAsmRoutineManager asm_;
MIPSState *mips_;
};

View file

@ -45,7 +45,7 @@ void ArmRegCache::Start(MIPSAnalyst::AnalysisResults &stats) {
static const ARMReg *GetMIPSAllocationOrder(int &count) {
// Note that R0 and R1 are reserved as scratch for now. We can probably free up R1 eventually.
static const ARMReg allocationOrder[] = {
R2, R3, R4, R5, R6, R7, R8, R9
R2, R3, R4, R5, R6, R7, R8
};
count = sizeof(allocationOrder) / sizeof(const int);
return allocationOrder;

View file

@ -38,6 +38,10 @@ public:
AsmRoutineManager()
{
}
~AsmRoutineManager()
{
FreeCodeSpace();
}
void Init(MIPSState *mips, MIPSComp::Jit *jit)
{
@ -45,10 +49,6 @@ public:
Generate(mips, jit);
WriteProtect();
}
~AsmRoutineManager()
{
FreeCodeSpace();
}
const u8 *enterCode;

View file

@ -47,10 +47,6 @@ EmuScreen::EmuScreen(const std::string &filename) : invalid_(true)
CoreParameter coreParam;
coreParam.cpuCore = (CPUCore)g_Config.iCpuCore;
#if defined(ARM)
if (coreParam.cpuCore == CPU_JIT)
coreParam.cpuCore = CPU_FASTINTERPRETER;
#endif
coreParam.gpuCore = GPU_GLES;
coreParam.enableSound = g_Config.bEnableSound;
coreParam.fileToStart = fileToStart;

View file

@ -285,19 +285,14 @@ void SettingsScreen::render() {
}
UICheckBox(GEN_ID, x, y += 45, "Hardware Transform", ALIGN_TOPLEFT, &g_Config.bHardwareTransform);
bool useFastInt = g_Config.iCpuCore == CPU_FASTINTERPRETER;
UICheckBox(GEN_ID, x, y += 45, "Slightly faster interpreter (may crash)", ALIGN_TOPLEFT, &useFastInt);
bool useJit = g_Config.iCpuCore == CPU_JIT;
UICheckBox(GEN_ID, x, y += 45, "Use Dynarec (JIT)", ALIGN_TOPLEFT, &useJit);
g_Config.iCpuCore = useJit ? CPU_JIT : CPU_INTERPRETER;
// ui_draw2d.DrawText(UBUNTU48, "much faster JIT coming later", x, y+=50, 0xcFFFFFFF, ALIGN_LEFT);
UICheckBox(GEN_ID, x, y += 45, "On-screen Touch Controls", ALIGN_TOPLEFT, &g_Config.bShowTouchControls);
if (g_Config.bShowTouchControls)
UICheckBox(GEN_ID, x + 50, y += 50, "Show Analog Stick", ALIGN_TOPLEFT, &g_Config.bShowAnalogStick);
g_Config.iCpuCore = useFastInt ? CPU_FASTINTERPRETER : CPU_INTERPRETER;
bool useJit = g_Config.iCpuCore == CPU_JIT;
UICheckBox(GEN_ID, x, y += 50, "Use JIT (very crashy)", ALIGN_TOPLEFT, &useJit);
if (useJit) {
g_Config.iCpuCore = CPU_JIT;
}
// UICheckBox(GEN_ID, x, y += 50, "Draw raw framebuffer (for some homebrew)", ALIGN_TOPLEFT, &g_Config.bDisplayFramebuffer);
if (UIButton(GEN_ID, Pos(dp_xres - 10, dp_yres-10), LARGE_BUTTON_WIDTH, "Back", ALIGN_RIGHT | ALIGN_BOTTOM)) {

View file

@ -15,4 +15,4 @@ public class PpssppActivity extends NativeActivity {
{
return false;
}
}
}