mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-27 10:20:49 +00:00
Rename files. Rewrite ArmRegCache from scratch.
This commit is contained in:
parent
771382cab9
commit
a2ff416534
@ -185,49 +185,55 @@
|
||||
<ClCompile Include="Loaders.cpp" />
|
||||
<ClCompile Include="MemMap.cpp" />
|
||||
<ClCompile Include="MemmapFunctions.cpp" />
|
||||
<ClCompile Include="MIPS\ARM\Asm.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmAsm.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompALU.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmCompALU.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompBranch.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmCompBranch.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompFPU.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmCompFPU.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompLoadStore.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmCompLoadStore.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\Jit.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmCompVFPU.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\JitCache.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmJit.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\RegCache.cpp">
|
||||
<ClCompile Include="MIPS\ARM\ArmJitCache.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmRegCache.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
@ -338,25 +344,25 @@
|
||||
<ClInclude Include="HW\MemoryStick.h" />
|
||||
<ClInclude Include="Loaders.h" />
|
||||
<ClInclude Include="MemMap.h" />
|
||||
<ClInclude Include="MIPS\ARM\Asm.h">
|
||||
<ClInclude Include="MIPS\ARM\ArmAsm.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\Jit.h">
|
||||
<ClInclude Include="MIPS\ARM\ArmJit.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\JitCache.h">
|
||||
<ClInclude Include="MIPS\ARM\ArmJitCache.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\RegCache.h">
|
||||
<ClInclude Include="MIPS\ARM\ArmRegCache.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
@ -409,4 +415,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -111,30 +111,6 @@
|
||||
<ClCompile Include="MIPS\x86\CompVFPU.cpp">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\Asm.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompALU.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompBranch.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompFPU.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\Jit.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\CompLoadStore.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\JitCache.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\RegCache.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\JitCommon\JitCommon.cpp">
|
||||
<Filter>MIPS\JitCommon</Filter>
|
||||
</ClCompile>
|
||||
@ -363,6 +339,33 @@
|
||||
<ClCompile Include="..\ext\snappy\snappy.cpp">
|
||||
<Filter>Ext\Snappy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmAsm.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmCompALU.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmCompBranch.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmCompFPU.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmCompLoadStore.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmJit.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmJitCache.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmRegCache.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmCompVFPU.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@ -413,18 +416,6 @@
|
||||
<ClInclude Include="MIPS\x86\RegCache.h">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\Asm.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\Jit.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\JitCache.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\RegCache.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\JitCommon\JitCommon.h">
|
||||
<Filter>MIPS\JitCommon</Filter>
|
||||
</ClInclude>
|
||||
@ -674,6 +665,18 @@
|
||||
<ClInclude Include="..\ext\snappy\snappy-internal.h">
|
||||
<Filter>Ext\Snappy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmAsm.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmJit.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmJitCache.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmRegCache.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
@ -681,4 +684,4 @@
|
||||
<None Include="..\android\jni\Android.mk" />
|
||||
<None Include="GameLogNotes.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -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 <ArmEmitter.h>
|
||||
#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<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);
|
||||
|
||||
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<void *>(&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);*/
|
||||
}
|
||||
}
|
@ -21,19 +21,7 @@
|
||||
#include <ArmEmitter.h>
|
||||
#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
|
@ -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 <ArmEmitter.h>
|
||||
#include "ArmJit.h"
|
||||
#include "ArmRegCache.h"
|
||||
#include "ArmEmitter.h"
|
||||
|
||||
using namespace MIPSAnalyst;
|
||||
#define _RS ((op>>21) & 0x1F)
|
@ -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 <ArmEmitter.h>
|
||||
|
||||
#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)
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 <ArmEmitter.h>
|
||||
#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;
|
@ -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 <ArmEmitter.h>
|
||||
#include "ArmJitCache.h"
|
||||
#include "../JitCommon/JitCommon.h"
|
||||
#include "ArmAsm.h"
|
||||
|
||||
#if defined USE_OPROFILE && USE_OPROFILE
|
||||
#include <opagent.h>
|
||||
@ -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<int> *block_numbers)
|
||||
void ArmJitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *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<u32, int>::iterator iter;
|
||||
pair<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
|
||||
// equal_range(b) returns pair<iterator,iterator> 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<u32, int>::iterator iter;
|
||||
pair<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
|
||||
ppp = links_to.equal_range(b.originalAddress);
|
||||
if (ppp.first == ppp.second)
|
||||
return;
|
||||
for (multimap<u32, int>::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;
|
@ -22,7 +22,7 @@
|
||||
#include <string>
|
||||
|
||||
#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<u32, int> links_to;
|
||||
std::map<std::pair<u32,u32>, 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();
|
||||
|
189
Core/MIPS/ARM/ArmRegCache.cpp
Normal file
189
Core/MIPS/ARM/ArmRegCache.cpp
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
|
112
Core/MIPS/ARM/ArmRegCache.h
Normal file
112
Core/MIPS/ARM/ArmRegCache.h
Normal file
@ -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];
|
||||
};
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
@ -18,7 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(ARM)
|
||||
#include "../ARM/Jit.h"
|
||||
#include "../ARM/ArmJit.h"
|
||||
#else
|
||||
#include "../x86/Jit.h"
|
||||
#endif
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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);*/
|
||||
}
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1,2 +1,5 @@
|
||||
APP_STL := stlport_static
|
||||
APP_ABI := armeabi armeabi-v7a
|
||||
APP_ABI := armeabi-v7a
|
||||
|
||||
|
||||
#armeabi
|
||||
|
Loading…
Reference in New Issue
Block a user