mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
More armjit work
This commit is contained in:
parent
a2ff416534
commit
5a7f4acc06
11 changed files with 141 additions and 79 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -15,4 +15,4 @@ public class PpssppActivity extends NativeActivity {
|
|||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue