diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 8e3574417c..610f37f31a 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -185,49 +185,55 @@
-
+
true
true
true
true
-
+
true
true
true
true
-
+
true
true
true
true
-
+
true
true
true
true
-
+
true
true
true
true
-
+
true
true
true
true
-
+
true
true
true
true
-
+
+ true
+ true
+ true
+ true
+
+
true
true
true
@@ -338,25 +344,25 @@
-
+
true
true
true
true
-
+
true
true
true
true
-
+
true
true
true
true
-
+
true
true
true
@@ -409,4 +415,4 @@
-
+
\ No newline at end of file
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index c0c03cd556..03ca3df852 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -111,30 +111,6 @@
MIPS\x86
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
MIPS\JitCommon
@@ -363,6 +339,33 @@
Ext\Snappy
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
@@ -413,18 +416,6 @@
MIPS\x86
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
-
- MIPS\ARM
-
MIPS\JitCommon
@@ -674,6 +665,18 @@
Ext\Snappy
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
+
+ MIPS\ARM
+
@@ -681,4 +684,4 @@
-
+
\ No newline at end of file
diff --git a/Core/MIPS/ARM/Asm.cpp b/Core/MIPS/ARM/ArmAsm.cpp
similarity index 65%
rename from Core/MIPS/ARM/Asm.cpp
rename to Core/MIPS/ARM/ArmAsm.cpp
index 9072857f8a..e93e755fae 100644
--- a/Core/MIPS/ARM/Asm.cpp
+++ b/Core/MIPS/ARM/ArmAsm.cpp
@@ -15,8 +15,8 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
-#include "ABI.h"
-#include
+#include "ArmEmitter.h"
+#include "ArmABI.h"
#include "../../MemMap.h"
@@ -24,11 +24,10 @@
#include "../../CoreTiming.h"
#include "MemoryUtil.h"
-#include "ABI.h"
-#include "Jit.h"
+#include "ArmJit.h"
#include "../JitCommon/JitCommon.h"
#include "../../Core.h"
-#include "Asm.h"
+#include "ArmAsm.h"
using namespace ArmGen;
@@ -72,24 +71,26 @@ void Jit()
void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit)
{
enterCode = AlignCode16();
- //ARMABI_PushAllCalleeSavedRegsAndAdjustStack();
-/*
-#ifndef _M_IX86
- // Two statically allocated registers.
- MOV(64, R(RBX), Imm64((u64)Memory::base));
- MOV(64, R(R15), Imm64((u64)jit->GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough
-#endif
- */
PUSH(8, R5, R6, R7, R8, R9, R10, R11, _LR);
SetCC(CC_AL);
- //ARMABI_MOVIMM32(R11, (u32)Memory::base);
- //ARMABI_MOVIMM32(R10, (u32)jit->GetBlockCache()->GetCodePointers());
+
+ // 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());
outerLoop = GetCodePtr();
//ARMABI_CallFunction(reinterpret_cast(&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);
+
dispatcher = GetCodePtr();
// The result of slice decrementation should be in flags if somebody jumped here
// IMPORTANT - We jump on negative, not carry!!!
@@ -127,65 +128,15 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit)
B(dispatcherNoCheck); // no point in special casing this
SetJumpTarget(bail);
- doTiming = GetCodePtr();
- testExternalExceptions = GetCodePtr();
- //TEST(32, M((void *)&mips->exceptions), Imm32(MIPSState::BREAKING_EXCEPTIONS));
- //FixupBranch noExtException = J_CC(CC_Z);
- //MOV(32, R(EAX), M(&mips->pc));
- // MOV(32, M(&NPC), R(EAX));
- // ABI_CallFunction(reinterpret_cast(&MIPSState::CheckExternalExceptions));
- //SetJumpTarget(noExtException);
+ SetJumpTarget(badCoreState);
//CMP(M((void*)&coreState), Imm8(0));
SetCC(CC_EQ);
//B(outerLoop);
SetCC(CC_AL);
- //Landing pad for drec space
- //ARMABI_PopAllCalleeSavedRegsAndAdjustStack();
- B(_LR);
+ //Landing pad for drec space
PUSH(8, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns
-
-
-
- GenerateCommon();
-}
-
-void AsmRoutineManager::GenerateCommon()
-{
- /*
- fifoDirectWrite8 = AlignCode4();
- GenFifoWrite(8);
- fifoDirectWrite16 = AlignCode4();
- GenFifoWrite(16);
- fifoDirectWrite32 = AlignCode4();
- GenFifoWrite(32);
- fifoDirectWriteFloat = AlignCode4();
- GenFifoFloatWrite();
- fifoDirectWriteXmm64 = AlignCode4();
- GenFifoXmm64Write();
-
- GenQuantizedLoads();
- GenQuantizedStores();
- GenQuantizedSingleStores();
- */
-
- //CMPSD(R(XMM0), M(&zero),
- // TODO
-
- // Fast write routines - special case the most common hardware write
- // TODO: use this.
- // Even in x86, the param values will be in the right registers.
- /*
- const u8 *fastMemWrite8 = AlignCode16();
- CMP(32, R(ABI_PARAM2), Imm32(0xCC008000));
- FixupBranch skip_fast_write = J_CC(CC_NE, false);
- MOV(32, EAX, M(&m_gatherPipeCount));
- MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1);
- ADD(32, 1, M(&m_gatherPipeCount));
- RET();
- SetJumpTarget(skip_fast_write);
- CALL((void *)&Memory::Write_U8);*/
-}
+}
\ No newline at end of file
diff --git a/Core/MIPS/ARM/Asm.h b/Core/MIPS/ARM/ArmAsm.h
similarity index 62%
rename from Core/MIPS/ARM/Asm.h
rename to Core/MIPS/ARM/ArmAsm.h
index 481e46374b..459582452e 100644
--- a/Core/MIPS/ARM/Asm.h
+++ b/Core/MIPS/ARM/ArmAsm.h
@@ -21,19 +21,7 @@
#include
#include "../MIPS.h"
-// In PPSSPP, we don't use inline assembly. Instead, we generate all machine-near
-// code at runtime. In the case of fixed code like this, after writing it, we write
-// protect the memory, essentially making it work just like precompiled code.
-
-// There are some advantages to this approach:
-// 1) No need to setup an external assembler in the build.
-// 2) Cross platform, as long as it's x86/x64.
-// 3) Can optimize code at runtime for the specific CPU model.
-// There aren't really any disadvantages other than having to maintain code emitters,
-// which we have to do anyway :)
-//
-// To add a new asm routine, just add another const here, and add the code to Generate.
-// Also, possibly increase the size of the code buffer.
+// Runtime generated assembly routines, like the Dispatcher.
namespace MIPSComp
{
@@ -65,14 +53,10 @@ public:
const u8 *enterCode;
const u8 *outerLoop;
+ const u8 *dispatcherCheckCoreState;
const u8 *dispatcher;
const u8 *dispatcherNoCheck;
const u8 *dispatcherPcInR0;
-
- const u8 *fpException;
- const u8 *testExceptions;
- const u8 *testExternalExceptions;
- const u8 *doTiming;
};
#endif // _JIT64ASM_H
diff --git a/Core/MIPS/ARM/CompALU.cpp b/Core/MIPS/ARM/ArmCompALU.cpp
similarity index 99%
rename from Core/MIPS/ARM/CompALU.cpp
rename to Core/MIPS/ARM/ArmCompALU.cpp
index 5560da52e4..459e5effa9 100644
--- a/Core/MIPS/ARM/CompALU.cpp
+++ b/Core/MIPS/ARM/ArmCompALU.cpp
@@ -15,9 +15,9 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
-#include "Jit.h"
-#include "RegCache.h"
-#include
+#include "ArmJit.h"
+#include "ArmRegCache.h"
+#include "ArmEmitter.h"
using namespace MIPSAnalyst;
#define _RS ((op>>21) & 0x1F)
diff --git a/Core/MIPS/ARM/CompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp
similarity index 98%
rename from Core/MIPS/ARM/CompBranch.cpp
rename to Core/MIPS/ARM/ArmCompBranch.cpp
index cdcb257f4e..750589b654 100644
--- a/Core/MIPS/ARM/CompBranch.cpp
+++ b/Core/MIPS/ARM/ArmCompBranch.cpp
@@ -21,9 +21,9 @@
#include "../MIPSAnalyst.h"
#include "../MIPSTables.h"
-#include "Jit.h"
-#include "RegCache.h"
-#include "JitCache.h"
+#include "ArmJit.h"
+#include "ArmRegCache.h"
+#include "ArmJitCache.h"
#include
#define _RS ((op>>21) & 0x1F)
@@ -209,9 +209,9 @@ void Jit::BranchFPFlag(u32 op, ArmGen::CCFlags cc, bool likely)
}
FlushAll();
- ARMABI_MOVI2R(R0, (u32)&(mips_->fpcond));
+ ARMABI_MOVI2R(R0, (u32)&(mips_->fcr31));
LDR(R0, R0, Operand2(0, TYPE_IMM));
- TST(R0, Operand2(1, TYPE_IMM));
+ TST(R0, Operand2(1 << 23, TYPE_IMM));
ArmGen::FixupBranch ptr;
js.inDelaySlot = true;
if (!likely)
diff --git a/Core/MIPS/ARM/CompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp
similarity index 99%
rename from Core/MIPS/ARM/CompFPU.cpp
rename to Core/MIPS/ARM/ArmCompFPU.cpp
index 0ed608eac2..d008d2308b 100644
--- a/Core/MIPS/ARM/CompFPU.cpp
+++ b/Core/MIPS/ARM/ArmCompFPU.cpp
@@ -16,8 +16,8 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "../MIPS.h"
-#include "Jit.h"
-#include "RegCache.h"
+#include "ArmJit.h"
+#include "ArmRegCache.h"
#define _RS ((op>>21) & 0x1F)
#define _RT ((op>>16) & 0x1F)
diff --git a/Core/MIPS/ARM/CompLoadStore.cpp b/Core/MIPS/ARM/ArmCompLoadStore.cpp
similarity index 98%
rename from Core/MIPS/ARM/CompLoadStore.cpp
rename to Core/MIPS/ARM/ArmCompLoadStore.cpp
index e8d8430447..fd458240f0 100644
--- a/Core/MIPS/ARM/CompLoadStore.cpp
+++ b/Core/MIPS/ARM/ArmCompLoadStore.cpp
@@ -17,8 +17,8 @@
#include "../../MemMap.h"
#include "../MIPSAnalyst.h"
-#include "Jit.h"
-#include "RegCache.h"
+#include "ArmJit.h"
+#include "ArmRegCache.h"
#define _RS ((op>>21) & 0x1F)
diff --git a/Core/MIPS/ARM/CompVFPU.cpp b/Core/MIPS/ARM/ArmCompVFPU.cpp
similarity index 87%
rename from Core/MIPS/ARM/CompVFPU.cpp
rename to Core/MIPS/ARM/ArmCompVFPU.cpp
index 7abf7a19af..b434446b68 100644
--- a/Core/MIPS/ARM/CompVFPU.cpp
+++ b/Core/MIPS/ARM/ArmCompVFPU.cpp
@@ -1,8 +1,8 @@
#include "../../MemMap.h"
#include "../MIPSAnalyst.h"
-#include "Jit.h"
-#include "RegCache.h"
+#include "ArmJit.h"
+#include "ArmRegCache.h"
#define _RS ((op>>21) & 0x1F)
diff --git a/Core/MIPS/ARM/Jit.cpp b/Core/MIPS/ARM/ArmJit.cpp
similarity index 86%
rename from Core/MIPS/ARM/Jit.cpp
rename to Core/MIPS/ARM/ArmJit.cpp
index d3c33f61c7..9dc526d59d 100644
--- a/Core/MIPS/ARM/Jit.cpp
+++ b/Core/MIPS/ARM/ArmJit.cpp
@@ -22,11 +22,8 @@
#include "../MIPSInt.h"
#include "../MIPSTables.h"
-#include "RegCache.h"
-#include "Jit.h"
-
-
-extern u32 *pspmainram;
+#include "ArmRegCache.h"
+#include "ArmJit.h"
namespace MIPSComp
{
@@ -74,7 +71,7 @@ Jit::Jit(MIPSState *mips) : blocks(mips), gpr(mips), mips_(mips)
void Jit::FlushAll()
{
- gpr.Flush();
+ gpr.FlushAll();
//fpr.Flush(FLUSH_ALL);
}
@@ -100,7 +97,7 @@ void Jit::Compile(u32 em_address)
}
int block_num = blocks.AllocateBlock(em_address);
- JitBlock *b = blocks.GetBlock(block_num);
+ ArmJitBlock *b = blocks.GetBlock(block_num);
blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, b));
}
@@ -110,7 +107,7 @@ void Jit::RunLoopUntil(u64 globalticks)
((void (*)())asm_.enterCode)();
}
-const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
+const u8 *Jit::DoJit(u32 em_address, ArmJitBlock *b)
{
js.cancel = false;
js.blockStart = js.compilerPC = mips_->pc;
@@ -166,42 +163,35 @@ void Jit::Comp_Generic(u32 op)
void Jit::DoDownCount()
{
- ARMReg A = gpr.GetReg();
- ARMReg B = gpr.GetReg();
- ARMABI_MOVI2R(A, Mem(&CoreTiming::downcount));
- LDR(B, A);
+ ARMABI_MOVI2R(R0, Mem(&CoreTiming::downcount));
+ LDR(R1, R0);
if(js.downcountAmount < 255) // We can enlarge this if we used rotations
{
- SUBS(B, B, js.downcountAmount);
- STR(A, B);
+ SUBS(R1, R1, js.downcountAmount);
+ STR(R0, R1);
+ } else {
+ // Should be fine to use R2 here, flushed the regcache anyway.
+ // If js.downcountAmount can be expressed as an Imm8, we don't need this anyway.
+ ARMABI_MOVI2R(R2, js.downcountAmount);
+ SUBS(R1, R1, R2);
+ STR(R0, R1);
}
- else
- {
- ARMReg C = gpr.GetReg(false);
- ARMABI_MOVI2R(C, js.downcountAmount);
- SUBS(B, B, C);
- STR(A, B);
- }
- gpr.Unlock(A, B);
}
void Jit::WriteExitDestInR(ARMReg Reg)
{
- ARMReg A = gpr.GetReg();
- ARMABI_MOVI2R(A, (u32)&mips_->pc);
- STR(A, Reg);
- gpr.Unlock(Reg); // This was locked in the instruction beforehand.
+ ARMABI_MOVI2R(R0, (u32)&mips_->pc);
+ STR(R0, Reg);
DoDownCount();
- ARMABI_MOVI2R(A, (u32)asm_.dispatcher);
- B(A);
- gpr.Unlock(A);
+ ARMABI_MOVI2R(R0, (u32)asm_.dispatcher);
+ B(R0);
}
void Jit::WriteExit(u32 destination, int exit_num)
{
DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done)
- JitBlock *b = js.curBlock;
+ ArmJitBlock *b = js.curBlock;
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
@@ -218,9 +208,8 @@ void Jit::WriteExit(u32 destination, int exit_num)
ARMABI_MOVI2R(R0, (u32)&mips_->pc); // Watch out! This uses R14 and R12!
ARMABI_MOVI2R(R1, destination); // Watch out! This uses R14 and R12!
STR(R0, R1); // Watch out! This uses R14 and R12!
- ARMReg A = gpr.GetReg(false);
- ARMABI_MOVI2R(A, (u32)asm_.dispatcher);
- B(A);
+ ARMABI_MOVI2R(R0, (u32)asm_.dispatcher);
+ B(R0);
}
}
diff --git a/Core/MIPS/ARM/Jit.h b/Core/MIPS/ARM/ArmJit.h
similarity index 89%
rename from Core/MIPS/ARM/Jit.h
rename to Core/MIPS/ARM/ArmJit.h
index 60e91a43cf..8d9f1de9ee 100644
--- a/Core/MIPS/ARM/Jit.h
+++ b/Core/MIPS/ARM/ArmJit.h
@@ -18,23 +18,18 @@
#pragma once
#include "../../../Globals.h"
-#include "Asm.h"
-
-#if !defined(ARM)
-#error DO NOT BUILD ARM JIT ON NON-ARM
-#endif
-
+#include "ArmAsm.h"
#include
-#include "JitCache.h"
-#include "RegCache.h"
+#include "ArmJitCache.h"
+#include "ArmRegCache.h"
namespace MIPSComp
{
-struct JitOptions
+struct ArmJitOptions
{
- JitOptions()
+ ArmJitOptions()
{
enableBlocklink = false;
}
@@ -42,7 +37,7 @@ struct JitOptions
bool enableBlocklink;
};
-struct JitState
+struct ArmJitState
{
u32 compilerPC;
u32 blockStart;
@@ -50,7 +45,7 @@ struct JitState
bool inDelaySlot;
int downcountAmount;
bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block
- JitBlock *curBlock;
+ ArmJitBlock *curBlock;
};
class Jit : public ArmGen::ARMXCodeBlock
@@ -66,7 +61,7 @@ public:
void RunLoopUntil(u64 globalticks);
void Compile(u32 em_address); // Compiles a block at current MIPS PC
- const u8 *DoJit(u32 em_address, JitBlock *b);
+ const u8 *DoJit(u32 em_address, ArmJitBlock *b);
void CompileAt(u32 addr);
void Comp_RunBlock(u32 op);
@@ -92,7 +87,7 @@ public:
void Comp_FPU2op(u32 op);
void Comp_mxc1(u32 op);
- JitBlockCache *GetBlockCache() { return &blocks; }
+ ArmJitBlockCache *GetBlockCache() { return &blocks; }
AsmRoutineManager &Asm() { return asm_; }
void ClearCache();
@@ -121,9 +116,9 @@ private:
void CompFPTriArith(u32 op, void (XEmitter::*arith)(X64Reg reg, OpArg), bool orderMatters);
*/
- JitBlockCache blocks;
- JitOptions jo;
- JitState js;
+ ArmJitBlockCache blocks;
+ ArmJitOptions jo;
+ ArmJitState js;
ArmRegCache gpr;
// FPURegCache fpr;
diff --git a/Core/MIPS/ARM/JitCache.cpp b/Core/MIPS/ARM/ArmJitCache.cpp
similarity index 84%
rename from Core/MIPS/ARM/JitCache.cpp
rename to Core/MIPS/ARM/ArmJitCache.cpp
index 68a5aa5d3c..7c7b2c76f5 100644
--- a/Core/MIPS/ARM/JitCache.cpp
+++ b/Core/MIPS/ARM/ArmJitCache.cpp
@@ -29,12 +29,11 @@
#include "../MIPSTables.h"
#include "../MIPSAnalyst.h"
-#include "JitCache.h"
-#include "../JitCommon/JitCommon.h"
-#include "Asm.h"
-// #include "JitBase.h"
+#include "ArmEmitter.h"
-#include
+#include "ArmJitCache.h"
+#include "../JitCommon/JitCommon.h"
+#include "ArmAsm.h"
#if defined USE_OPROFILE && USE_OPROFILE
#include
@@ -52,30 +51,30 @@ using namespace ArmGen;
#define INVALID_EXIT 0xFFFFFFFF
-bool JitBlock::ContainsAddress(u32 em_address)
+bool ArmJitBlock::ContainsAddress(u32 em_address)
{
// WARNING - THIS DOES NOT WORK WITH INLINING ENABLED.
return (em_address >= originalAddress && em_address < originalAddress + 4 * originalSize);
}
-bool JitBlockCache::IsFull() const
+bool ArmJitBlockCache::IsFull() const
{
return GetNumBlocks() >= MAX_NUM_BLOCKS - 1;
}
-void JitBlockCache::Init()
+void ArmJitBlockCache::Init()
{
MAX_NUM_BLOCKS = 65536*2;
#if defined USE_OPROFILE && USE_OPROFILE
agent = op_open_agent();
#endif
- blocks = new JitBlock[MAX_NUM_BLOCKS];
+ blocks = new ArmJitBlock[MAX_NUM_BLOCKS];
blockCodePointers = new const u8*[MAX_NUM_BLOCKS];
Clear();
}
-void JitBlockCache::Shutdown()
+void ArmJitBlockCache::Shutdown()
{
delete[] blocks;
delete[] blockCodePointers;
@@ -91,7 +90,7 @@ void JitBlockCache::Shutdown()
#endif
}
-JitBlockCache::~JitBlockCache()
+ArmJitBlockCache::~ArmJitBlockCache()
{
Shutdown();
}
@@ -99,7 +98,7 @@ JitBlockCache::~JitBlockCache()
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
// is full and when saving and loading states.
-void JitBlockCache::Clear()
+void ArmJitBlockCache::Clear()
{
for (int i = 0; i < num_blocks; i++)
{
@@ -111,7 +110,7 @@ void JitBlockCache::Clear()
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
}
-void JitBlockCache::ClearSafe()
+void ArmJitBlockCache::ClearSafe()
{
#ifdef JIT_UNLIMITED_ICACHE
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
@@ -129,23 +128,23 @@ void JitBlockCache::ClearSafe()
}
}*/
-void JitBlockCache::Reset()
+void ArmJitBlockCache::Reset()
{
Shutdown();
Init();
}
-JitBlock *JitBlockCache::GetBlock(int no)
+ArmJitBlock *ArmJitBlockCache::GetBlock(int no)
{
return &blocks[no];
}
-int JitBlockCache::GetNumBlocks() const
+int ArmJitBlockCache::GetNumBlocks() const
{
return num_blocks;
}
-bool JitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const
+bool ArmJitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const
{
// check if any endpoint is inside the other range
if ((s1 >= s2 && s1 <= e2) ||
@@ -157,9 +156,9 @@ bool JitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const
return false;
}
-int JitBlockCache::AllocateBlock(u32 em_address)
+int ArmJitBlockCache::AllocateBlock(u32 em_address)
{
- JitBlock &b = blocks[num_blocks];
+ ArmJitBlock &b = blocks[num_blocks];
b.invalid = false;
b.originalAddress = em_address;
b.exitAddress[0] = INVALID_EXIT;
@@ -173,10 +172,10 @@ int JitBlockCache::AllocateBlock(u32 em_address)
return num_blocks - 1;
}
-void JitBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr)
+void ArmJitBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr)
{
blockCodePointers[block_num] = code_ptr;
- JitBlock &b = blocks[block_num];
+ ArmJitBlock &b = blocks[block_num];
b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress);
u32 opcode = MIPS_MAKE_EMUHACK(0, block_num);
@@ -222,12 +221,12 @@ void JitBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code
#endif
}
-const u8 **JitBlockCache::GetCodePointers()
+const u8 **ArmJitBlockCache::GetCodePointers()
{
return blockCodePointers;
}
-int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
+int ArmJitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
{
if (!blocks)
return -1;
@@ -242,14 +241,14 @@ int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
return bl;
}
-void JitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers)
+void ArmJitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers)
{
for (int i = 0; i < num_blocks; i++)
if (blocks[i].ContainsAddress(em_address))
block_numbers->push_back(i);
}
-u32 JitBlockCache::GetOriginalFirstOp(int block_num)
+u32 ArmJitBlockCache::GetOriginalFirstOp(int block_num)
{
if (block_num >= num_blocks)
{
@@ -259,12 +258,12 @@ u32 JitBlockCache::GetOriginalFirstOp(int block_num)
return blocks[block_num].originalFirstOpcode;
}
-CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int block_num)
+CompiledCode ArmJitBlockCache::GetCompiledCodeFromBlock(int block_num)
{
return (CompiledCode)blockCodePointers[block_num];
}
-std::string JitBlockCache::GetCompiledDisassembly(int block_num)
+std::string ArmJitBlockCache::GetCompiledDisassembly(int block_num)
{
/*
std::string buf;
@@ -287,9 +286,9 @@ std::string JitBlockCache::GetCompiledDisassembly(int block_num)
//Can be faster by doing a queue for blocks to link up, and only process those
//Should probably be done
-void JitBlockCache::LinkBlockExits(int i)
+void ArmJitBlockCache::LinkBlockExits(int i)
{
- JitBlock &b = blocks[i];
+ ArmJitBlock &b = blocks[i];
if (b.invalid)
{
// This block is dead. Don't relink it.
@@ -312,10 +311,10 @@ void JitBlockCache::LinkBlockExits(int i)
using namespace std;
-void JitBlockCache::LinkBlock(int i)
+void ArmJitBlockCache::LinkBlock(int i)
{
LinkBlockExits(i);
- JitBlock &b = blocks[i];
+ ArmJitBlock &b = blocks[i];
std::map::iterator iter;
pair::iterator, multimap::iterator> ppp;
// equal_range(b) returns pair representing the range
@@ -329,16 +328,16 @@ void JitBlockCache::LinkBlock(int i)
}
}
-void JitBlockCache::UnlinkBlock(int i)
+void ArmJitBlockCache::UnlinkBlock(int i)
{
- JitBlock &b = blocks[i];
+ ArmJitBlock &b = blocks[i];
std::map::iterator iter;
pair::iterator, multimap::iterator> ppp;
ppp = links_to.equal_range(b.originalAddress);
if (ppp.first == ppp.second)
return;
for (multimap::iterator iter2 = ppp.first; iter2 != ppp.second; ++iter2) {
- JitBlock &sourceBlock = blocks[iter2->second];
+ ArmJitBlock &sourceBlock = blocks[iter2->second];
for (int e = 0; e < 2; e++)
{
if (sourceBlock.exitAddress[e] == b.originalAddress)
@@ -347,14 +346,14 @@ void JitBlockCache::UnlinkBlock(int i)
}
}
-void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
+void ArmJitBlockCache::DestroyBlock(int block_num, bool invalidate)
{
if (block_num < 0 || block_num >= num_blocks)
{
ERROR_LOG(JIT, "DestroyBlock: Invalid block number %d", block_num);
return;
}
- JitBlock &b = blocks[block_num];
+ ArmJitBlock &b = blocks[block_num];
if (b.invalid)
{
if (invalidate)
@@ -382,7 +381,7 @@ void JitBlockCache::DestroyBlock(int block_num, bool invalidate)
*/
}
-void JitBlockCache::InvalidateICache(u32 address, const u32 length)
+void ArmJitBlockCache::InvalidateICache(u32 address, const u32 length)
{
// Convert the logical address to a physical address for the block map
u32 pAddr = address & 0x1FFFFFFF;
diff --git a/Core/MIPS/ARM/JitCache.h b/Core/MIPS/ARM/ArmJitCache.h
similarity index 95%
rename from Core/MIPS/ARM/JitCache.h
rename to Core/MIPS/ARM/ArmJitCache.h
index ae38f06e6a..d464417115 100644
--- a/Core/MIPS/ARM/JitCache.h
+++ b/Core/MIPS/ARM/ArmJitCache.h
@@ -22,7 +22,7 @@
#include
#include "../MIPSAnalyst.h"
-
+#include "../MIPS.h"
// Define this in order to get VTune profile support for the Jit generated code.
// Add the VTune include/lib directories to the project directories to get this to build.
// #define USE_VTUNE
@@ -42,7 +42,7 @@
#define JIT_OPCODE 0xFFCCCCCC // yeah this ain't gonna work
-struct JitBlock
+struct ArmJitBlock
{
const u8 *checkedEntry;
const u8 *normalEntry;
@@ -77,11 +77,11 @@ struct JitBlock
typedef void (*CompiledCode)();
-class JitBlockCache
+class ArmJitBlockCache
{
MIPSState *mips;
const u8 **blockCodePointers;
- JitBlock *blocks;
+ ArmJitBlock *blocks;
int num_blocks;
std::multimap links_to;
std::map, u32> block_map; // (end_addr, start_addr) -> number
@@ -94,10 +94,10 @@ class JitBlockCache
void UnlinkBlock(int i);
public:
- JitBlockCache(MIPSState *mips_) :
+ ArmJitBlockCache(MIPSState *mips_) :
mips(mips_), blockCodePointers(0), blocks(0), num_blocks(0),
MAX_NUM_BLOCKS(0) { }
- ~JitBlockCache();
+ ~ArmJitBlockCache();
int AllocateBlock(u32 em_address);
void FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr);
@@ -110,7 +110,7 @@ public:
bool IsFull() const;
// Code Cache
- JitBlock *GetBlock(int block_num);
+ ArmJitBlock *GetBlock(int block_num);
int GetNumBlocks() const;
const u8 **GetCodePointers();
diff --git a/Core/MIPS/ARM/ArmRegCache.cpp b/Core/MIPS/ARM/ArmRegCache.cpp
new file mode 100644
index 0000000000..83037335df
--- /dev/null
+++ b/Core/MIPS/ARM/ArmRegCache.cpp
@@ -0,0 +1,189 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "ArmABI.h"
+#include "ArmRegCache.h"
+#include "ArmEmitter.h"
+
+using namespace ArmGen;
+
+#define CTXREG ((ARMReg)14)
+
+ArmRegCache::ArmRegCache(MIPSState *mips) : mips_(mips) {
+}
+
+void ArmRegCache::Init(ARMXEmitter *emitter) {
+ emit = emitter;
+}
+
+void ArmRegCache::Start(MIPSAnalyst::AnalysisResults &stats) {
+ for (int i = 0; i < 16; i++) {
+ ar[i].mipsReg = -1;
+ ar[i].spillLock = false;
+ ar[i].allocLock = false;
+ ar[i].isDirty = false;
+ }
+ for (int i = 0; i < 32; i++) {
+ mr[i].loc = ML_MEM;
+ }
+}
+
+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
+ };
+ count = sizeof(allocationOrder) / sizeof(const int);
+ return allocationOrder;
+}
+
+ARMReg ArmRegCache::MapReg(MIPSReg mipsReg, int mapFlags) {
+ // Let's see if it's already mapped.
+ for (int i = 0; i < NUM_ARMREG; i++) {
+ if (ar[i].mipsReg == mipsReg) {
+ // Already mapped, no need to do anything more.
+ return (ARMReg)i;
+ }
+ }
+
+ // Okay, so we need to allocate one.
+
+ int allocCount;
+ const ARMReg *allocOrder = GetMIPSAllocationOrder(allocCount);
+
+allocate:
+ for (int i = 0; i < allocCount; i++) {
+ int reg = allocOrder[i];
+
+ if (ar[reg].mipsReg == -1 && !ar[reg].allocLock) {
+ // That means it's free. Grab it, and load the value into it (if requested).
+ ar[reg].mipsReg = mipsReg;
+ ar[reg].isDirty = (mapFlags & MAP_DIRTY) ? true : false;
+ if (mapFlags & MAP_INITVAL) {
+ if (mr[mipsReg].loc == ML_MEM)
+ emit->LDR((ARMReg)reg, CTXREG, 4 * mipsReg);
+ else if (mr[mipsReg].loc == ML_IMM)
+ emit->ARMABI_MOVI2R((ARMReg)reg, mr[mipsReg].imm);
+ }
+ return (ARMReg)reg;
+ }
+ }
+
+ // Still nothing. Let's spill a reg and goto 10
+
+ for (int i = 0; i < allocCount; i++) {
+ if (ar[i].spillLock || ar[i].allocLock)
+ continue;
+ FlushArmReg((ARMReg)i);
+ goto allocate;
+ }
+
+ // Uh oh, we have all them alloclocked and spilllocked....
+ _assert_msg_(JIT, false, "All available registers are locked dumb dumb");
+ return INVALID_REG;
+}
+
+void ArmRegCache::FlushArmReg(ARMReg r) {
+ if (ar[r].mipsReg == -1) {
+ // Nothing to do
+ return;
+ }
+ if (ar[r].isDirty) {
+ if (mr[ar[r].mipsReg].loc == ML_MEM)
+ emit->STR(r, CTXREG, 4 * ar[r].mipsReg);
+ }
+}
+
+void ArmRegCache::FlushMipsReg(MIPSReg r) {
+ switch (mr[r].loc) {
+ case ML_IMM:
+ // IMM is always "dirty".
+ emit->ARMABI_MOVI2R(R0, mr[r].imm);
+ emit->STR(R0, CTXREG, GetMipsRegOffset(r));
+ break;
+
+ case ML_ARMREG:
+ if (ar[mr[r].reg].isDirty)
+ emit->STR(mr[r].reg, CTXREG, GetMipsRegOffset(r));
+ ar[mr[r].reg].mipsReg = -1;
+ ar[mr[r].reg].isDirty = false;
+ break;
+
+ default:
+ //BAD
+ break;
+ }
+ mr[r].loc = ML_MEM;
+}
+
+void ArmRegCache::FlushAll() {
+ for (int i = 0; i < NUM_MIPSREG; i++) {
+ FlushMipsReg(i);
+ }
+}
+
+void ArmRegCache::SetImm(MIPSReg r, u32 immVal) {
+ // Zap existing value
+ if (mr[r].loc == ML_ARMREG)
+ ar[mr[r].reg].mipsReg = -1;
+ mr[r].loc = ML_IMM;
+ mr[r].imm = immVal;
+}
+
+bool ArmRegCache::IsImm(MIPSReg r) const {
+ return mr[r].loc == ML_IMM;
+}
+
+u32 ArmRegCache::GetImm(MIPSReg r) const {
+ // TODO: Check.
+ return mr[r].imm;
+}
+
+int ArmRegCache::GetMipsRegOffset(MIPSReg r) {
+ if (r < 32)
+ return r * 4;
+ switch (r) {
+ case MIPSREG_HI:
+ return offsetof(MIPSState, hi);
+ case MIPSREG_LO:
+ return offsetof(MIPSState, lo);
+ }
+ _dbg_assert_msg_(JIT, false, "bad mips register %i", (int)r);
+ return -999; // boom!
+}
+
+void ArmRegCache::SpillLock(MIPSReg r1, MIPSReg r2, MIPSReg r3) {
+ if (mr[r1].loc == ML_ARMREG) ar[mr[r1].reg].spillLock = true;
+ if (r2 != -1 && mr[r2].loc == ML_ARMREG) ar[mr[r2].reg].spillLock = true;
+ if (r3 != -1 && mr[r3].loc == ML_ARMREG) ar[mr[r3].reg].spillLock = true;
+}
+
+void ArmRegCache::ReleaseSpillLocks() {
+ for (int i = 0; i < 16; i++) {
+ ar[i].spillLock = false;
+ }
+}
+
+ARMReg ArmRegCache::R(int mipsReg) {
+ if (mr[mipsReg].loc == ML_ARMREG) {
+ return mr[mipsReg].reg;
+ } else {
+ _dbg_assert_msg_(JIT, false, "R: not mapped");
+ return INVALID_REG; // BAAAD
+ }
+}
+
diff --git a/Core/MIPS/ARM/ArmRegCache.h b/Core/MIPS/ARM/ArmRegCache.h
new file mode 100644
index 0000000000..dfbcf2b4da
--- /dev/null
+++ b/Core/MIPS/ARM/ArmRegCache.h
@@ -0,0 +1,112 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#pragma once
+
+#include "ArmEmitter.h"
+#include "../MIPS.h"
+#include "../MIPSAnalyst.h"
+#include "ArmABI.h"
+
+using namespace ArmGen;
+
+// R2 to R9: mapped MIPS regs
+// R11 = base pointer
+// R12 = MIPS context
+// R14 = code pointers
+
+// Special MIPS registers:
+enum {
+ MIPSREG_HI = 32,
+ MIPSREG_LO = 33,
+ TOTAL_MAPPABLE_MIPSREGS = 34,
+};
+
+typedef int MIPSReg;
+
+struct RegARM {
+ int mipsReg; // if -1, no mipsreg attached.
+ bool isDirty; // Should the register be written back?
+ bool allocLock; // if true, this ARM register cannot be used for allocation.
+ bool spillLock; // if true, this register cannot be spilled.
+};
+
+enum RegMIPSLoc {
+ ML_IMM,
+ ML_ARMREG,
+ ML_MEM,
+};
+
+struct RegMIPS {
+ // Where is this MIPS register?
+ RegMIPSLoc loc;
+ // Data (only one of these is used, depending on loc. Could make a union).
+ u32 imm;
+ ARMReg reg;
+ // If loc == ML_MEM, it's back in its location in the CPU context struct.
+};
+
+enum {
+ MAP_DIRTY = 1,
+ MAP_INITVAL = 2,
+};
+
+class ArmRegCache
+{
+public:
+ ArmRegCache(MIPSState *mips);
+ ~ArmRegCache() {}
+
+ void Init(ARMXEmitter *emitter);
+ void Start(MIPSAnalyst::AnalysisResults &stats);
+
+ // void AllocLock(ARMReg reg, ARMReg reg2 = INVALID_REG, ARMReg reg3 = INVALID_REG);
+ // void ReleaseAllocLock(ARMReg reg);
+
+ // Protect the arm register containing a MIPS register from spilling, to ensure that
+ // it's being kept allocated.
+ void SpillLock(MIPSReg reg, MIPSReg reg2 = -1, MIPSReg reg3 = -1);
+ void ReleaseSpillLocks();
+
+ void SetImm(MIPSReg reg, u32 immVal);
+ bool IsImm(MIPSReg reg) const;
+ u32 GetImm(MIPSReg reg) const;
+
+ // Returns an ARM register containing the requested MIPS register.
+ ARMReg MapReg(MIPSReg reg, int mapFlags = 0);
+ void FlushArmReg(ARMReg r);
+ void FlushMipsReg(MIPSReg r);
+
+ void FlushAll();
+
+ ARMReg R(int preg); // Returns a cached register
+
+ void SetEmitter(ARMXEmitter *emitter) { emit = emitter; }
+
+private:
+ int GetMipsRegOffset(MIPSReg r);
+ MIPSState *mips_;
+ ARMXEmitter *emit;
+
+ enum {
+ NUM_ARMREG = 16,
+ NUM_MIPSREG = TOTAL_MAPPABLE_MIPSREGS,
+ };
+
+ RegARM ar[16];
+ RegMIPS mr[32];
+};
diff --git a/Core/MIPS/ARM/RegCache.cpp b/Core/MIPS/ARM/RegCache.cpp
deleted file mode 100644
index 80ec9ec8f3..0000000000
--- a/Core/MIPS/ARM/RegCache.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright (C) 2003 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include "RegCache.h"
-#include "ArmEmitter.h"
-
-using namespace ArmGen;
-
-/*
-// these are MIPS reg indices
-void RegCache::Lock(int p1, int p2, int p3, int p4)
-{
- locks[p1] = true;
- if (p2 != 0xFF) locks[p2] = true;
- if (p3 != 0xFF) locks[p3] = true;
- if (p4 != 0xFF) locks[p4] = true;
-}
-
-// these are x64 reg indices
-void RegCache::LockX(int x1, int x2, int x3, int x4)
-{
- if (xlocks[x1]) {
- PanicAlert("RegCache: x %i already locked!", x1);
- }
- xlocks[x1] = true;
- if (x2 != 0xFF) xlocks[x2] = true;
- if (x3 != 0xFF) xlocks[x3] = true;
- if (x4 != 0xFF) xlocks[x4] = true;
-}
-
-bool RegCache::IsFreeX(int xreg) const
-{
- return xregs[xreg].free && !xlocks[xreg];
-}
-
-void RegCache::UnlockAll()
-{
- for (int i = 0; i < 32; i++)
- locks[i] = false;
-}
-*/
-
-ArmRegCache::ArmRegCache(MIPSState *mips)
- : mips_(mips)
-{
- emit = 0;
-
-}
-
-void ArmRegCache::Init(ARMXEmitter *emitter)
-{
- emit = emitter;
- ARMReg *PPCRegs = GetMIPSAllocationOrder(NUMMIPSREG);
- ARMReg *Regs = GetAllocationOrder(NUMARMREG);
- for(int a = 0; a < 32; ++a)
- {
- // This gives us the memory locations of the gpr registers so we can
- // load them.
- regs[a].location = (u8*)&mips_->r[a];
- }
- for(int a = 0; a < NUMMIPSREG; ++a)
- {
- ArmCRegs[a].MIPSReg = 33;
- ArmCRegs[a].Reg = PPCRegs[a];
- ArmCRegs[a].LastLoad = 0;
- }
- for(int a = 0; a < NUMARMREG; ++a)
- {
- ArmRegs[a].Reg = Regs[a];
- ArmRegs[a].free = true;
- }
-}
-
-void ArmRegCache::Start(MIPSAnalyst::AnalysisResults &stats)
-{
- for(int a = 0; a < NUMMIPSREG; ++a)
- {
- ArmCRegs[a].MIPSReg = 33;
- ArmCRegs[a].LastLoad = 0;
- }
-}
-
-ARMReg *ArmRegCache::GetMIPSAllocationOrder(int &count)
-{
- // This will return us the allocation order of the registers we can use on
- // the MIPS side.
- static ARMReg allocationOrder[] =
- {
- R0, R1, R2, R3, R4, R5, R6, R7, R8, R9
- };
- count = sizeof(allocationOrder) / sizeof(const int);
- return allocationOrder;
-}
-ARMReg *ArmRegCache::GetAllocationOrder(int &count)
-{
- // This will return us the allocation order of the registers we can use on
- // the host side.
- static ARMReg allocationOrder[] =
- {
- R14, R12, R11, R10
- };
- count = sizeof(allocationOrder) / sizeof(const int);
- return allocationOrder;
-}
-
-ARMReg ArmRegCache::GetReg(bool AutoLock)
-{
- for (int a = 0; a < NUMARMREG; ++a)
- {
- if(ArmRegs[a].free)
- {
- // Alright, this one is free
- if (AutoLock)
- ArmRegs[a].free = false;
- return ArmRegs[a].Reg;
- }
- }
- // Uh Oh, we have all them locked....
- _assert_msg_(JIT, false, "All available registers are locked dumb dumb");
-}
-void ArmRegCache::Lock(ARMReg Reg)
-{
- for (int RegNum = 0; RegNum < NUMARMREG; ++RegNum)
- {
- if(ArmRegs[RegNum].Reg == Reg)
- {
- _assert_msg_(JIT, ArmRegs[RegNum].free, "This register is already locked");
- ArmRegs[RegNum].free = false;
- }
- }
- _assert_msg_(JIT, false, "Register %d can't be used with lock", Reg);
-}
-void ArmRegCache::Unlock(ARMReg R0, ARMReg R1, ARMReg R2, ARMReg R3)
-{
- for (int RegNum = 0; RegNum < NUMARMREG; ++RegNum)
- {
- if(ArmRegs[RegNum].Reg == R0)
- {
- _assert_msg_(JIT, !ArmRegs[RegNum].free, "This register is already unlocked");
- ArmRegs[RegNum].free = true;
- }
- if( R1 != INVALID_REG && ArmRegs[RegNum].Reg == R1) ArmRegs[RegNum].free = true;
- if( R2 != INVALID_REG && ArmRegs[RegNum].Reg == R2) ArmRegs[RegNum].free = true;
- if( R3 != INVALID_REG && ArmRegs[RegNum].Reg == R3) ArmRegs[RegNum].free = true;
- }
-}
-
-ARMReg ArmRegCache::R(int preg)
-{
- u32 HighestUsed = 0;
- u8 Num = 0;
- for (int a = 0; a < NUMMIPSREG; ++a){
- ++ArmCRegs[a].LastLoad;
- if (ArmCRegs[a].LastLoad > HighestUsed)
- {
- HighestUsed = ArmCRegs[a].LastLoad;
- Num = a;
- }
- }
- // Check if already Loaded
- for (int a = 0; a < NUMMIPSREG; ++a) {
- if (ArmCRegs[a].MIPSReg == preg)
- {
- ArmCRegs[a].LastLoad = 0;
- return ArmCRegs[a].Reg;
- }
- }
- // Check if we have a free register
- for (u8 a = 0; a < NUMMIPSREG; ++a)
- if (ArmCRegs[a].MIPSReg == 33)
- {
- emit->ARMABI_MOVI2R(ArmCRegs[a].Reg, (u32)&mips_->r);
- emit->LDR(ArmCRegs[a].Reg, ArmCRegs[a].Reg, preg * 4);
- ArmCRegs[a].MIPSReg = preg;
- ArmCRegs[a].LastLoad = 0;
- return ArmCRegs[a].Reg;
- }
- // Alright, we couldn't get a free space, dump that least used register
- // Note that this is incredibly dangerous if references to the register
- // are still floating around out there!
- ARMReg rA = GetReg(false);
- emit->ARMABI_MOVI2R(rA, (u32)&mips_->r);
- emit->STR(rA, ArmCRegs[Num].Reg, ArmCRegs[Num].MIPSReg * 4);
- emit->LDR(ArmCRegs[Num].Reg, rA, preg * 4);
- ArmCRegs[Num].MIPSReg = preg;
- ArmCRegs[Num].LastLoad = 0;
- return ArmCRegs[Num].Reg;
-}
-
-void ArmRegCache::Flush()
-{
- // Maybe we should keep this pointer around permanently?
- emit->MOVW(R14, (u32)&mips_->r);
- emit->MOVT(R14, (u32)&mips_->r, true);
-
- for (int a = 0; a < NUMMIPSREG; ++a) {
- if (ArmCRegs[a].MIPSReg != 33)
- {
- emit->STR(R14, ArmCRegs[a].Reg, ArmCRegs[a].MIPSReg * 4);
- ArmCRegs[a].MIPSReg = 33;
- ArmCRegs[a].LastLoad = 0;
- }
- }
-}
-
diff --git a/Core/MIPS/ARM/RegCache.h b/Core/MIPS/ARM/RegCache.h
deleted file mode 100644
index ab5d85c0ca..0000000000
--- a/Core/MIPS/ARM/RegCache.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (C) 2003 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#ifndef _JITARMREGCACHE_H
-#define _JITARMREGCACHE_H
-
-#include "ArmEmitter.h"
-#include "../MIPS.h"
-#include "../MIPSAnalyst.h"
-#include "ArmABI.h"
-
-using namespace ArmGen;
-
-// This ARM Register cache actually pre loads the most used registers before
-// the block to increase speed since every memory load requires two
-// instructions to load it. We are going to use R0-RMAX as registers for the
-// use of MIPS Registers.
-// Allocation order as follows
-#define ARMREGS 16
-// Allocate R0 to R9 for MIPS first.
-// For General registers on the host side, start with R14 and go down as we go
-// R13 is reserved for our stack pointer, don't ever use that. Unless you save
-// it
-// So we have R14, R12, R11, R10 to work with instructions
-
-struct MIPSCachedReg
-{
- const u8 *location;
-};
-
-struct JRCPPC
-{
- u32 MIPSReg; // Tied to which MIPS Register
- ARMReg Reg; // Tied to which ARM Register
- u32 LastLoad;
-};
-struct JRCReg
-{
- ARMReg Reg; // Which reg this is.
- bool free;
-};
-class ArmRegCache
-{
-private:
- MIPSCachedReg regs[32];
- JRCPPC ArmCRegs[ARMREGS];
- JRCReg ArmRegs[ARMREGS]; // Four registers remaining
-
- int NUMMIPSREG; // + LO, HI, ...
- int NUMARMREG;
-
- ARMReg *GetAllocationOrder(int &count);
- ARMReg *GetMIPSAllocationOrder(int &count);
-
- MIPSState *mips_;
-
-protected:
- ARMXEmitter *emit;
-
-public:
- ArmRegCache(MIPSState *mips);
- ~ArmRegCache() {}
-
- void Init(ARMXEmitter *emitter);
- void Start(MIPSAnalyst::AnalysisResults &stats);
-
- void SetEmitter(ARMXEmitter *emitter) {emit = emitter;}
-
- // TODO: Add a way to lock MIPS registers so they aren't kicked out when you don't expect it.
-
- ARMReg GetReg(bool AutoLock = true); // Return a ARM register we can use.
- void Lock(ARMReg R0);
- void Unlock(ARMReg R0, ARMReg R1 = INVALID_REG, ARMReg R2 = INVALID_REG, ARMReg R3 = INVALID_REG);
- void Flush();
- ARMReg R(int preg); // Returns a cached register
-
-};
-
-
-
-
-#endif
diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h
index a7b4673484..a8630e6fbe 100644
--- a/Core/MIPS/JitCommon/JitCommon.h
+++ b/Core/MIPS/JitCommon/JitCommon.h
@@ -18,7 +18,7 @@
#pragma once
#if defined(ARM)
-#include "../ARM/Jit.h"
+#include "../ARM/ArmJit.h"
#else
#include "../x86/Jit.h"
#endif
diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp
index d784419212..b7d89cd873 100644
--- a/Core/MIPS/MIPS.cpp
+++ b/Core/MIPS/MIPS.cpp
@@ -24,8 +24,8 @@
#include "../HLE/sceDisplay.h"
#if defined(ARM)
-#include "ARM/JitCache.h"
-#include "ARM/Jit.h"
+#include "ARM/ArmJitCache.h"
+#include "ARM/ArmJit.h"
#else
#include "x86/JitCache.h"
#include "x86/Jit.h"
@@ -40,7 +40,6 @@ MIPSDebugInterface *currentDebugMIPS = &debugr4k;
MIPSState::MIPSState()
{
- cpuType = CPUTYPE_ALLEGREX;
MIPSComp::jit = 0;
}
@@ -57,7 +56,7 @@ void MIPSState::Reset()
delete MIPSComp::jit;
MIPSComp::jit = 0;
}
-
+
if (PSP_CoreParameter().cpuCore == CPU_JIT)
MIPSComp::jit = new MIPSComp::Jit(this);
@@ -90,7 +89,6 @@ void MIPSState::Reset()
fcr0 = 0;
fcr31 = 0;
debugCount = 0;
- exceptions = 0;
currentMIPS = this;
inDelaySlot = false;
llBit = 0;
@@ -120,8 +118,6 @@ void MIPSState::DoState(PointerWrap &p)
rng.DoState(p);
p.Do(inDelaySlot);
p.Do(llBit);
- p.Do(cpuType);
- p.Do(exceptions);
p.Do(debugCount);
p.DoMarker("MIPSState");
}
diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h
index 1e8bd29a6f..92c440e606 100644
--- a/Core/MIPS/MIPS.h
+++ b/Core/MIPS/MIPS.h
@@ -124,22 +124,15 @@ public:
u32 hi;
u32 lo;
- u32 fpcond; //separate for speed - TODO: not worth it
-
u32 fcr0;
u32 fcr31; //fpu control register
+ u32 fpcond; // cache the cond flag of fcr31 (& 1 << 23)
GMRng rng; // VFPU hardware random number generator. Probably not the right type.
bool inDelaySlot;
int llBit; // ll/sc
- CPUType cpuType;
-
- // TODO: How do we handle exceptions?
- u32 exceptions;
- enum { BREAKING_EXCEPTIONS = 1 };
-
// Debug stuff
u32 debugCount; // can be used to count basic blocks before crashes, etc.
diff --git a/Core/MIPS/x86/Asm.cpp b/Core/MIPS/x86/Asm.cpp
index 08cfa7d0c0..715d8bef10 100644
--- a/Core/MIPS/x86/Asm.cpp
+++ b/Core/MIPS/x86/Asm.cpp
@@ -149,43 +149,4 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit)
//Landing pad for drec space
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
-
- GenerateCommon();
-}
-
-void AsmRoutineManager::GenerateCommon()
-{
- /*
- fifoDirectWrite8 = AlignCode4();
- GenFifoWrite(8);
- fifoDirectWrite16 = AlignCode4();
- GenFifoWrite(16);
- fifoDirectWrite32 = AlignCode4();
- GenFifoWrite(32);
- fifoDirectWriteFloat = AlignCode4();
- GenFifoFloatWrite();
- fifoDirectWriteXmm64 = AlignCode4();
- GenFifoXmm64Write();
-
- GenQuantizedLoads();
- GenQuantizedStores();
- GenQuantizedSingleStores();
- */
-
- //CMPSD(R(XMM0), M(&zero),
- // TODO
-
- // Fast write routines - special case the most common hardware write
- // TODO: use this.
- // Even in x86, the param values will be in the right registers.
- /*
- const u8 *fastMemWrite8 = AlignCode16();
- CMP(32, R(ABI_PARAM2), Imm32(0xCC008000));
- FixupBranch skip_fast_write = J_CC(CC_NE, false);
- MOV(32, EAX, M(&m_gatherPipeCount));
- MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1);
- ADD(32, 1, M(&m_gatherPipeCount));
- RET();
- SetJumpTarget(skip_fast_write);
- CALL((void *)&Memory::Write_U8);*/
-}
+}
\ No newline at end of file
diff --git a/Core/MIPS/x86/Asm.h b/Core/MIPS/x86/Asm.h
index 226332c676..d60aa4172d 100644
--- a/Core/MIPS/x86/Asm.h
+++ b/Core/MIPS/x86/Asm.h
@@ -20,19 +20,8 @@
#include "x64Emitter.h"
#include "../MIPS.h"
-// In Dolphin, we don't use inline assembly. Instead, we generate all machine-near
-// code at runtime. In the case of fixed code like this, after writing it, we write
-// protect the memory, essentially making it work just like precompiled code.
-// There are some advantages to this approach:
-// 1) No need to setup an external assembler in the build.
-// 2) Cross platform, as long as it's x86/x64.
-// 3) Can optimize code at runtime for the specific CPU model.
-// There aren't really any disadvantages other than having to maintain a x86 emitter,
-// which we have to do anyway :)
-//
-// To add a new asm routine, just add another const here, and add the code to Generate.
-// Also, possibly increase the size of the code buffer.
+// Runtime generated assembly routines, like the Dispatcher.
namespace MIPSComp
{
@@ -68,8 +57,6 @@ public:
const u8 *dispatcherCheckCoreState;
const u8 *dispatcherNoCheck;
- const u8 *fpException;
-
const u8 *breakpointBailout;
};
diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp
index 58b04562fc..cfdc23963d 100644
--- a/Core/MIPS/x86/Jit.cpp
+++ b/Core/MIPS/x86/Jit.cpp
@@ -25,9 +25,6 @@
#include "RegCache.h"
#include "Jit.h"
-
-extern u32 *pspmainram;
-
namespace MIPSComp
{
@@ -52,8 +49,6 @@ void Jit::ClearCache()
ClearCodeSpace();
}
-u8 *codeCache;
-#define CACHESIZE 16384*1024
void Jit::CompileAt(u32 addr)
{
u32 op = Memory::Read_Instruction(addr);
diff --git a/android/jni/Android.mk b/android/jni/Android.mk
index 0b99805fe0..4e54d3bcff 100644
--- a/android/jni/Android.mk
+++ b/android/jni/Android.mk
@@ -168,14 +168,15 @@ LOCAL_SRC_FILES := \
$(SRC)/Core/MIPS/MIPSCodeUtils.cpp \
$(SRC)/Core/MIPS/MIPSDebugInterface.cpp \
$(SRC)/Core/MIPS/JitCommon/JitCommon.cpp \
- $(SRC)/Core/MIPS/ARM/JitCache.cpp \
- $(SRC)/Core/MIPS/ARM/CompALU.cpp \
- $(SRC)/Core/MIPS/ARM/CompBranch.cpp \
- $(SRC)/Core/MIPS/ARM/CompFPU.cpp \
- $(SRC)/Core/MIPS/ARM/Asm.cpp \
- $(SRC)/Core/MIPS/ARM/Jit.cpp \
- $(SRC)/Core/MIPS/ARM/CompLoadStore.cpp \
- $(SRC)/Core/MIPS/ARM/RegCache.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmJitCache.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmCompALU.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmCompBranch.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmCompFPU.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmCompLoadStore.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmCompVFPU.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmAsm.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmJit.cpp \
+ $(SRC)/Core/MIPS/ARM/ArmRegCache.cpp \
$(SRC)/Core/Util/BlockAllocator.cpp \
$(SRC)/Core/Util/ppge_atlas.cpp \
$(SRC)/Core/Util/PPGeDraw.cpp
diff --git a/android/jni/Application.mk b/android/jni/Application.mk
index dd83bdcd41..62367cb819 100644
--- a/android/jni/Application.mk
+++ b/android/jni/Application.mk
@@ -1,2 +1,5 @@
APP_STL := stlport_static
-APP_ABI := armeabi armeabi-v7a
+APP_ABI := armeabi-v7a
+
+
+#armeabi