Refactor the JIT to be object-oriented (#1879)
* Move TinyVector to a new file - So it's less sensitive to #include ordering * Forgot to include assert.h * Refactor ARMJIT_Memory into an object * Oops, forgot a declaration * Refactor ARMJIT to be contained in an object * Remove an unused function declaration * Add a missing #include * Remove a now-unused global * Use ARMJIT_Memory's own memory access functions * Fix some omissions in the ARM JIT * Move libandroid to be a member of ARMJIT_Memory instead of a global * Default-initialize most fields in ARMJIT_Compiler.h * Define NOOP_IF_NO_JIT * Finish refactoring the JIT to be object-oriented
This commit is contained in:
parent
f2d7a29015
commit
544fefa27f
38
src/ARM.cpp
38
src/ARM.cpp
|
@ -26,11 +26,7 @@
|
||||||
#include "ARMJIT.h"
|
#include "ARMJIT.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
#include "GPU.h"
|
#include "GPU.h"
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
#include "ARMJIT.h"
|
|
||||||
#include "ARMJIT_Memory.h"
|
#include "ARMJIT_Memory.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
using Platform::Log;
|
using Platform::Log;
|
||||||
using Platform::LogLevel;
|
using Platform::LogLevel;
|
||||||
|
@ -88,7 +84,7 @@ void ARM::GdbCheckC() {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u32 ARM::ConditionTable[16] =
|
const u32 ARM::ConditionTable[16] =
|
||||||
{
|
{
|
||||||
0xF0F0, // EQ
|
0xF0F0, // EQ
|
||||||
0x0F0F, // NE
|
0x0F0F, // NE
|
||||||
|
@ -108,16 +104,14 @@ u32 ARM::ConditionTable[16] =
|
||||||
0x0000 // NE
|
0x0000 // NE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ARM::ARM(u32 num, ARMJIT::ARMJIT& jit, Melon::GPU& gpu) :
|
||||||
ARM::ARM(u32 num, Melon::GPU& gpu) :
|
|
||||||
#ifdef GDBSTUB_ENABLED
|
#ifdef GDBSTUB_ENABLED
|
||||||
GdbStub(this, Platform::GetConfigInt(num ? Platform::GdbPortARM7 : Platform::GdbPortARM9)),
|
GdbStub(this, Platform::GetConfigInt(num ? Platform::GdbPortARM7 : Platform::GdbPortARM9)),
|
||||||
#endif
|
#endif
|
||||||
|
JIT(jit),
|
||||||
|
Num(num), // well uh
|
||||||
GPU(gpu)
|
GPU(gpu)
|
||||||
{
|
{
|
||||||
// well uh
|
|
||||||
Num = num;
|
|
||||||
|
|
||||||
#ifdef GDBSTUB_ENABLED
|
#ifdef GDBSTUB_ENABLED
|
||||||
if (Platform::GetConfigBool(Platform::GdbEnabled)
|
if (Platform::GetConfigBool(Platform::GdbEnabled)
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
|
@ -134,25 +128,21 @@ ARM::~ARM()
|
||||||
// dorp
|
// dorp
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMv5::ARMv5(Melon::GPU& gpu) : ARM(0, gpu)
|
ARMv5::ARMv5(ARMJIT::ARMJIT& jit, Melon::GPU& gpu) : ARM(0, jit, gpu)
|
||||||
{
|
{
|
||||||
#ifndef JIT_ENABLED
|
DTCM = JIT.Memory.GetARM9DTCM();
|
||||||
DTCM = new u8[DTCMPhysicalSize];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PU_Map = PU_PrivMap;
|
PU_Map = PU_PrivMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMv4::ARMv4(Melon::GPU& gpu) : ARM(1, gpu)
|
ARMv4::ARMv4(ARMJIT::ARMJIT& jit, Melon::GPU& gpu) : ARM(1, jit, gpu)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMv5::~ARMv5()
|
ARMv5::~ARMv5()
|
||||||
{
|
{
|
||||||
#ifndef JIT_ENABLED
|
// DTCM is owned by Memory, not going to delete it
|
||||||
delete[] DTCM;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARM::Reset()
|
void ARM::Reset()
|
||||||
|
@ -752,19 +742,19 @@ void ARMv5::ExecuteJIT()
|
||||||
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
|
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
|
||||||
|
|
||||||
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
|
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
|
||||||
&& !ARMJIT::SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
&& !JIT.SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
||||||
{
|
{
|
||||||
NDS::ARM9Timestamp = NDS::ARM9Target;
|
NDS::ARM9Timestamp = NDS::ARM9Target;
|
||||||
Log(LogLevel::Error, "ARMv5 PC in non executable region %08X\n", R[15]);
|
Log(LogLevel::Error, "ARMv5 PC in non executable region %08X\n", R[15]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMJIT::JitBlockEntry block = ARMJIT::LookUpBlock(0, FastBlockLookup,
|
ARMJIT::JitBlockEntry block = JIT.LookUpBlock(0, FastBlockLookup,
|
||||||
instrAddr - FastBlockLookupStart, instrAddr);
|
instrAddr - FastBlockLookupStart, instrAddr);
|
||||||
if (block)
|
if (block)
|
||||||
ARM_Dispatch(this, block);
|
ARM_Dispatch(this, block);
|
||||||
else
|
else
|
||||||
ARMJIT::CompileBlock(this);
|
JIT.CompileBlock(this);
|
||||||
|
|
||||||
if (StopExecution)
|
if (StopExecution)
|
||||||
{
|
{
|
||||||
|
@ -909,19 +899,19 @@ void ARMv4::ExecuteJIT()
|
||||||
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
|
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
|
||||||
|
|
||||||
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
|
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
|
||||||
&& !ARMJIT::SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
&& !JIT.SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
||||||
{
|
{
|
||||||
NDS::ARM7Timestamp = NDS::ARM7Target;
|
NDS::ARM7Timestamp = NDS::ARM7Target;
|
||||||
Log(LogLevel::Error, "ARMv4 PC in non executable region %08X\n", R[15]);
|
Log(LogLevel::Error, "ARMv4 PC in non executable region %08X\n", R[15]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMJIT::JitBlockEntry block = ARMJIT::LookUpBlock(1, FastBlockLookup,
|
ARMJIT::JitBlockEntry block = JIT.LookUpBlock(1, FastBlockLookup,
|
||||||
instrAddr - FastBlockLookupStart, instrAddr);
|
instrAddr - FastBlockLookupStart, instrAddr);
|
||||||
if (block)
|
if (block)
|
||||||
ARM_Dispatch(this, block);
|
ARM_Dispatch(this, block);
|
||||||
else
|
else
|
||||||
ARMJIT::CompileBlock(this);
|
JIT.CompileBlock(this);
|
||||||
|
|
||||||
if (StopExecution)
|
if (StopExecution)
|
||||||
{
|
{
|
||||||
|
|
15
src/ARM.h
15
src/ARM.h
|
@ -42,18 +42,24 @@ enum
|
||||||
const u32 ITCMPhysicalSize = 0x8000;
|
const u32 ITCMPhysicalSize = 0x8000;
|
||||||
const u32 DTCMPhysicalSize = 0x4000;
|
const u32 DTCMPhysicalSize = 0x4000;
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
|
{
|
||||||
|
class ARMJIT;
|
||||||
|
}
|
||||||
namespace Melon
|
namespace Melon
|
||||||
{
|
{
|
||||||
class GPU;
|
class GPU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ARMJIT_Memory;
|
||||||
|
|
||||||
class ARM
|
class ARM
|
||||||
#ifdef GDBSTUB_ENABLED
|
#ifdef GDBSTUB_ENABLED
|
||||||
: public Gdb::StubCallbacks
|
: public Gdb::StubCallbacks
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ARM(u32 num, Melon::GPU& gpu);
|
ARM(u32 num, ARMJIT::ARMJIT& jit, Melon::GPU& gpu);
|
||||||
virtual ~ARM(); // destroy shit
|
virtual ~ARM(); // destroy shit
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
@ -179,11 +185,12 @@ public:
|
||||||
u64* FastBlockLookup;
|
u64* FastBlockLookup;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static u32 ConditionTable[16];
|
static const u32 ConditionTable[16];
|
||||||
#ifdef GDBSTUB_ENABLED
|
#ifdef GDBSTUB_ENABLED
|
||||||
Gdb::GdbStub GdbStub;
|
Gdb::GdbStub GdbStub;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ARMJIT::ARMJIT& JIT;
|
||||||
protected:
|
protected:
|
||||||
u8 (*BusRead8)(u32 addr);
|
u8 (*BusRead8)(u32 addr);
|
||||||
u16 (*BusRead16)(u32 addr);
|
u16 (*BusRead16)(u32 addr);
|
||||||
|
@ -221,7 +228,7 @@ private:
|
||||||
class ARMv5 : public ARM
|
class ARMv5 : public ARM
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ARMv5(Melon::GPU& gpu);
|
ARMv5(ARMJIT::ARMJIT& jit, Melon::GPU& gpu);
|
||||||
~ARMv5();
|
~ARMv5();
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
|
@ -365,7 +372,7 @@ public:
|
||||||
class ARMv4 : public ARM
|
class ARMv4 : public ARM
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ARMv4(Melon::GPU& gpu);
|
ARMv4(ARMJIT::ARMJIT& jit, Melon::GPU& gpu);
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
|
|
||||||
|
|
244
src/ARMJIT.cpp
244
src/ARMJIT.cpp
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ARMJIT.h"
|
#include "ARMJIT.h"
|
||||||
|
#include "ARMJIT_Memory.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -58,49 +58,6 @@ namespace ARMJIT
|
||||||
#define JIT_DEBUGPRINT(msg, ...)
|
#define JIT_DEBUGPRINT(msg, ...)
|
||||||
//#define JIT_DEBUGPRINT(msg, ...) Platform::Log(Platform::LogLevel::Debug, msg, ## __VA_ARGS__)
|
//#define JIT_DEBUGPRINT(msg, ...) Platform::Log(Platform::LogLevel::Debug, msg, ## __VA_ARGS__)
|
||||||
|
|
||||||
Compiler* JITCompiler;
|
|
||||||
|
|
||||||
int MaxBlockSize;
|
|
||||||
bool LiteralOptimizations;
|
|
||||||
bool BranchOptimizations;
|
|
||||||
bool FastMemory;
|
|
||||||
|
|
||||||
|
|
||||||
std::unordered_map<u32, JitBlock*> JitBlocks9;
|
|
||||||
std::unordered_map<u32, JitBlock*> JitBlocks7;
|
|
||||||
|
|
||||||
std::unordered_map<u32, JitBlock*> RestoreCandidates;
|
|
||||||
|
|
||||||
TinyVector<u32> InvalidLiterals;
|
|
||||||
|
|
||||||
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512];
|
|
||||||
AddressRange CodeIndexMainRAM[NDS::MainRAMMaxSize / 512];
|
|
||||||
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512];
|
|
||||||
AddressRange CodeIndexVRAM[0x100000 / 512];
|
|
||||||
AddressRange CodeIndexARM9BIOS[sizeof(NDS::ARM9BIOS) / 512];
|
|
||||||
AddressRange CodeIndexARM7BIOS[sizeof(NDS::ARM7BIOS) / 512];
|
|
||||||
AddressRange CodeIndexARM7WRAM[NDS::ARM7WRAMSize / 512];
|
|
||||||
AddressRange CodeIndexARM7WVRAM[0x40000 / 512];
|
|
||||||
AddressRange CodeIndexBIOS9DSi[0x10000 / 512];
|
|
||||||
AddressRange CodeIndexBIOS7DSi[0x10000 / 512];
|
|
||||||
AddressRange CodeIndexNWRAM_A[DSi::NWRAMSize / 512];
|
|
||||||
AddressRange CodeIndexNWRAM_B[DSi::NWRAMSize / 512];
|
|
||||||
AddressRange CodeIndexNWRAM_C[DSi::NWRAMSize / 512];
|
|
||||||
|
|
||||||
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2];
|
|
||||||
u64 FastBlockLookupMainRAM[NDS::MainRAMMaxSize / 2];
|
|
||||||
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2];
|
|
||||||
u64 FastBlockLookupVRAM[0x100000 / 2];
|
|
||||||
u64 FastBlockLookupARM9BIOS[sizeof(NDS::ARM9BIOS) / 2];
|
|
||||||
u64 FastBlockLookupARM7BIOS[sizeof(NDS::ARM7BIOS) / 2];
|
|
||||||
u64 FastBlockLookupARM7WRAM[NDS::ARM7WRAMSize / 2];
|
|
||||||
u64 FastBlockLookupARM7WVRAM[0x40000 / 2];
|
|
||||||
u64 FastBlockLookupBIOS9DSi[0x10000 / 2];
|
|
||||||
u64 FastBlockLookupBIOS7DSi[0x10000 / 2];
|
|
||||||
u64 FastBlockLookupNWRAM_A[DSi::NWRAMSize / 2];
|
|
||||||
u64 FastBlockLookupNWRAM_B[DSi::NWRAMSize / 2];
|
|
||||||
u64 FastBlockLookupNWRAM_C[DSi::NWRAMSize / 2];
|
|
||||||
|
|
||||||
const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
|
const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
|
||||||
{
|
{
|
||||||
0,
|
0,
|
||||||
|
@ -123,58 +80,14 @@ const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
|
||||||
DSi::NWRAMSize,
|
DSi::NWRAMSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
|
u32 ARMJIT::LocaliseCodeAddress(u32 num, u32 addr) const noexcept
|
||||||
{
|
|
||||||
NULL,
|
|
||||||
CodeIndexITCM,
|
|
||||||
NULL,
|
|
||||||
CodeIndexARM9BIOS,
|
|
||||||
CodeIndexMainRAM,
|
|
||||||
CodeIndexSWRAM,
|
|
||||||
NULL,
|
|
||||||
CodeIndexVRAM,
|
|
||||||
CodeIndexARM7BIOS,
|
|
||||||
CodeIndexARM7WRAM,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
CodeIndexARM7WVRAM,
|
|
||||||
CodeIndexBIOS9DSi,
|
|
||||||
CodeIndexBIOS7DSi,
|
|
||||||
CodeIndexNWRAM_A,
|
|
||||||
CodeIndexNWRAM_B,
|
|
||||||
CodeIndexNWRAM_C
|
|
||||||
};
|
|
||||||
|
|
||||||
u64* const FastBlockLookupRegions[ARMJIT_Memory::memregions_Count] =
|
|
||||||
{
|
|
||||||
NULL,
|
|
||||||
FastBlockLookupITCM,
|
|
||||||
NULL,
|
|
||||||
FastBlockLookupARM9BIOS,
|
|
||||||
FastBlockLookupMainRAM,
|
|
||||||
FastBlockLookupSWRAM,
|
|
||||||
NULL,
|
|
||||||
FastBlockLookupVRAM,
|
|
||||||
FastBlockLookupARM7BIOS,
|
|
||||||
FastBlockLookupARM7WRAM,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
FastBlockLookupARM7WVRAM,
|
|
||||||
FastBlockLookupBIOS9DSi,
|
|
||||||
FastBlockLookupBIOS7DSi,
|
|
||||||
FastBlockLookupNWRAM_A,
|
|
||||||
FastBlockLookupNWRAM_B,
|
|
||||||
FastBlockLookupNWRAM_C
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 LocaliseCodeAddress(u32 num, u32 addr)
|
|
||||||
{
|
{
|
||||||
int region = num == 0
|
int region = num == 0
|
||||||
? ARMJIT_Memory::ClassifyAddress9(addr)
|
? Memory.ClassifyAddress9(addr)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(addr);
|
: Memory.ClassifyAddress7(addr);
|
||||||
|
|
||||||
if (CodeMemRegions[region])
|
if (CodeMemRegions[region])
|
||||||
return ARMJIT_Memory::LocaliseAddress(region, num, addr);
|
return Memory.LocaliseAddress(region, num, addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +115,26 @@ T SlowRead9(u32 addr, ARMv5* cpu)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, int ConsoleType>
|
||||||
|
T SlowRead7(u32 addr)
|
||||||
|
{
|
||||||
|
u32 offset = addr & 0x3;
|
||||||
|
addr &= ~(sizeof(T) - 1);
|
||||||
|
|
||||||
|
T val;
|
||||||
|
if (std::is_same<T, u32>::value)
|
||||||
|
val = (ConsoleType == 0 ? NDS::ARM7Read32 : DSi::ARM7Read32)(addr);
|
||||||
|
else if (std::is_same<T, u16>::value)
|
||||||
|
val = (ConsoleType == 0 ? NDS::ARM7Read16 : DSi::ARM7Read16)(addr);
|
||||||
|
else
|
||||||
|
val = (ConsoleType == 0 ? NDS::ARM7Read8 : DSi::ARM7Read8)(addr);
|
||||||
|
|
||||||
|
if (std::is_same<T, u32>::value)
|
||||||
|
return ROR(val, offset << 3);
|
||||||
|
else
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, int ConsoleType>
|
template <typename T, int ConsoleType>
|
||||||
void SlowWrite9(u32 addr, ARMv5* cpu, u32 val)
|
void SlowWrite9(u32 addr, ARMv5* cpu, u32 val)
|
||||||
{
|
{
|
||||||
|
@ -209,7 +142,7 @@ void SlowWrite9(u32 addr, ARMv5* cpu, u32 val)
|
||||||
|
|
||||||
if (addr < cpu->ITCMSize)
|
if (addr < cpu->ITCMSize)
|
||||||
{
|
{
|
||||||
CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
cpu->JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||||
*(T*)&cpu->ITCM[addr & 0x7FFF] = val;
|
*(T*)&cpu->ITCM[addr & 0x7FFF] = val;
|
||||||
}
|
}
|
||||||
else if ((addr & cpu->DTCMMask) == cpu->DTCMBase)
|
else if ((addr & cpu->DTCMMask) == cpu->DTCMBase)
|
||||||
|
@ -230,26 +163,6 @@ void SlowWrite9(u32 addr, ARMv5* cpu, u32 val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int ConsoleType>
|
|
||||||
T SlowRead7(u32 addr)
|
|
||||||
{
|
|
||||||
u32 offset = addr & 0x3;
|
|
||||||
addr &= ~(sizeof(T) - 1);
|
|
||||||
|
|
||||||
T val;
|
|
||||||
if (std::is_same<T, u32>::value)
|
|
||||||
val = (ConsoleType == 0 ? NDS::ARM7Read32 : DSi::ARM7Read32)(addr);
|
|
||||||
else if (std::is_same<T, u16>::value)
|
|
||||||
val = (ConsoleType == 0 ? NDS::ARM7Read16 : DSi::ARM7Read16)(addr);
|
|
||||||
else
|
|
||||||
val = (ConsoleType == 0 ? NDS::ARM7Read8 : DSi::ARM7Read8)(addr);
|
|
||||||
|
|
||||||
if (std::is_same<T, u32>::value)
|
|
||||||
return ROR(val, offset << 3);
|
|
||||||
else
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, int ConsoleType>
|
template <typename T, int ConsoleType>
|
||||||
void SlowWrite7(u32 addr, u32 val)
|
void SlowWrite7(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
|
@ -316,24 +229,13 @@ void SlowBlockTransfer7(u32 addr, u64* data, u32 num)
|
||||||
INSTANTIATE_SLOWMEM(0)
|
INSTANTIATE_SLOWMEM(0)
|
||||||
INSTANTIATE_SLOWMEM(1)
|
INSTANTIATE_SLOWMEM(1)
|
||||||
|
|
||||||
void Init()
|
ARMJIT::~ARMJIT() noexcept
|
||||||
{
|
|
||||||
JITCompiler = new Compiler();
|
|
||||||
|
|
||||||
ARMJIT_Memory::Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeInit()
|
|
||||||
{
|
{
|
||||||
JitEnableWrite();
|
JitEnableWrite();
|
||||||
ResetBlockCache();
|
ResetBlockCache();
|
||||||
ARMJIT_Memory::DeInit();
|
|
||||||
|
|
||||||
delete JITCompiler;
|
|
||||||
JITCompiler = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void ARMJIT::Reset() noexcept
|
||||||
{
|
{
|
||||||
MaxBlockSize = Platform::GetConfigInt(Platform::JIT_MaxBlockSize);
|
MaxBlockSize = Platform::GetConfigInt(Platform::JIT_MaxBlockSize);
|
||||||
LiteralOptimizations = Platform::GetConfigBool(Platform::JIT_LiteralOptimizations);
|
LiteralOptimizations = Platform::GetConfigBool(Platform::JIT_LiteralOptimizations);
|
||||||
|
@ -348,7 +250,7 @@ void Reset()
|
||||||
JitEnableWrite();
|
JitEnableWrite();
|
||||||
ResetBlockCache();
|
ResetBlockCache();
|
||||||
|
|
||||||
ARMJIT_Memory::Reset();
|
Memory.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloodFillSetFlags(FetchedInstr instrs[], int start, u8 flags)
|
void FloodFillSetFlags(FetchedInstr instrs[], int start, u8 flags)
|
||||||
|
@ -575,7 +477,7 @@ InterpreterFunc InterpretTHUMB[ARMInstrInfo::tk_Count] =
|
||||||
};
|
};
|
||||||
#undef F
|
#undef F
|
||||||
|
|
||||||
void RetireJitBlock(JitBlock* block)
|
void ARMJIT::RetireJitBlock(JitBlock* block) noexcept
|
||||||
{
|
{
|
||||||
auto it = RestoreCandidates.find(block->InstrHash);
|
auto it = RestoreCandidates.find(block->InstrHash);
|
||||||
if (it != RestoreCandidates.end())
|
if (it != RestoreCandidates.end())
|
||||||
|
@ -589,7 +491,7 @@ void RetireJitBlock(JitBlock* block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompileBlock(ARM* cpu)
|
void ARMJIT::CompileBlock(ARM* cpu) noexcept
|
||||||
{
|
{
|
||||||
bool thumb = cpu->CPSR & 0x20;
|
bool thumb = cpu->CPSR & 0x20;
|
||||||
|
|
||||||
|
@ -616,7 +518,7 @@ void CompileBlock(ARM* cpu)
|
||||||
|
|
||||||
u64* entry = &FastBlockLookupRegions[localAddr >> 27][(localAddr & 0x7FFFFFF) / 2];
|
u64* entry = &FastBlockLookupRegions[localAddr >> 27][(localAddr & 0x7FFFFFF) / 2];
|
||||||
*entry = ((u64)blockAddr | cpu->Num) << 32;
|
*entry = ((u64)blockAddr | cpu->Num) << 32;
|
||||||
*entry |= JITCompiler->SubEntryOffset(existingBlockIt->second->EntryPoint);
|
*entry |= JITCompiler.SubEntryOffset(existingBlockIt->second->EntryPoint);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,7 +619,7 @@ void CompileBlock(ARM* cpu)
|
||||||
nextInstr[1] = cpuv4->CodeRead32(r15);
|
nextInstr[1] = cpuv4->CodeRead32(r15);
|
||||||
instrs[i].CodeCycles = cpu->CodeCycles;
|
instrs[i].CodeCycles = cpu->CodeCycles;
|
||||||
}
|
}
|
||||||
instrs[i].Info = ARMInstrInfo::Decode(thumb, cpu->Num, instrs[i].Instr);
|
instrs[i].Info = ARMInstrInfo::Decode(thumb, cpu->Num, instrs[i].Instr, LiteralOptimizations);
|
||||||
|
|
||||||
hasMemoryInstr |= thumb
|
hasMemoryInstr |= thumb
|
||||||
? (instrs[i].Info.Kind >= ARMInstrInfo::tk_LDR_PCREL && instrs[i].Info.Kind <= ARMInstrInfo::tk_STMIA)
|
? (instrs[i].Info.Kind >= ARMInstrInfo::tk_LDR_PCREL && instrs[i].Info.Kind <= ARMInstrInfo::tk_STMIA)
|
||||||
|
@ -875,7 +777,7 @@ void CompileBlock(ARM* cpu)
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
bool canCompile = JITCompiler->CanCompile(thumb, instrs[i - 1].Info.Kind);
|
bool canCompile = JITCompiler.CanCompile(thumb, instrs[i - 1].Info.Kind);
|
||||||
bool secondaryFlagReadCond = !canCompile || (instrs[i - 1].BranchFlags & (branch_FollowCondTaken | branch_FollowCondNotTaken));
|
bool secondaryFlagReadCond = !canCompile || (instrs[i - 1].BranchFlags & (branch_FollowCondTaken | branch_FollowCondNotTaken));
|
||||||
if (instrs[i - 1].Info.ReadFlags != 0 || secondaryFlagReadCond)
|
if (instrs[i - 1].Info.ReadFlags != 0 || secondaryFlagReadCond)
|
||||||
FloodFillSetFlags(instrs, i - 2, !secondaryFlagReadCond ? instrs[i - 1].Info.ReadFlags : 0xF);
|
FloodFillSetFlags(instrs, i - 2, !secondaryFlagReadCond ? instrs[i - 1].Info.ReadFlags : 0xF);
|
||||||
|
@ -956,7 +858,7 @@ void CompileBlock(ARM* cpu)
|
||||||
FloodFillSetFlags(instrs, i - 1, 0xF);
|
FloodFillSetFlags(instrs, i - 1, 0xF);
|
||||||
|
|
||||||
JitEnableWrite();
|
JitEnableWrite();
|
||||||
block->EntryPoint = JITCompiler->CompileBlock(cpu, thumb, instrs, i, hasMemoryInstr);
|
block->EntryPoint = JITCompiler.CompileBlock(cpu, thumb, instrs, i, hasMemoryInstr);
|
||||||
JitEnableExecute();
|
JitEnableExecute();
|
||||||
|
|
||||||
JIT_DEBUGPRINT("block start %p\n", block->EntryPoint);
|
JIT_DEBUGPRINT("block start %p\n", block->EntryPoint);
|
||||||
|
@ -977,7 +879,7 @@ void CompileBlock(ARM* cpu)
|
||||||
AddressRange* region = CodeMemRegions[addressRanges[j] >> 27];
|
AddressRange* region = CodeMemRegions[addressRanges[j] >> 27];
|
||||||
|
|
||||||
if (!PageContainsCode(®ion[(addressRanges[j] & 0x7FFF000) / 512]))
|
if (!PageContainsCode(®ion[(addressRanges[j] & 0x7FFF000) / 512]))
|
||||||
ARMJIT_Memory::SetCodeProtection(addressRanges[j] >> 27, addressRanges[j] & 0x7FFFFFF, true);
|
Memory.SetCodeProtection(addressRanges[j] >> 27, addressRanges[j] & 0x7FFFFFF, true);
|
||||||
|
|
||||||
AddressRange* range = ®ion[(addressRanges[j] & 0x7FFFFFF) / 512];
|
AddressRange* range = ®ion[(addressRanges[j] & 0x7FFFFFF) / 512];
|
||||||
range->Code |= addressMasks[j];
|
range->Code |= addressMasks[j];
|
||||||
|
@ -991,10 +893,10 @@ void CompileBlock(ARM* cpu)
|
||||||
|
|
||||||
u64* entry = &FastBlockLookupRegions[(localAddr >> 27)][(localAddr & 0x7FFFFFF) / 2];
|
u64* entry = &FastBlockLookupRegions[(localAddr >> 27)][(localAddr & 0x7FFFFFF) / 2];
|
||||||
*entry = ((u64)blockAddr | cpu->Num) << 32;
|
*entry = ((u64)blockAddr | cpu->Num) << 32;
|
||||||
*entry |= JITCompiler->SubEntryOffset(block->EntryPoint);
|
*entry |= JITCompiler.SubEntryOffset(block->EntryPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvalidateByAddr(u32 localAddr)
|
void ARMJIT::InvalidateByAddr(u32 localAddr) noexcept
|
||||||
{
|
{
|
||||||
JIT_DEBUGPRINT("invalidating by addr %x\n", localAddr);
|
JIT_DEBUGPRINT("invalidating by addr %x\n", localAddr);
|
||||||
|
|
||||||
|
@ -1031,7 +933,7 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
if (range->Blocks.Length == 0
|
if (range->Blocks.Length == 0
|
||||||
&& !PageContainsCode(®ion[(localAddr & 0x7FFF000) / 512]))
|
&& !PageContainsCode(®ion[(localAddr & 0x7FFF000) / 512]))
|
||||||
{
|
{
|
||||||
ARMJIT_Memory::SetCodeProtection(localAddr >> 27, localAddr & 0x7FFFFFF, false);
|
Memory.SetCodeProtection(localAddr >> 27, localAddr & 0x7FFFFFF, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool literalInvalidation = false;
|
bool literalInvalidation = false;
|
||||||
|
@ -1064,7 +966,7 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
if (otherRange->Blocks.Length == 0)
|
if (otherRange->Blocks.Length == 0)
|
||||||
{
|
{
|
||||||
if (!PageContainsCode(&otherRegion[(addr & 0x7FFF000) / 512]))
|
if (!PageContainsCode(&otherRegion[(addr & 0x7FFF000) / 512]))
|
||||||
ARMJIT_Memory::SetCodeProtection(addr >> 27, addr & 0x7FFFFFF, false);
|
Memory.SetCodeProtection(addr >> 27, addr & 0x7FFFFFF, false);
|
||||||
|
|
||||||
otherRange->Code = 0;
|
otherRange->Code = 0;
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +990,7 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckAndInvalidateITCM()
|
void ARMJIT::CheckAndInvalidateITCM() noexcept
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < ITCMPhysicalSize; i+=512)
|
for (u32 i = 0; i < ITCMPhysicalSize; i+=512)
|
||||||
{
|
{
|
||||||
|
@ -1106,7 +1008,7 @@ void CheckAndInvalidateITCM()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckAndInvalidateWVRAM(int bank)
|
void ARMJIT::CheckAndInvalidateWVRAM(int bank) noexcept
|
||||||
{
|
{
|
||||||
u32 start = bank == 1 ? 0x20000 : 0;
|
u32 start = bank == 1 ? 0x20000 : 0;
|
||||||
for (u32 i = start; i < start+0x20000; i+=512)
|
for (u32 i = start; i < start+0x20000; i+=512)
|
||||||
|
@ -1122,38 +1024,30 @@ void CheckAndInvalidateWVRAM(int bank)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <u32 num, int region>
|
JitBlockEntry ARMJIT::LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr) noexcept
|
||||||
void CheckAndInvalidate(u32 addr)
|
|
||||||
{
|
|
||||||
u32 localAddr = ARMJIT_Memory::LocaliseAddress(region, num, addr);
|
|
||||||
if (CodeMemRegions[region][(localAddr & 0x7FFFFFF) / 512].Code & (1 << ((localAddr & 0x1FF) / 16)))
|
|
||||||
InvalidateByAddr(localAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr)
|
|
||||||
{
|
{
|
||||||
u64* entry = &entries[offset / 2];
|
u64* entry = &entries[offset / 2];
|
||||||
if (*entry >> 32 == (addr | num))
|
if (*entry >> 32 == (addr | num))
|
||||||
return JITCompiler->AddEntryOffset((u32)*entry);
|
return JITCompiler.AddEntryOffset((u32)*entry);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockSanityCheck(u32 num, u32 blockAddr, JitBlockEntry entry)
|
void ARMJIT::blockSanityCheck(u32 num, u32 blockAddr, JitBlockEntry entry) noexcept
|
||||||
{
|
{
|
||||||
u32 localAddr = LocaliseCodeAddress(num, blockAddr);
|
u32 localAddr = LocaliseCodeAddress(num, blockAddr);
|
||||||
assert(JITCompiler->AddEntryOffset((u32)FastBlockLookupRegions[localAddr >> 27][(localAddr & 0x7FFFFFF) / 2]) == entry);
|
assert(JITCompiler.AddEntryOffset((u32)FastBlockLookupRegions[localAddr >> 27][(localAddr & 0x7FFFFFF) / 2]) == entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SetupExecutableRegion(u32 num, u32 blockAddr, u64*& entry, u32& start, u32& size)
|
bool ARMJIT::SetupExecutableRegion(u32 num, u32 blockAddr, u64*& entry, u32& start, u32& size) noexcept
|
||||||
{
|
{
|
||||||
// amazingly ignoring the DTCM is the proper behaviour for code fetches
|
// amazingly ignoring the DTCM is the proper behaviour for code fetches
|
||||||
int region = num == 0
|
int region = num == 0
|
||||||
? ARMJIT_Memory::ClassifyAddress9(blockAddr)
|
? Memory.ClassifyAddress9(blockAddr)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(blockAddr);
|
: Memory.ClassifyAddress7(blockAddr);
|
||||||
|
|
||||||
u32 memoryOffset;
|
u32 memoryOffset;
|
||||||
if (FastBlockLookupRegions[region]
|
if (FastBlockLookupRegions[region]
|
||||||
&& ARMJIT_Memory::GetMirrorLocation(region, num, blockAddr, memoryOffset, start, size))
|
&& Memory.GetMirrorLocation(region, num, blockAddr, memoryOffset, start, size))
|
||||||
{
|
{
|
||||||
//printf("setup exec region %d %d %08x %08x %x %x\n", num, region, blockAddr, start, size, memoryOffset);
|
//printf("setup exec region %d %d %08x %08x %x %x\n", num, region, blockAddr, start, size, memoryOffset);
|
||||||
entry = FastBlockLookupRegions[region] + memoryOffset / 2;
|
entry = FastBlockLookupRegions[region] + memoryOffset / 2;
|
||||||
|
@ -1162,28 +1056,28 @@ bool SetupExecutableRegion(u32 num, u32 blockAddr, u64*& entry, u32& start, u32&
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(u32);
|
template void ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(u32);
|
template void ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(u32);
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(u32);
|
template void ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(u32);
|
template void ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(u32);
|
template void ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(u32);
|
template void ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(u32);
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(u32);
|
template void ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(u32);
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(u32);
|
template void ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(u32);
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(u32);
|
template void ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(u32);
|
template void ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(u32);
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(u32);
|
template void ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(u32);
|
template void ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(u32);
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(u32);
|
template void ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(u32);
|
template void ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(u32);
|
||||||
|
|
||||||
void ResetBlockCache()
|
void ARMJIT::ResetBlockCache() noexcept
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "Resetting JIT block cache...\n");
|
Log(LogLevel::Debug, "Resetting JIT block cache...\n");
|
||||||
|
|
||||||
// could be replace through a function which only resets
|
// could be replace through a function which only resets
|
||||||
// the permissions but we're too lazy
|
// the permissions but we're too lazy
|
||||||
ARMJIT_Memory::Reset();
|
Memory.Reset();
|
||||||
|
|
||||||
InvalidLiterals.Clear();
|
InvalidLiterals.Clear();
|
||||||
for (int i = 0; i < ARMJIT_Memory::memregions_Count; i++)
|
for (int i = 0; i < ARMJIT_Memory::memregions_Count; i++)
|
||||||
|
@ -1221,10 +1115,10 @@ void ResetBlockCache()
|
||||||
JitBlocks9.clear();
|
JitBlocks9.clear();
|
||||||
JitBlocks7.clear();
|
JitBlocks7.clear();
|
||||||
|
|
||||||
JITCompiler->Reset();
|
JITCompiler.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitEnableWrite()
|
void ARMJIT::JitEnableWrite() noexcept
|
||||||
{
|
{
|
||||||
#if defined(__APPLE__) && defined(__aarch64__)
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
if (__builtin_available(macOS 11.0, *))
|
if (__builtin_available(macOS 11.0, *))
|
||||||
|
@ -1232,7 +1126,7 @@ void JitEnableWrite()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitEnableExecute()
|
void ARMJIT::JitEnableExecute() noexcept
|
||||||
{
|
{
|
||||||
#if defined(__APPLE__) && defined(__aarch64__)
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
if (__builtin_available(macOS 11.0, *))
|
if (__builtin_available(macOS 11.0, *))
|
||||||
|
|
142
src/ARMJIT.h
142
src/ARMJIT.h
|
@ -19,49 +19,147 @@
|
||||||
#ifndef ARMJIT_H
|
#ifndef ARMJIT_H
|
||||||
#define ARMJIT_H
|
#define ARMJIT_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#include "ARM.h"
|
#include "ARMJIT_Memory.h"
|
||||||
#include "ARM_InstrInfo.h"
|
#include "JitBlock.h"
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__aarch64__)
|
#if defined(__APPLE__) && defined(__aarch64__)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "ARMJIT_Compiler.h"
|
||||||
|
|
||||||
|
class ARM;
|
||||||
|
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
|
class JitBlock;
|
||||||
|
class ARMJIT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ARMJIT() noexcept : JITCompiler(*this), Memory(*this) {}
|
||||||
|
~ARMJIT() noexcept NOOP_IF_NO_JIT;
|
||||||
|
void InvalidateByAddr(u32) noexcept NOOP_IF_NO_JIT;
|
||||||
|
void CheckAndInvalidateWVRAM(int) noexcept NOOP_IF_NO_JIT;
|
||||||
|
void CheckAndInvalidateITCM() noexcept NOOP_IF_NO_JIT;
|
||||||
|
void Reset() noexcept NOOP_IF_NO_JIT;
|
||||||
|
void JitEnableWrite() noexcept NOOP_IF_NO_JIT;
|
||||||
|
void JitEnableExecute() noexcept NOOP_IF_NO_JIT;
|
||||||
|
void CompileBlock(ARM* cpu) noexcept NOOP_IF_NO_JIT;
|
||||||
|
void ResetBlockCache() noexcept NOOP_IF_NO_JIT;
|
||||||
|
|
||||||
typedef void (*JitBlockEntry)();
|
#ifdef JIT_ENABLED
|
||||||
|
template <u32 num, int region>
|
||||||
|
void CheckAndInvalidate(u32 addr) noexcept
|
||||||
|
{
|
||||||
|
u32 localAddr = Memory.LocaliseAddress(region, num, addr);
|
||||||
|
if (CodeMemRegions[region][(localAddr & 0x7FFFFFF) / 512].Code & (1 << ((localAddr & 0x1FF) / 16)))
|
||||||
|
InvalidateByAddr(localAddr);
|
||||||
|
}
|
||||||
|
JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr) noexcept;
|
||||||
|
bool SetupExecutableRegion(u32 num, u32 blockAddr, u64*& entry, u32& start, u32& size) noexcept;
|
||||||
|
u32 LocaliseCodeAddress(u32 num, u32 addr) const noexcept;
|
||||||
|
#else
|
||||||
|
template <u32, int>
|
||||||
|
void CheckAndInvalidate(u32) noexcept {}
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int MaxBlockSize;
|
ARMJIT_Memory Memory;
|
||||||
extern bool LiteralOptimizations;
|
int MaxBlockSize {};
|
||||||
extern bool BranchOptimizations;
|
bool LiteralOptimizations = false;
|
||||||
extern bool FastMemory;
|
bool BranchOptimizations = false;
|
||||||
|
bool FastMemory = false;
|
||||||
|
|
||||||
void Init();
|
TinyVector<u32> InvalidLiterals {};
|
||||||
void DeInit();
|
private:
|
||||||
|
friend class ::ARMJIT_Memory;
|
||||||
|
void blockSanityCheck(u32 num, u32 blockAddr, JitBlockEntry entry) noexcept;
|
||||||
|
void RetireJitBlock(JitBlock* block) noexcept;
|
||||||
|
|
||||||
void Reset();
|
Compiler JITCompiler;
|
||||||
|
std::unordered_map<u32, JitBlock*> JitBlocks9 {};
|
||||||
|
std::unordered_map<u32, JitBlock*> JitBlocks7 {};
|
||||||
|
|
||||||
void CheckAndInvalidateITCM();
|
std::unordered_map<u32, JitBlock*> RestoreCandidates {};
|
||||||
void CheckAndInvalidateWVRAM(int bank);
|
|
||||||
|
|
||||||
void InvalidateByAddr(u32 pseudoPhysical);
|
|
||||||
|
|
||||||
template <u32 num, int region>
|
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512] {};
|
||||||
void CheckAndInvalidate(u32 addr);
|
AddressRange CodeIndexMainRAM[NDS::MainRAMMaxSize / 512] {};
|
||||||
|
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512] {};
|
||||||
|
AddressRange CodeIndexVRAM[0x100000 / 512] {};
|
||||||
|
AddressRange CodeIndexARM9BIOS[sizeof(NDS::ARM9BIOS) / 512] {};
|
||||||
|
AddressRange CodeIndexARM7BIOS[sizeof(NDS::ARM7BIOS) / 512] {};
|
||||||
|
AddressRange CodeIndexARM7WRAM[NDS::ARM7WRAMSize / 512] {};
|
||||||
|
AddressRange CodeIndexARM7WVRAM[0x40000 / 512] {};
|
||||||
|
AddressRange CodeIndexBIOS9DSi[0x10000 / 512] {};
|
||||||
|
AddressRange CodeIndexBIOS7DSi[0x10000 / 512] {};
|
||||||
|
AddressRange CodeIndexNWRAM_A[DSi::NWRAMSize / 512] {};
|
||||||
|
AddressRange CodeIndexNWRAM_B[DSi::NWRAMSize / 512] {};
|
||||||
|
AddressRange CodeIndexNWRAM_C[DSi::NWRAMSize / 512] {};
|
||||||
|
|
||||||
void CompileBlock(ARM* cpu);
|
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2] {};
|
||||||
|
u64 FastBlockLookupMainRAM[NDS::MainRAMMaxSize / 2] {};
|
||||||
|
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2] {};
|
||||||
|
u64 FastBlockLookupVRAM[0x100000 / 2] {};
|
||||||
|
u64 FastBlockLookupARM9BIOS[sizeof(NDS::ARM9BIOS) / 2] {};
|
||||||
|
u64 FastBlockLookupARM7BIOS[sizeof(NDS::ARM7BIOS) / 2] {};
|
||||||
|
u64 FastBlockLookupARM7WRAM[NDS::ARM7WRAMSize / 2] {};
|
||||||
|
u64 FastBlockLookupARM7WVRAM[0x40000 / 2] {};
|
||||||
|
u64 FastBlockLookupBIOS9DSi[0x10000 / 2] {};
|
||||||
|
u64 FastBlockLookupBIOS7DSi[0x10000 / 2] {};
|
||||||
|
u64 FastBlockLookupNWRAM_A[DSi::NWRAMSize / 2] {};
|
||||||
|
u64 FastBlockLookupNWRAM_B[DSi::NWRAMSize / 2] {};
|
||||||
|
u64 FastBlockLookupNWRAM_C[DSi::NWRAMSize / 2] {};
|
||||||
|
|
||||||
void ResetBlockCache();
|
AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
CodeIndexITCM,
|
||||||
|
NULL,
|
||||||
|
CodeIndexARM9BIOS,
|
||||||
|
CodeIndexMainRAM,
|
||||||
|
CodeIndexSWRAM,
|
||||||
|
NULL,
|
||||||
|
CodeIndexVRAM,
|
||||||
|
CodeIndexARM7BIOS,
|
||||||
|
CodeIndexARM7WRAM,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
CodeIndexARM7WVRAM,
|
||||||
|
CodeIndexBIOS9DSi,
|
||||||
|
CodeIndexBIOS7DSi,
|
||||||
|
CodeIndexNWRAM_A,
|
||||||
|
CodeIndexNWRAM_B,
|
||||||
|
CodeIndexNWRAM_C
|
||||||
|
};
|
||||||
|
|
||||||
JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr);
|
u64* const FastBlockLookupRegions[ARMJIT_Memory::memregions_Count] =
|
||||||
bool SetupExecutableRegion(u32 num, u32 blockAddr, u64*& entry, u32& start, u32& size);
|
{
|
||||||
|
NULL,
|
||||||
void JitEnableWrite();
|
FastBlockLookupITCM,
|
||||||
void JitEnableExecute();
|
NULL,
|
||||||
|
FastBlockLookupARM9BIOS,
|
||||||
|
FastBlockLookupMainRAM,
|
||||||
|
FastBlockLookupSWRAM,
|
||||||
|
NULL,
|
||||||
|
FastBlockLookupVRAM,
|
||||||
|
FastBlockLookupARM7BIOS,
|
||||||
|
FastBlockLookupARM7WRAM,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
FastBlockLookupARM7WVRAM,
|
||||||
|
FastBlockLookupBIOS9DSi,
|
||||||
|
FastBlockLookupBIOS7DSi,
|
||||||
|
FastBlockLookupNWRAM_A,
|
||||||
|
FastBlockLookupNWRAM_B,
|
||||||
|
FastBlockLookupNWRAM_C
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defined in assembly
|
||||||
extern "C" void ARM_Dispatch(ARM* cpu, ARMJIT::JitBlockEntry entry);
|
extern "C" void ARM_Dispatch(ARM* cpu, ARMJIT::JitBlockEntry entry);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "../ARMJIT_Internal.h"
|
#include "../ARMJIT_Internal.h"
|
||||||
#include "../ARMInterpreter.h"
|
#include "../ARMInterpreter.h"
|
||||||
|
#include "../ARMJIT.h"
|
||||||
|
|
||||||
#if defined(__SWITCH__)
|
#if defined(__SWITCH__)
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
@ -219,7 +220,7 @@ void Compiler::PopRegs(bool saveHiRegs, bool saveRegsToBeChanged)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Compiler::Compiler()
|
Compiler::Compiler(ARMJIT& jit) : Arm64Gen::ARM64XEmitter(), JIT(jit)
|
||||||
{
|
{
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
JitRWBase = aligned_alloc(0x1000, JitMemSize);
|
JitRWBase = aligned_alloc(0x1000, JitMemSize);
|
||||||
|
@ -704,12 +705,12 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
|
||||||
if (JitMemMainSize - GetCodeOffset() < 1024 * 16)
|
if (JitMemMainSize - GetCodeOffset() < 1024 * 16)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "JIT near memory full, resetting...\n");
|
Log(LogLevel::Debug, "JIT near memory full, resetting...\n");
|
||||||
ResetBlockCache();
|
JIT.ResetBlockCache();
|
||||||
}
|
}
|
||||||
if ((JitMemMainSize + JitMemSecondarySize) - OtherCodeRegion < 1024 * 8)
|
if ((JitMemMainSize + JitMemSecondarySize) - OtherCodeRegion < 1024 * 8)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "JIT far memory full, resetting...\n");
|
Log(LogLevel::Debug, "JIT far memory full, resetting...\n");
|
||||||
ResetBlockCache();
|
JIT.ResetBlockCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
JitBlockEntry res = (JitBlockEntry)GetRXPtr();
|
JitBlockEntry res = (JitBlockEntry)GetRXPtr();
|
||||||
|
@ -722,7 +723,7 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
|
||||||
CPSRDirty = false;
|
CPSRDirty = false;
|
||||||
|
|
||||||
if (hasMemInstr)
|
if (hasMemInstr)
|
||||||
MOVP2R(RMemBase, Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
|
MOVP2R(RMemBase, Num == 0 ? JIT.Memory.FastMem9Start : JIT.Memory.FastMem7Start);
|
||||||
|
|
||||||
for (int i = 0; i < instrsCount; i++)
|
for (int i = 0; i < instrsCount; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#define ARMJIT_A64_COMPILER_H
|
#define ARMJIT_A64_COMPILER_H
|
||||||
|
|
||||||
#include "../ARM.h"
|
#include "../ARM.h"
|
||||||
#include "../ARMJIT.h"
|
|
||||||
|
|
||||||
#include "../dolphin/Arm64Emitter.h"
|
#include "../dolphin/Arm64Emitter.h"
|
||||||
|
|
||||||
|
@ -31,7 +30,7 @@
|
||||||
|
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
|
class ARMJIT;
|
||||||
const Arm64Gen::ARM64Reg RMemBase = Arm64Gen::X26;
|
const Arm64Gen::ARM64Reg RMemBase = Arm64Gen::X26;
|
||||||
const Arm64Gen::ARM64Reg RCPSR = Arm64Gen::W27;
|
const Arm64Gen::ARM64Reg RCPSR = Arm64Gen::W27;
|
||||||
const Arm64Gen::ARM64Reg RCycles = Arm64Gen::W28;
|
const Arm64Gen::ARM64Reg RCycles = Arm64Gen::W28;
|
||||||
|
@ -97,7 +96,7 @@ class Compiler : public Arm64Gen::ARM64XEmitter
|
||||||
public:
|
public:
|
||||||
typedef void (Compiler::*CompileFunc)();
|
typedef void (Compiler::*CompileFunc)();
|
||||||
|
|
||||||
Compiler();
|
Compiler(ARMJIT& jit);
|
||||||
~Compiler();
|
~Compiler();
|
||||||
|
|
||||||
void PushRegs(bool saveHiRegs, bool saveRegsToBeChanged, bool allowUnload = true);
|
void PushRegs(bool saveHiRegs, bool saveRegsToBeChanged, bool allowUnload = true);
|
||||||
|
@ -243,6 +242,7 @@ public:
|
||||||
OtherCodeRegion = offset;
|
OtherCodeRegion = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARMJIT& JIT;
|
||||||
ptrdiff_t OtherCodeRegion;
|
ptrdiff_t OtherCodeRegion;
|
||||||
|
|
||||||
bool Exit;
|
bool Exit;
|
||||||
|
|
|
@ -62,9 +62,9 @@ u8* Compiler::RewriteMemAccess(u8* pc)
|
||||||
|
|
||||||
bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
|
bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
|
||||||
{
|
{
|
||||||
u32 localAddr = LocaliseCodeAddress(Num, addr);
|
u32 localAddr = JIT.LocaliseCodeAddress(Num, addr);
|
||||||
|
|
||||||
int invalidLiteralIdx = InvalidLiterals.Find(localAddr);
|
int invalidLiteralIdx = JIT.InvalidLiterals.Find(localAddr);
|
||||||
if (invalidLiteralIdx != -1)
|
if (invalidLiteralIdx != -1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -111,7 +111,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
||||||
if (size == 16)
|
if (size == 16)
|
||||||
addressMask = ~1;
|
addressMask = ~1;
|
||||||
|
|
||||||
if (ARMJIT::LiteralOptimizations && rn == 15 && rd != 15 && offset.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
if (JIT.LiteralOptimizations && rn == 15 && rd != 15 && offset.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
||||||
{
|
{
|
||||||
u32 addr = R15 + offset.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
|
u32 addr = R15 + offset.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
||||||
MOV(W0, rnMapped);
|
MOV(W0, rnMapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addrIsStatic = ARMJIT::LiteralOptimizations
|
bool addrIsStatic = JIT.LiteralOptimizations
|
||||||
&& RegCache.IsLiteral(rn) && offset.IsImm && !(flags & (memop_Writeback|memop_Post));
|
&& RegCache.IsLiteral(rn) && offset.IsImm && !(flags & (memop_Writeback|memop_Post));
|
||||||
u32 staticAddress;
|
u32 staticAddress;
|
||||||
if (addrIsStatic)
|
if (addrIsStatic)
|
||||||
|
@ -185,10 +185,10 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
||||||
MOV(rnMapped, W0);
|
MOV(rnMapped, W0);
|
||||||
|
|
||||||
u32 expectedTarget = Num == 0
|
u32 expectedTarget = Num == 0
|
||||||
? ARMJIT_Memory::ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
|
? JIT.Memory.ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
|
: JIT.Memory.ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
|
||||||
|
|
||||||
if (ARMJIT::FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || ARMJIT_Memory::IsFastmemCompatible(expectedTarget)))
|
if (JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || JIT.Memory.IsFastmemCompatible(expectedTarget)))
|
||||||
{
|
{
|
||||||
ptrdiff_t memopStart = GetCodeOffset();
|
ptrdiff_t memopStart = GetCodeOffset();
|
||||||
LoadStorePatch patch;
|
LoadStorePatch patch;
|
||||||
|
@ -225,7 +225,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
||||||
{
|
{
|
||||||
void* func = NULL;
|
void* func = NULL;
|
||||||
if (addrIsStatic)
|
if (addrIsStatic)
|
||||||
func = ARMJIT_Memory::GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
func = JIT.Memory.GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
||||||
|
|
||||||
PushRegs(false, false);
|
PushRegs(false, false);
|
||||||
|
|
||||||
|
@ -452,7 +452,7 @@ void Compiler::T_Comp_LoadPCRel()
|
||||||
u32 offset = ((CurInstr.Instr & 0xFF) << 2);
|
u32 offset = ((CurInstr.Instr & 0xFF) << 2);
|
||||||
u32 addr = (R15 & ~0x2) + offset;
|
u32 addr = (R15 & ~0x2) + offset;
|
||||||
|
|
||||||
if (!ARMJIT::LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
if (!JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
||||||
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
|
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,11 +494,11 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
Comp_AddCycles_CDI();
|
Comp_AddCycles_CDI();
|
||||||
|
|
||||||
int expectedTarget = Num == 0
|
int expectedTarget = Num == 0
|
||||||
? ARMJIT_Memory::ClassifyAddress9(CurInstr.DataRegion)
|
? JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
|
: JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||||
|
|
||||||
bool compileFastPath = ARMJIT::FastMemory
|
bool compileFastPath = JIT.FastMemory
|
||||||
&& store && !usermode && (CurInstr.Cond() < 0xE || ARMJIT_Memory::IsFastmemCompatible(expectedTarget));
|
&& store && !usermode && (CurInstr.Cond() < 0xE || JIT.Memory.IsFastmemCompatible(expectedTarget));
|
||||||
|
|
||||||
{
|
{
|
||||||
s32 offset = decrement
|
s32 offset = decrement
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
#ifndef ARMJIT_COMPILER_H
|
#ifndef ARMJIT_COMPILER_H
|
||||||
#define ARMJIT_COMPILER_H
|
#define ARMJIT_COMPILER_H
|
||||||
|
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
|
#define NOOP_IF_NO_JIT
|
||||||
|
#else
|
||||||
|
#define NOOP_IF_NO_JIT {}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
#include "ARMJIT_x64/ARMJIT_Compiler.h"
|
#include "ARMJIT_x64/ARMJIT_Compiler.h"
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
|
@ -27,9 +33,4 @@
|
||||||
#error "The current target platform doesn't have a JIT backend"
|
#error "The current target platform doesn't have a JIT backend"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ARMJIT
|
|
||||||
{
|
|
||||||
extern Compiler* JITCompiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,8 +24,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "ARMJIT.h"
|
#include "ARM_InstrInfo.h"
|
||||||
#include "ARMJIT_Memory.h"
|
#include "JitBlock.h"
|
||||||
|
#include "TinyVector.h"
|
||||||
|
|
||||||
|
class ARM;
|
||||||
|
class ARMv5;
|
||||||
|
|
||||||
// here lands everything which doesn't fit into ARMJIT.h
|
// here lands everything which doesn't fit into ARMJIT.h
|
||||||
// where it would be included by pretty much everything
|
// where it would be included by pretty much everything
|
||||||
|
@ -69,139 +73,6 @@ struct FetchedInstr
|
||||||
ARMInstrInfo::Info Info;
|
ARMInstrInfo::Info Info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
TinyVector
|
|
||||||
- because reinventing the wheel is the best!
|
|
||||||
|
|
||||||
- meant to be used very often, with not so many elements
|
|
||||||
max 1 << 16 elements
|
|
||||||
- doesn't allocate while no elements are inserted
|
|
||||||
- not stl confirmant of course
|
|
||||||
- probably only works with POD types
|
|
||||||
- remove operations don't preserve order, but O(1)!
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
struct __attribute__((packed)) TinyVector
|
|
||||||
{
|
|
||||||
T* Data = NULL;
|
|
||||||
u16 Capacity = 0;
|
|
||||||
u16 Length = 0;
|
|
||||||
|
|
||||||
~TinyVector()
|
|
||||||
{
|
|
||||||
delete[] Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MakeCapacity(u32 capacity)
|
|
||||||
{
|
|
||||||
assert(capacity <= UINT16_MAX);
|
|
||||||
assert(capacity > Capacity);
|
|
||||||
T* newMem = new T[capacity];
|
|
||||||
if (Data != NULL)
|
|
||||||
memcpy(newMem, Data, sizeof(T) * Length);
|
|
||||||
|
|
||||||
T* oldData = Data;
|
|
||||||
Data = newMem;
|
|
||||||
if (oldData != NULL)
|
|
||||||
delete[] oldData;
|
|
||||||
|
|
||||||
Capacity = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetLength(u16 length)
|
|
||||||
{
|
|
||||||
if (Capacity < length)
|
|
||||||
MakeCapacity(length);
|
|
||||||
|
|
||||||
Length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
Length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Add(T element)
|
|
||||||
{
|
|
||||||
assert(Length + 1 <= UINT16_MAX);
|
|
||||||
if (Length + 1 > Capacity)
|
|
||||||
MakeCapacity(((Capacity + 4) * 3) / 2);
|
|
||||||
|
|
||||||
Data[Length++] = element;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Remove(int index)
|
|
||||||
{
|
|
||||||
assert(Length > 0);
|
|
||||||
assert(index >= 0 && index < Length);
|
|
||||||
|
|
||||||
Length--;
|
|
||||||
Data[index] = Data[Length];
|
|
||||||
/*for (int i = index; i < Length; i++)
|
|
||||||
Data[i] = Data[i + 1];*/
|
|
||||||
}
|
|
||||||
|
|
||||||
int Find(T needle)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Length; i++)
|
|
||||||
{
|
|
||||||
if (Data[i] == needle)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RemoveByValue(T needle)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Length; i++)
|
|
||||||
{
|
|
||||||
if (Data[i] == needle)
|
|
||||||
{
|
|
||||||
Remove(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator[](int index)
|
|
||||||
{
|
|
||||||
assert(index >= 0 && index < Length);
|
|
||||||
return Data[index];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class JitBlock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
JitBlock(u32 num, u32 literalHash, u32 numAddresses, u32 numLiterals)
|
|
||||||
{
|
|
||||||
Num = num;
|
|
||||||
NumAddresses = numAddresses;
|
|
||||||
NumLiterals = numLiterals;
|
|
||||||
Data.SetLength(numAddresses * 2 + numLiterals);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 StartAddr;
|
|
||||||
u32 StartAddrLocal;
|
|
||||||
u32 InstrHash, LiteralHash;
|
|
||||||
u8 Num;
|
|
||||||
u16 NumAddresses;
|
|
||||||
u16 NumLiterals;
|
|
||||||
|
|
||||||
JitBlockEntry EntryPoint;
|
|
||||||
|
|
||||||
u32* AddressRanges()
|
|
||||||
{ return &Data[0]; }
|
|
||||||
u32* AddressMasks()
|
|
||||||
{ return &Data[NumAddresses]; }
|
|
||||||
u32* Literals()
|
|
||||||
{ return &Data[NumAddresses * 2]; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
TinyVector<u32> Data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// size should be 16 bytes because I'm to lazy to use mul and whatnot
|
// size should be 16 bytes because I'm to lazy to use mul and whatnot
|
||||||
struct __attribute__((packed)) AddressRange
|
struct __attribute__((packed)) AddressRange
|
||||||
{
|
{
|
||||||
|
@ -214,10 +85,6 @@ typedef void (*InterpreterFunc)(ARM* cpu);
|
||||||
extern InterpreterFunc InterpretARM[];
|
extern InterpreterFunc InterpretARM[];
|
||||||
extern InterpreterFunc InterpretTHUMB[];
|
extern InterpreterFunc InterpretTHUMB[];
|
||||||
|
|
||||||
extern TinyVector<u32> InvalidLiterals;
|
|
||||||
|
|
||||||
extern AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count];
|
|
||||||
|
|
||||||
inline bool PageContainsCode(AddressRange* range)
|
inline bool PageContainsCode(AddressRange* range)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
|
@ -228,11 +95,6 @@ inline bool PageContainsCode(AddressRange* range)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 LocaliseCodeAddress(u32 num, u32 addr);
|
|
||||||
|
|
||||||
template <u32 Num>
|
|
||||||
void LinkBlock(ARM* cpu, u32 codeOffset);
|
|
||||||
|
|
||||||
template <typename T, int ConsoleType> T SlowRead9(u32 addr, ARMv5* cpu);
|
template <typename T, int ConsoleType> T SlowRead9(u32 addr, ARMv5* cpu);
|
||||||
template <typename T, int ConsoleType> void SlowWrite9(u32 addr, ARMv5* cpu, u32 val);
|
template <typename T, int ConsoleType> void SlowWrite9(u32 addr, ARMv5* cpu, u32 val);
|
||||||
template <typename T, int ConsoleType> T SlowRead7(u32 addr);
|
template <typename T, int ConsoleType> T SlowRead7(u32 addr);
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "ARMJIT.h"
|
||||||
#include "ARMJIT_Memory.h"
|
#include "ARMJIT_Memory.h"
|
||||||
|
|
||||||
#include "ARMJIT_Internal.h"
|
#include "ARMJIT_Internal.h"
|
||||||
|
@ -72,17 +73,6 @@ using Platform::LogLevel;
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace ARMJIT_Memory
|
|
||||||
{
|
|
||||||
struct FaultDescription
|
|
||||||
{
|
|
||||||
u32 EmulatedFaultAddr;
|
|
||||||
u8* FaultPC;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool FaultHandler(FaultDescription& faultDesc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Yes I know this looks messy, but better here than somewhere else in the code
|
// Yes I know this looks messy, but better here than somewhere else in the code
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -112,7 +102,6 @@ bool FaultHandler(FaultDescription& faultDesc);
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define ASHMEM_DEVICE "/dev/ashmem"
|
#define ASHMEM_DEVICE "/dev/ashmem"
|
||||||
Platform::DynamicLibrary* Libandroid = nullptr;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__SWITCH__)
|
#if defined(__SWITCH__)
|
||||||
|
@ -146,7 +135,7 @@ void __libnx_exception_handler(ThreadExceptionDump* ctx)
|
||||||
integerRegisters[31] = ctx->sp.x;
|
integerRegisters[31] = ctx->sp.x;
|
||||||
integerRegisters[32] = ctx->pc.x;
|
integerRegisters[32] = ctx->pc.x;
|
||||||
|
|
||||||
if (ARMJIT_Memory::FaultHandler(desc))
|
if (Melon::FaultHandler(desc))
|
||||||
{
|
{
|
||||||
integerRegisters[32] = (u64)desc.FaultPC;
|
integerRegisters[32] = (u64)desc.FaultPC;
|
||||||
|
|
||||||
|
@ -160,19 +149,19 @@ void __libnx_exception_handler(ThreadExceptionDump* ctx)
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
|
|
||||||
static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
|
LONG ARMJIT_Memory::ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
|
||||||
{
|
{
|
||||||
if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
||||||
{
|
{
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMJIT_Memory::FaultDescription desc;
|
u8* curArea = (u8*)(NDS::CurCPU == 0 ? NDS::JIT->Memory.FastMem9Start : NDS::JIT->Memory.FastMem7Start);
|
||||||
u8* curArea = (u8*)(NDS::CurCPU == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
|
FaultDescription desc {};
|
||||||
desc.EmulatedFaultAddr = (u8*)exceptionInfo->ExceptionRecord->ExceptionInformation[1] - curArea;
|
desc.EmulatedFaultAddr = (u8*)exceptionInfo->ExceptionRecord->ExceptionInformation[1] - curArea;
|
||||||
desc.FaultPC = (u8*)exceptionInfo->ContextRecord->CONTEXT_PC;
|
desc.FaultPC = (u8*)exceptionInfo->ContextRecord->CONTEXT_PC;
|
||||||
|
|
||||||
if (ARMJIT_Memory::FaultHandler(desc))
|
if (FaultHandler(desc, *NDS::JIT))
|
||||||
{
|
{
|
||||||
exceptionInfo->ContextRecord->CONTEXT_PC = (u64)desc.FaultPC;
|
exceptionInfo->ContextRecord->CONTEXT_PC = (u64)desc.FaultPC;
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
@ -186,7 +175,7 @@ static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
|
||||||
static struct sigaction OldSaSegv;
|
static struct sigaction OldSaSegv;
|
||||||
static struct sigaction OldSaBus;
|
static struct sigaction OldSaBus;
|
||||||
|
|
||||||
static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
|
void ARMJIT_Memory::SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
|
||||||
{
|
{
|
||||||
if (sig != SIGSEGV && sig != SIGBUS)
|
if (sig != SIGSEGV && sig != SIGBUS)
|
||||||
{
|
{
|
||||||
|
@ -201,13 +190,13 @@ static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
|
||||||
|
|
||||||
ucontext_t* context = (ucontext_t*)rawContext;
|
ucontext_t* context = (ucontext_t*)rawContext;
|
||||||
|
|
||||||
ARMJIT_Memory::FaultDescription desc;
|
FaultDescription desc {};
|
||||||
u8* curArea = (u8*)(NDS::CurCPU == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
|
u8* curArea = (u8*)(NDS::CurCPU == 0 ? NDS::JIT->Memory.FastMem9Start : NDS::JIT->Memory.FastMem7Start);
|
||||||
|
|
||||||
desc.EmulatedFaultAddr = (u8*)info->si_addr - curArea;
|
desc.EmulatedFaultAddr = (u8*)info->si_addr - curArea;
|
||||||
desc.FaultPC = (u8*)context->CONTEXT_PC;
|
desc.FaultPC = (u8*)context->CONTEXT_PC;
|
||||||
|
|
||||||
if (ARMJIT_Memory::FaultHandler(desc))
|
if (FaultHandler(desc, *NDS::JIT))
|
||||||
{
|
{
|
||||||
context->CONTEXT_PC = (u64)desc.FaultPC;
|
context->CONTEXT_PC = (u64)desc.FaultPC;
|
||||||
return;
|
return;
|
||||||
|
@ -239,33 +228,7 @@ static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ARMJIT_Memory
|
const u32 OffsetsPerRegion[ARMJIT_Memory::memregions_Count] =
|
||||||
{
|
|
||||||
|
|
||||||
void* FastMem9Start, *FastMem7Start;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
inline u32 RoundUp(u32 size)
|
|
||||||
{
|
|
||||||
return (size + 0xFFFF) & ~0xFFFF;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
inline u32 RoundUp(u32 size)
|
|
||||||
{
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const u32 MemBlockMainRAMOffset = 0;
|
|
||||||
const u32 MemBlockSWRAMOffset = RoundUp(NDS::MainRAMMaxSize);
|
|
||||||
const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(NDS::SharedWRAMSize);
|
|
||||||
const u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(NDS::ARM7WRAMSize);
|
|
||||||
const u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize);
|
|
||||||
const u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(DSi::NWRAMSize);
|
|
||||||
const u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(DSi::NWRAMSize);
|
|
||||||
const u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(DSi::NWRAMSize);
|
|
||||||
|
|
||||||
const u32 OffsetsPerRegion[memregions_Count] =
|
|
||||||
{
|
{
|
||||||
UINT32_MAX,
|
UINT32_MAX,
|
||||||
UINT32_MAX,
|
UINT32_MAX,
|
||||||
|
@ -295,23 +258,9 @@ enum
|
||||||
memstate_MappedProtected,
|
memstate_MappedProtected,
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 MappingStatus9[1 << (32-12)];
|
|
||||||
u8 MappingStatus7[1 << (32-12)];
|
|
||||||
|
|
||||||
#if defined(__SWITCH__)
|
|
||||||
VirtmemReservation* FastMem9Reservation, *FastMem7Reservation;
|
|
||||||
u8* MemoryBase;
|
|
||||||
u8* MemoryBaseCodeMem;
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
u8* MemoryBase;
|
|
||||||
HANDLE MemoryFile;
|
|
||||||
LPVOID ExceptionHandlerHandle;
|
|
||||||
#else
|
|
||||||
u8* MemoryBase;
|
|
||||||
int MemoryFile = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
|
bool ARMJIT_Memory::MapIntoRange(u32 addr, u32 num, u32 offset, u32 size) noexcept
|
||||||
{
|
{
|
||||||
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
|
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
|
@ -326,7 +275,7 @@ bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size)
|
bool ARMJIT_Memory::UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size) noexcept
|
||||||
{
|
{
|
||||||
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
|
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
|
@ -341,7 +290,7 @@ bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
|
void ARMJIT_Memory::SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection) noexcept
|
||||||
{
|
{
|
||||||
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
|
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
@ -367,18 +316,12 @@ void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Mapping
|
void ARMJIT_Memory::Mapping::Unmap(int region, ARMJIT_Memory& memory) noexcept
|
||||||
{
|
{
|
||||||
u32 Addr;
|
|
||||||
u32 Size, LocalOffset;
|
|
||||||
u32 Num;
|
|
||||||
|
|
||||||
void Unmap(int region)
|
|
||||||
{
|
|
||||||
u32 dtcmStart = NDS::ARM9->DTCMBase;
|
u32 dtcmStart = NDS::ARM9->DTCMBase;
|
||||||
u32 dtcmSize = ~NDS::ARM9->DTCMMask + 1;
|
u32 dtcmSize = ~NDS::ARM9->DTCMMask + 1;
|
||||||
bool skipDTCM = Num == 0 && region != memregion_DTCM;
|
bool skipDTCM = Num == 0 && region != memregion_DTCM;
|
||||||
u8* statuses = Num == 0 ? MappingStatus9 : MappingStatus7;
|
u8* statuses = Num == 0 ? memory.MappingStatus9 : memory.MappingStatus7;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
while (offset < Size)
|
while (offset < Size)
|
||||||
{
|
{
|
||||||
|
@ -404,7 +347,7 @@ struct Mapping
|
||||||
{
|
{
|
||||||
u32 segmentSize = offset - segmentOffset;
|
u32 segmentSize = offset - segmentOffset;
|
||||||
Log(LogLevel::Debug, "unmapping %x %x %x %x\n", Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
|
Log(LogLevel::Debug, "unmapping %x %x %x %x\n", Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
|
||||||
bool success = UnmapFromRange(Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
|
bool success = memory.UnmapFromRange(Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
|
||||||
assert(success);
|
assert(success);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -421,28 +364,26 @@ struct Mapping
|
||||||
bool success;
|
bool success;
|
||||||
if (dtcmStart > Addr)
|
if (dtcmStart > Addr)
|
||||||
{
|
{
|
||||||
success = UnmapFromRange(Addr, 0, OffsetsPerRegion[region] + LocalOffset, dtcmStart - Addr);
|
success = memory.UnmapFromRange(Addr, 0, OffsetsPerRegion[region] + LocalOffset, dtcmStart - Addr);
|
||||||
assert(success);
|
assert(success);
|
||||||
}
|
}
|
||||||
if (dtcmEnd < Addr + Size)
|
if (dtcmEnd < Addr + Size)
|
||||||
{
|
{
|
||||||
u32 offset = dtcmStart - Addr + dtcmSize;
|
u32 offset = dtcmStart - Addr + dtcmSize;
|
||||||
success = UnmapFromRange(dtcmEnd, 0, OffsetsPerRegion[region] + LocalOffset + offset, Size - offset);
|
success = memory.UnmapFromRange(dtcmEnd, 0, OffsetsPerRegion[region] + LocalOffset + offset, Size - offset);
|
||||||
assert(success);
|
assert(success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
bool succeded = UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
|
bool succeded = memory.UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
|
||||||
assert(succeded);
|
assert(succeded);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
|
||||||
ARMJIT::TinyVector<Mapping> Mappings[memregions_Count];
|
|
||||||
|
|
||||||
void SetCodeProtection(int region, u32 offset, bool protect)
|
void ARMJIT_Memory::SetCodeProtection(int region, u32 offset, bool protect) noexcept
|
||||||
{
|
{
|
||||||
offset &= ~0xFFF;
|
offset &= ~0xFFF;
|
||||||
//printf("set code protection %d %x %d\n", region, offset, protect);
|
//printf("set code protection %d %x %d\n", region, offset, protect);
|
||||||
|
@ -479,7 +420,7 @@ void SetCodeProtection(int region, u32 offset, bool protect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemapDTCM(u32 newBase, u32 newSize)
|
void ARMJIT_Memory::RemapDTCM(u32 newBase, u32 newSize) noexcept
|
||||||
{
|
{
|
||||||
// this first part could be made more efficient
|
// this first part could be made more efficient
|
||||||
// by unmapping DTCM first and then map the holes
|
// by unmapping DTCM first and then map the holes
|
||||||
|
@ -510,7 +451,7 @@ void RemapDTCM(u32 newBase, u32 newSize)
|
||||||
|
|
||||||
if (mapping.Num == 0 && overlap)
|
if (mapping.Num == 0 && overlap)
|
||||||
{
|
{
|
||||||
mapping.Unmap(region);
|
mapping.Unmap(region, *this);
|
||||||
Mappings[region].Remove(i);
|
Mappings[region].Remove(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -522,12 +463,12 @@ void RemapDTCM(u32 newBase, u32 newSize)
|
||||||
|
|
||||||
for (int i = 0; i < Mappings[memregion_DTCM].Length; i++)
|
for (int i = 0; i < Mappings[memregion_DTCM].Length; i++)
|
||||||
{
|
{
|
||||||
Mappings[memregion_DTCM][i].Unmap(memregion_DTCM);
|
Mappings[memregion_DTCM][i].Unmap(memregion_DTCM, *this);
|
||||||
}
|
}
|
||||||
Mappings[memregion_DTCM].Clear();
|
Mappings[memregion_DTCM].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemapNWRAM(int num)
|
void ARMJIT_Memory::RemapNWRAM(int num) noexcept
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length;)
|
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length;)
|
||||||
{
|
{
|
||||||
|
@ -535,7 +476,7 @@ void RemapNWRAM(int num)
|
||||||
if (DSi::NWRAMStart[mapping.Num][num] < mapping.Addr + mapping.Size
|
if (DSi::NWRAMStart[mapping.Num][num] < mapping.Addr + mapping.Size
|
||||||
&& DSi::NWRAMEnd[mapping.Num][num] > mapping.Addr)
|
&& DSi::NWRAMEnd[mapping.Num][num] > mapping.Addr)
|
||||||
{
|
{
|
||||||
mapping.Unmap(memregion_SharedWRAM);
|
mapping.Unmap(memregion_SharedWRAM, *this);
|
||||||
Mappings[memregion_SharedWRAM].Remove(i);
|
Mappings[memregion_SharedWRAM].Remove(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -545,12 +486,12 @@ void RemapNWRAM(int num)
|
||||||
}
|
}
|
||||||
for (int i = 0; i < Mappings[memregion_NewSharedWRAM_A + num].Length; i++)
|
for (int i = 0; i < Mappings[memregion_NewSharedWRAM_A + num].Length; i++)
|
||||||
{
|
{
|
||||||
Mappings[memregion_NewSharedWRAM_A + num][i].Unmap(memregion_NewSharedWRAM_A + num);
|
Mappings[memregion_NewSharedWRAM_A + num][i].Unmap(memregion_NewSharedWRAM_A + num, *this);
|
||||||
}
|
}
|
||||||
Mappings[memregion_NewSharedWRAM_A + num].Clear();
|
Mappings[memregion_NewSharedWRAM_A + num].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemapSWRAM()
|
void ARMJIT_Memory::RemapSWRAM() noexcept
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "remapping SWRAM\n");
|
Log(LogLevel::Debug, "remapping SWRAM\n");
|
||||||
for (int i = 0; i < Mappings[memregion_WRAM7].Length;)
|
for (int i = 0; i < Mappings[memregion_WRAM7].Length;)
|
||||||
|
@ -558,7 +499,7 @@ void RemapSWRAM()
|
||||||
Mapping& mapping = Mappings[memregion_WRAM7][i];
|
Mapping& mapping = Mappings[memregion_WRAM7][i];
|
||||||
if (mapping.Addr + mapping.Size <= 0x03800000)
|
if (mapping.Addr + mapping.Size <= 0x03800000)
|
||||||
{
|
{
|
||||||
mapping.Unmap(memregion_WRAM7);
|
mapping.Unmap(memregion_WRAM7, *this);
|
||||||
Mappings[memregion_WRAM7].Remove(i);
|
Mappings[memregion_WRAM7].Remove(i);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -566,12 +507,12 @@ void RemapSWRAM()
|
||||||
}
|
}
|
||||||
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length; i++)
|
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length; i++)
|
||||||
{
|
{
|
||||||
Mappings[memregion_SharedWRAM][i].Unmap(memregion_SharedWRAM);
|
Mappings[memregion_SharedWRAM][i].Unmap(memregion_SharedWRAM, *this);
|
||||||
}
|
}
|
||||||
Mappings[memregion_SharedWRAM].Clear();
|
Mappings[memregion_SharedWRAM].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapAtAddress(u32 addr)
|
bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
|
||||||
{
|
{
|
||||||
u32 num = NDS::CurCPU;
|
u32 num = NDS::CurCPU;
|
||||||
|
|
||||||
|
@ -589,7 +530,7 @@ bool MapAtAddress(u32 addr)
|
||||||
|
|
||||||
u8* states = num == 0 ? MappingStatus9 : MappingStatus7;
|
u8* states = num == 0 ? MappingStatus9 : MappingStatus7;
|
||||||
//printf("mapping mirror %x, %x %x %d %d\n", mirrorStart, mirrorSize, memoryOffset, region, num);
|
//printf("mapping mirror %x, %x %x %d %d\n", mirrorStart, mirrorSize, memoryOffset, region, num);
|
||||||
bool isExecutable = ARMJIT::CodeMemRegions[region];
|
bool isExecutable = JIT.CodeMemRegions[region];
|
||||||
|
|
||||||
u32 dtcmStart = NDS::ARM9->DTCMBase;
|
u32 dtcmStart = NDS::ARM9->DTCMBase;
|
||||||
u32 dtcmSize = ~NDS::ARM9->DTCMMask + 1;
|
u32 dtcmSize = ~NDS::ARM9->DTCMMask + 1;
|
||||||
|
@ -621,7 +562,7 @@ bool MapAtAddress(u32 addr)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ARMJIT::AddressRange* range = ARMJIT::CodeMemRegions[region] + memoryOffset / 512;
|
ARMJIT::AddressRange* range = JIT.CodeMemRegions[region] + memoryOffset / 512;
|
||||||
|
|
||||||
// this overcomplicated piece of code basically just finds whole pieces of code memory
|
// this overcomplicated piece of code basically just finds whole pieces of code memory
|
||||||
// which can be mapped/protected
|
// which can be mapped/protected
|
||||||
|
@ -676,19 +617,19 @@ bool MapAtAddress(u32 addr)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FaultHandler(FaultDescription& faultDesc)
|
bool ARMJIT_Memory::FaultHandler(FaultDescription& faultDesc, ARMJIT::ARMJIT& jit)
|
||||||
{
|
{
|
||||||
if (ARMJIT::JITCompiler->IsJITFault(faultDesc.FaultPC))
|
if (jit.JITCompiler.IsJITFault(faultDesc.FaultPC))
|
||||||
{
|
{
|
||||||
bool rewriteToSlowPath = true;
|
bool rewriteToSlowPath = true;
|
||||||
|
|
||||||
u8* memStatus = NDS::CurCPU == 0 ? MappingStatus9 : MappingStatus7;
|
u8* memStatus = NDS::CurCPU == 0 ? jit.Memory.MappingStatus9 : jit.Memory.MappingStatus7;
|
||||||
|
|
||||||
if (memStatus[faultDesc.EmulatedFaultAddr >> 12] == memstate_Unmapped)
|
if (memStatus[faultDesc.EmulatedFaultAddr >> 12] == memstate_Unmapped)
|
||||||
rewriteToSlowPath = !MapAtAddress(faultDesc.EmulatedFaultAddr);
|
rewriteToSlowPath = !jit.Memory.MapAtAddress(faultDesc.EmulatedFaultAddr);
|
||||||
|
|
||||||
if (rewriteToSlowPath)
|
if (rewriteToSlowPath)
|
||||||
faultDesc.FaultPC = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc.FaultPC);
|
faultDesc.FaultPC = jit.JITCompiler.RewriteMemAccess(faultDesc.FaultPC);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -697,7 +638,7 @@ bool FaultHandler(FaultDescription& faultDesc)
|
||||||
|
|
||||||
const u64 AddrSpaceSize = 0x100000000;
|
const u64 AddrSpaceSize = 0x100000000;
|
||||||
|
|
||||||
void Init()
|
ARMJIT_Memory::ARMJIT_Memory(ARMJIT::ARMJIT& jit) noexcept : JIT(jit)
|
||||||
{
|
{
|
||||||
#if defined(__SWITCH__)
|
#if defined(__SWITCH__)
|
||||||
MemoryBase = (u8*)aligned_alloc(0x1000, MemoryTotalSize);
|
MemoryBase = (u8*)aligned_alloc(0x1000, MemoryTotalSize);
|
||||||
|
@ -740,8 +681,6 @@ void Init()
|
||||||
MemoryBase = MemoryBase + AddrSpaceSize*3;
|
MemoryBase = MemoryBase + AddrSpaceSize*3;
|
||||||
|
|
||||||
MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, MemoryTotalSize, MemoryBase);
|
MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, MemoryTotalSize, MemoryBase);
|
||||||
|
|
||||||
u8* basePtr = MemoryBase;
|
|
||||||
#else
|
#else
|
||||||
// this used to be allocated with three different mmaps
|
// this used to be allocated with three different mmaps
|
||||||
// The idea was to give the OS more freedom where to position the buffers,
|
// The idea was to give the OS more freedom where to position the buffers,
|
||||||
|
@ -798,16 +737,9 @@ void Init()
|
||||||
|
|
||||||
u8* basePtr = MemoryBase;
|
u8* basePtr = MemoryBase;
|
||||||
#endif
|
#endif
|
||||||
NDS::MainRAM = basePtr + MemBlockMainRAMOffset;
|
|
||||||
NDS::SharedWRAM = basePtr + MemBlockSWRAMOffset;
|
|
||||||
NDS::ARM7WRAM = basePtr + MemBlockARM7WRAMOffset;
|
|
||||||
NDS::ARM9->DTCM = basePtr + MemBlockDTCMOffset;
|
|
||||||
DSi::NWRAM_A = basePtr + MemBlockNWRAM_AOffset;
|
|
||||||
DSi::NWRAM_B = basePtr + MemBlockNWRAM_BOffset;
|
|
||||||
DSi::NWRAM_C = basePtr + MemBlockNWRAM_COffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeInit()
|
ARMJIT_Memory::~ARMJIT_Memory() noexcept
|
||||||
{
|
{
|
||||||
#if defined(__SWITCH__)
|
#if defined(__SWITCH__)
|
||||||
virtmemLock();
|
virtmemLock();
|
||||||
|
@ -875,12 +807,12 @@ void DeInit()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void ARMJIT_Memory::Reset() noexcept
|
||||||
{
|
{
|
||||||
for (int region = 0; region < memregions_Count; region++)
|
for (int region = 0; region < memregions_Count; region++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Mappings[region].Length; i++)
|
for (int i = 0; i < Mappings[region].Length; i++)
|
||||||
Mappings[region][i].Unmap(region);
|
Mappings[region][i].Unmap(region, *this);
|
||||||
Mappings[region].Clear();
|
Mappings[region].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,7 +825,7 @@ void Reset()
|
||||||
Log(LogLevel::Debug, "done resetting jit mem\n");
|
Log(LogLevel::Debug, "done resetting jit mem\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsFastmemCompatible(int region)
|
bool ARMJIT_Memory::IsFastmemCompatible(int region) const noexcept
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/*
|
/*
|
||||||
|
@ -909,7 +841,7 @@ bool IsFastmemCompatible(int region)
|
||||||
return OffsetsPerRegion[region] != UINT32_MAX;
|
return OffsetsPerRegion[region] != UINT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mirrorStart, u32& mirrorSize)
|
bool ARMJIT_Memory::GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mirrorStart, u32& mirrorSize) const noexcept
|
||||||
{
|
{
|
||||||
memoryOffset = 0;
|
memoryOffset = 0;
|
||||||
switch (region)
|
switch (region)
|
||||||
|
@ -955,14 +887,14 @@ bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mi
|
||||||
{
|
{
|
||||||
mirrorStart = addr & ~NDS::SWRAM_ARM9.Mask;
|
mirrorStart = addr & ~NDS::SWRAM_ARM9.Mask;
|
||||||
mirrorSize = NDS::SWRAM_ARM9.Mask + 1;
|
mirrorSize = NDS::SWRAM_ARM9.Mask + 1;
|
||||||
memoryOffset = NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM;
|
memoryOffset = NDS::SWRAM_ARM9.Mem - GetSharedWRAM();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (num == 1 && NDS::SWRAM_ARM7.Mem)
|
else if (num == 1 && NDS::SWRAM_ARM7.Mem)
|
||||||
{
|
{
|
||||||
mirrorStart = addr & ~NDS::SWRAM_ARM7.Mask;
|
mirrorStart = addr & ~NDS::SWRAM_ARM7.Mask;
|
||||||
mirrorSize = NDS::SWRAM_ARM7.Mask + 1;
|
mirrorSize = NDS::SWRAM_ARM7.Mask + 1;
|
||||||
memoryOffset = NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM;
|
memoryOffset = NDS::SWRAM_ARM7.Mem - GetSharedWRAM();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -995,7 +927,7 @@ bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mi
|
||||||
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
|
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
memoryOffset = ptr - DSi::NWRAM_A;
|
memoryOffset = ptr - GetNWRAM_A();
|
||||||
mirrorStart = addr & ~0xFFFF;
|
mirrorStart = addr & ~0xFFFF;
|
||||||
mirrorSize = 0x10000;
|
mirrorSize = 0x10000;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1007,7 +939,7 @@ bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mi
|
||||||
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
|
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
memoryOffset = ptr - DSi::NWRAM_B;
|
memoryOffset = ptr - GetNWRAM_B();
|
||||||
mirrorStart = addr & ~0x7FFF;
|
mirrorStart = addr & ~0x7FFF;
|
||||||
mirrorSize = 0x8000;
|
mirrorSize = 0x8000;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1019,7 +951,7 @@ bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mi
|
||||||
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
|
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
memoryOffset = ptr - DSi::NWRAM_C;
|
memoryOffset = ptr - GetNWRAM_C();
|
||||||
mirrorStart = addr & ~0x7FFF;
|
mirrorStart = addr & ~0x7FFF;
|
||||||
mirrorSize = 0x8000;
|
mirrorSize = 0x8000;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1048,7 +980,7 @@ bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 LocaliseAddress(int region, u32 num, u32 addr)
|
u32 ARMJIT_Memory::LocaliseAddress(int region, u32 num, u32 addr) const noexcept
|
||||||
{
|
{
|
||||||
switch (region)
|
switch (region)
|
||||||
{
|
{
|
||||||
|
@ -1062,9 +994,9 @@ u32 LocaliseAddress(int region, u32 num, u32 addr)
|
||||||
return (addr & 0x3FFF) | (memregion_BIOS7 << 27);
|
return (addr & 0x3FFF) | (memregion_BIOS7 << 27);
|
||||||
case memregion_SharedWRAM:
|
case memregion_SharedWRAM:
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
return ((addr & NDS::SWRAM_ARM9.Mask) + (NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM)) | (memregion_SharedWRAM << 27);
|
return ((addr & NDS::SWRAM_ARM9.Mask) + (NDS::SWRAM_ARM9.Mem - GetSharedWRAM())) | (memregion_SharedWRAM << 27);
|
||||||
else
|
else
|
||||||
return ((addr & NDS::SWRAM_ARM7.Mask) + (NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM)) | (memregion_SharedWRAM << 27);
|
return ((addr & NDS::SWRAM_ARM7.Mask) + (NDS::SWRAM_ARM7.Mem - GetSharedWRAM())) | (memregion_SharedWRAM << 27);
|
||||||
case memregion_WRAM7:
|
case memregion_WRAM7:
|
||||||
return (addr & (NDS::ARM7WRAMSize - 1)) | (memregion_WRAM7 << 27);
|
return (addr & (NDS::ARM7WRAMSize - 1)) | (memregion_WRAM7 << 27);
|
||||||
case memregion_VRAM:
|
case memregion_VRAM:
|
||||||
|
@ -1077,7 +1009,7 @@ u32 LocaliseAddress(int region, u32 num, u32 addr)
|
||||||
{
|
{
|
||||||
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
|
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
|
||||||
if (ptr)
|
if (ptr)
|
||||||
return (ptr - DSi::NWRAM_A + (addr & 0xFFFF)) | (memregion_NewSharedWRAM_A << 27);
|
return (ptr - GetNWRAM_A() + (addr & 0xFFFF)) | (memregion_NewSharedWRAM_A << 27);
|
||||||
else
|
else
|
||||||
return memregion_Other << 27; // zero filled memory
|
return memregion_Other << 27; // zero filled memory
|
||||||
}
|
}
|
||||||
|
@ -1085,7 +1017,7 @@ u32 LocaliseAddress(int region, u32 num, u32 addr)
|
||||||
{
|
{
|
||||||
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
|
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
|
||||||
if (ptr)
|
if (ptr)
|
||||||
return (ptr - DSi::NWRAM_B + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_B << 27);
|
return (ptr - GetNWRAM_B() + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_B << 27);
|
||||||
else
|
else
|
||||||
return memregion_Other << 27;
|
return memregion_Other << 27;
|
||||||
}
|
}
|
||||||
|
@ -1093,7 +1025,7 @@ u32 LocaliseAddress(int region, u32 num, u32 addr)
|
||||||
{
|
{
|
||||||
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
|
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
|
||||||
if (ptr)
|
if (ptr)
|
||||||
return (ptr - DSi::NWRAM_C + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_C << 27);
|
return (ptr - GetNWRAM_C() + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_C << 27);
|
||||||
else
|
else
|
||||||
return memregion_Other << 27;
|
return memregion_Other << 27;
|
||||||
}
|
}
|
||||||
|
@ -1106,7 +1038,7 @@ u32 LocaliseAddress(int region, u32 num, u32 addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClassifyAddress9(u32 addr)
|
int ARMJIT_Memory::ClassifyAddress9(u32 addr) const noexcept
|
||||||
{
|
{
|
||||||
if (addr < NDS::ARM9->ITCMSize)
|
if (addr < NDS::ARM9->ITCMSize)
|
||||||
{
|
{
|
||||||
|
@ -1160,7 +1092,7 @@ int ClassifyAddress9(u32 addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClassifyAddress7(u32 addr)
|
int ARMJIT_Memory::ClassifyAddress7(u32 addr) const noexcept
|
||||||
{
|
{
|
||||||
if (NDS::ConsoleType == 1 && addr < 0x00010000 && !(DSi::SCFG_BIOS & (1<<9)))
|
if (NDS::ConsoleType == 1 && addr < 0x00010000 && !(DSi::SCFG_BIOS & (1<<9)))
|
||||||
{
|
{
|
||||||
|
@ -1295,7 +1227,7 @@ u32 NDSCartSlot_ReadROMData()
|
||||||
return NDS::NDSCartSlot->ReadROMData();
|
return NDS::NDSCartSlot->ReadROMData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
|
void* ARMJIT_Memory::GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) const noexcept
|
||||||
{
|
{
|
||||||
if (cpu->Num == 0)
|
if (cpu->Num == 0)
|
||||||
{
|
{
|
||||||
|
@ -1433,5 +1365,3 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,22 +20,57 @@
|
||||||
#define ARMJIT_MEMORY
|
#define ARMJIT_MEMORY
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "TinyVector.h"
|
||||||
|
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
|
#include "DSi.h"
|
||||||
|
|
||||||
namespace ARMJIT_Memory
|
#if defined(__SWITCH__)
|
||||||
|
#include <switch.h>
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JIT_ENABLED
|
||||||
|
#include <array>
|
||||||
|
#include "NDS.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
|
class Compiler;
|
||||||
|
class ARMJIT;
|
||||||
|
}
|
||||||
|
|
||||||
extern void* FastMem9Start;
|
constexpr u32 RoundUp(u32 size) noexcept
|
||||||
extern void* FastMem7Start;
|
|
||||||
|
|
||||||
void Init();
|
|
||||||
void DeInit();
|
|
||||||
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return (size + 0xFFFF) & ~0xFFFF;
|
||||||
|
#else
|
||||||
|
return size;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 MemBlockMainRAMOffset = 0;
|
||||||
|
const u32 MemBlockSWRAMOffset = RoundUp(NDS::MainRAMMaxSize);
|
||||||
|
const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(NDS::SharedWRAMSize);
|
||||||
|
const u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(NDS::ARM7WRAMSize);
|
||||||
|
const u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize);
|
||||||
|
const u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(DSi::NWRAMSize);
|
||||||
|
const u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(DSi::NWRAMSize);
|
||||||
|
const u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(DSi::NWRAMSize);
|
||||||
|
|
||||||
|
class ARMJIT_Memory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
memregion_Other = 0,
|
memregion_Other = 0,
|
||||||
memregion_ITCM,
|
memregion_ITCM,
|
||||||
memregion_DTCM,
|
memregion_DTCM,
|
||||||
|
@ -58,24 +93,136 @@ enum
|
||||||
memregion_NewSharedWRAM_C,
|
memregion_NewSharedWRAM_C,
|
||||||
|
|
||||||
memregions_Count
|
memregions_Count
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
|
public:
|
||||||
|
explicit ARMJIT_Memory(ARMJIT::ARMJIT& jit) noexcept;
|
||||||
|
~ARMJIT_Memory() noexcept;
|
||||||
|
ARMJIT_Memory(const ARMJIT_Memory&) = delete;
|
||||||
|
ARMJIT_Memory(ARMJIT_Memory&&) = delete;
|
||||||
|
ARMJIT_Memory& operator=(const ARMJIT_Memory&) = delete;
|
||||||
|
ARMJIT_Memory& operator=(ARMJIT_Memory&&) = delete;
|
||||||
|
void Reset() noexcept;
|
||||||
|
void RemapDTCM(u32 newBase, u32 newSize) noexcept;
|
||||||
|
void RemapSWRAM() noexcept;
|
||||||
|
void RemapNWRAM(int num) noexcept;
|
||||||
|
void SetCodeProtection(int region, u32 offset, bool protect) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetMainRAM() noexcept { return MemoryBase + MemBlockMainRAMOffset; }
|
||||||
|
[[nodiscard]] const u8* GetMainRAM() const noexcept { return MemoryBase + MemBlockMainRAMOffset; }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetSharedWRAM() noexcept { return MemoryBase + MemBlockSWRAMOffset; }
|
||||||
|
[[nodiscard]] const u8* GetSharedWRAM() const noexcept { return MemoryBase + MemBlockSWRAMOffset; }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetARM7WRAM() noexcept { return MemoryBase + MemBlockARM7WRAMOffset; }
|
||||||
|
[[nodiscard]] const u8* GetARM7WRAM() const noexcept { return MemoryBase + MemBlockARM7WRAMOffset; }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetARM9DTCM() noexcept { return MemoryBase + MemBlockDTCMOffset; }
|
||||||
|
[[nodiscard]] const u8* GetARM9DTCM() const noexcept { return MemoryBase + MemBlockDTCMOffset; }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetNWRAM_A() noexcept { return MemoryBase + MemBlockNWRAM_AOffset; }
|
||||||
|
[[nodiscard]] const u8* GetNWRAM_A() const noexcept { return MemoryBase + MemBlockNWRAM_AOffset; }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetNWRAM_B() noexcept { return MemoryBase + MemBlockNWRAM_BOffset; }
|
||||||
|
[[nodiscard]] const u8* GetNWRAM_B() const noexcept { return MemoryBase + MemBlockNWRAM_BOffset; }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetNWRAM_C() noexcept { return MemoryBase + MemBlockNWRAM_COffset; }
|
||||||
|
[[nodiscard]] const u8* GetNWRAM_C() const noexcept { return MemoryBase + MemBlockNWRAM_COffset; }
|
||||||
|
|
||||||
|
int ClassifyAddress9(u32 addr) const noexcept;
|
||||||
|
int ClassifyAddress7(u32 addr) const noexcept;
|
||||||
|
bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mirrorStart, u32& mirrorSize) const noexcept;
|
||||||
|
u32 LocaliseAddress(int region, u32 num, u32 addr) const noexcept;
|
||||||
|
bool IsFastmemCompatible(int region) const noexcept;
|
||||||
|
void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) const noexcept;
|
||||||
|
bool MapAtAddress(u32 addr) noexcept;
|
||||||
|
private:
|
||||||
|
friend class ARMJIT::Compiler;
|
||||||
|
struct Mapping
|
||||||
|
{
|
||||||
|
u32 Addr;
|
||||||
|
u32 Size, LocalOffset;
|
||||||
|
u32 Num;
|
||||||
|
|
||||||
|
void Unmap(int region, ARMJIT_Memory& memory) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FaultDescription
|
||||||
|
{
|
||||||
|
u32 EmulatedFaultAddr;
|
||||||
|
u8* FaultPC;
|
||||||
|
};
|
||||||
|
static bool FaultHandler(FaultDescription& faultDesc, ARMJIT::ARMJIT& jit);
|
||||||
|
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size) noexcept;
|
||||||
|
bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size) noexcept;
|
||||||
|
void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection) noexcept;
|
||||||
|
|
||||||
|
ARMJIT::ARMJIT& JIT;
|
||||||
|
void* FastMem9Start;
|
||||||
|
void* FastMem7Start;
|
||||||
|
u8* MemoryBase = nullptr;
|
||||||
|
#if defined(__SWITCH__)
|
||||||
|
VirtmemReservation* FastMem9Reservation, *FastMem7Reservation;
|
||||||
|
u8* MemoryBaseCodeMem;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo);
|
||||||
|
HANDLE MemoryFile = INVALID_HANDLE_VALUE;
|
||||||
|
LPVOID ExceptionHandlerHandle = nullptr;
|
||||||
|
#else
|
||||||
|
static void SigsegvHandler(int sig, siginfo_t* info, void* rawContext);
|
||||||
|
int MemoryFile = -1;
|
||||||
|
#endif
|
||||||
|
#ifdef ANDROID
|
||||||
|
Platform::DynamicLibrary* Libandroid = nullptr;
|
||||||
|
#endif
|
||||||
|
u8 MappingStatus9[1 << (32-12)] {};
|
||||||
|
u8 MappingStatus7[1 << (32-12)] {};
|
||||||
|
ARMJIT::TinyVector<Mapping> Mappings[memregions_Count] {};
|
||||||
|
#else
|
||||||
|
public:
|
||||||
|
explicit ARMJIT_Memory(ARMJIT::ARMJIT&) {};
|
||||||
|
~ARMJIT_Memory() = default;
|
||||||
|
ARMJIT_Memory(const ARMJIT_Memory&) = delete;
|
||||||
|
ARMJIT_Memory(ARMJIT_Memory&&) = delete;
|
||||||
|
ARMJIT_Memory& operator=(const ARMJIT_Memory&) = delete;
|
||||||
|
ARMJIT_Memory& operator=(ARMJIT_Memory&&) = delete;
|
||||||
|
|
||||||
|
void Reset() noexcept {}
|
||||||
|
void RemapDTCM(u32 newBase, u32 newSize) noexcept {}
|
||||||
|
void RemapSWRAM() noexcept {}
|
||||||
|
void RemapNWRAM(int num) noexcept {}
|
||||||
|
void SetCodeProtection(int region, u32 offset, bool protect) noexcept {}
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetMainRAM() noexcept { return MainRAM.data(); }
|
||||||
|
[[nodiscard]] const u8* GetMainRAM() const noexcept { return MainRAM.data(); }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetSharedWRAM() noexcept { return SharedWRAM.data(); }
|
||||||
|
[[nodiscard]] const u8* GetSharedWRAM() const noexcept { return SharedWRAM.data(); }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetARM7WRAM() noexcept { return ARM7WRAM.data(); }
|
||||||
|
[[nodiscard]] const u8* GetARM7WRAM() const noexcept { return ARM7WRAM.data(); }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetARM9DTCM() noexcept { return DTCM.data(); }
|
||||||
|
[[nodiscard]] const u8* GetARM9DTCM() const noexcept { return DTCM.data(); }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetNWRAM_A() noexcept { return NWRAM_A.data(); }
|
||||||
|
[[nodiscard]] const u8* GetNWRAM_A() const noexcept { return NWRAM_A.data(); }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetNWRAM_B() noexcept { return NWRAM_B.data(); }
|
||||||
|
[[nodiscard]] const u8* GetNWRAM_B() const noexcept { return NWRAM_B.data(); }
|
||||||
|
|
||||||
|
[[nodiscard]] u8* GetNWRAM_C() noexcept { return NWRAM_C.data(); }
|
||||||
|
[[nodiscard]] const u8* GetNWRAM_C() const noexcept { return NWRAM_C.data(); }
|
||||||
|
private:
|
||||||
|
std::array<u8, NDS::MainRAMMaxSize> MainRAM {};
|
||||||
|
std::array<u8, NDS::ARM7WRAMSize> ARM7WRAM {};
|
||||||
|
std::array<u8, NDS::SharedWRAMSize> SharedWRAM {};
|
||||||
|
std::array<u8, DTCMPhysicalSize> DTCM {};
|
||||||
|
std::array<u8, DSi::NWRAMSize> NWRAM_A {};
|
||||||
|
std::array<u8, DSi::NWRAMSize> NWRAM_B {};
|
||||||
|
std::array<u8, DSi::NWRAMSize> NWRAM_C {};
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int ClassifyAddress9(u32 addr);
|
|
||||||
int ClassifyAddress7(u32 addr);
|
|
||||||
|
|
||||||
bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mirrorStart, u32& mirrorSize);
|
|
||||||
u32 LocaliseAddress(int region, u32 num, u32 addr);
|
|
||||||
|
|
||||||
bool IsFastmemCompatible(int region);
|
|
||||||
|
|
||||||
void RemapDTCM(u32 newBase, u32 newSize);
|
|
||||||
void RemapSWRAM();
|
|
||||||
void RemapNWRAM(int num);
|
|
||||||
|
|
||||||
void SetCodeProtection(int region, u32 offset, bool protect);
|
|
||||||
|
|
||||||
void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#ifndef ARMJIT_REGCACHE_H
|
#ifndef ARMJIT_REGCACHE_H
|
||||||
#define ARMJIT_REGCACHE_H
|
#define ARMJIT_REGCACHE_H
|
||||||
|
|
||||||
#include "ARMJIT.h"
|
|
||||||
#include "ARMJIT_Internal.h"
|
#include "ARMJIT_Internal.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ARMJIT_Compiler.h"
|
#include "ARMJIT_Compiler.h"
|
||||||
|
#include "../ARM.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ARMJIT_Compiler.h"
|
#include "ARMJIT_Compiler.h"
|
||||||
|
#include "../ARM.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "ARMJIT_Compiler.h"
|
#include "ARMJIT_Compiler.h"
|
||||||
|
|
||||||
|
#include "../ARMJIT.h"
|
||||||
#include "../ARMInterpreter.h"
|
#include "../ARMInterpreter.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -232,7 +233,7 @@ void Compiler::A_Comp_MSR()
|
||||||
*/
|
*/
|
||||||
u8 CodeMemory[1024 * 1024 * 32];
|
u8 CodeMemory[1024 * 1024 * 32];
|
||||||
|
|
||||||
Compiler::Compiler()
|
Compiler::Compiler(ARMJIT& jit) : XEmitter(), JIT(jit)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -712,12 +713,12 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
|
||||||
if (NearSize - (GetCodePtr() - NearStart) < 1024 * 32) // guess...
|
if (NearSize - (GetCodePtr() - NearStart) < 1024 * 32) // guess...
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "near reset\n");
|
Log(LogLevel::Debug, "near reset\n");
|
||||||
ResetBlockCache();
|
JIT.ResetBlockCache();
|
||||||
}
|
}
|
||||||
if (FarSize - (FarCode - FarStart) < 1024 * 32) // guess...
|
if (FarSize - (FarCode - FarStart) < 1024 * 32) // guess...
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug, "far reset\n");
|
Log(LogLevel::Debug, "far reset\n");
|
||||||
ResetBlockCache();
|
JIT.ResetBlockCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstantCycles = 0;
|
ConstantCycles = 0;
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#include "../dolphin/x64Emitter.h"
|
#include "../dolphin/x64Emitter.h"
|
||||||
|
|
||||||
#include "../ARMJIT.h"
|
|
||||||
#include "../ARMJIT_Internal.h"
|
#include "../ARMJIT_Internal.h"
|
||||||
#include "../ARMJIT_RegisterCache.h"
|
#include "../ARMJIT_RegisterCache.h"
|
||||||
|
|
||||||
|
@ -31,9 +30,11 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class ARMJIT_Memory;
|
||||||
|
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
|
class ARMJIT;
|
||||||
const Gen::X64Reg RCPU = Gen::RBP;
|
const Gen::X64Reg RCPU = Gen::RBP;
|
||||||
const Gen::X64Reg RCPSR = Gen::R15;
|
const Gen::X64Reg RCPSR = Gen::R15;
|
||||||
|
|
||||||
|
@ -79,7 +80,11 @@ struct Op2
|
||||||
class Compiler : public Gen::XEmitter
|
class Compiler : public Gen::XEmitter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Compiler();
|
#ifdef JIT_ENABLED
|
||||||
|
explicit Compiler(ARMJIT& jit);
|
||||||
|
#else
|
||||||
|
explicit Compiler(ARMJIT& jit) : XEmitter(), JIT(jit) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
@ -238,42 +243,43 @@ public:
|
||||||
void CreateMethod(const char* namefmt, void* start, ...);
|
void CreateMethod(const char* namefmt, void* start, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
u8* FarCode;
|
ARMJIT& JIT;
|
||||||
u8* NearCode;
|
u8* FarCode {};
|
||||||
u32 FarSize;
|
u8* NearCode {};
|
||||||
u32 NearSize;
|
u32 FarSize {};
|
||||||
|
u32 NearSize {};
|
||||||
|
|
||||||
u8* NearStart;
|
u8* NearStart {};
|
||||||
u8* FarStart;
|
u8* FarStart {};
|
||||||
|
|
||||||
void* PatchedStoreFuncs[2][2][3][16];
|
void* PatchedStoreFuncs[2][2][3][16] {};
|
||||||
void* PatchedLoadFuncs[2][2][3][2][16];
|
void* PatchedLoadFuncs[2][2][3][2][16] {};
|
||||||
|
|
||||||
std::unordered_map<u8*, LoadStorePatch> LoadStorePatches;
|
std::unordered_map<u8*, LoadStorePatch> LoadStorePatches {};
|
||||||
|
|
||||||
u8* ResetStart;
|
u8* ResetStart {};
|
||||||
u32 CodeMemSize;
|
u32 CodeMemSize {};
|
||||||
|
|
||||||
bool Exit;
|
bool Exit {};
|
||||||
bool IrregularCycles;
|
bool IrregularCycles {};
|
||||||
|
|
||||||
void* ReadBanked;
|
void* ReadBanked {};
|
||||||
void* WriteBanked;
|
void* WriteBanked {};
|
||||||
|
|
||||||
bool CPSRDirty = false;
|
bool CPSRDirty = false;
|
||||||
|
|
||||||
FetchedInstr CurInstr;
|
FetchedInstr CurInstr {};
|
||||||
|
|
||||||
RegisterCache<Compiler, Gen::X64Reg> RegCache;
|
RegisterCache<Compiler, Gen::X64Reg> RegCache {};
|
||||||
|
|
||||||
bool Thumb;
|
bool Thumb {};
|
||||||
u32 Num;
|
u32 Num {};
|
||||||
u32 R15;
|
u32 R15 {};
|
||||||
u32 CodeRegion;
|
u32 CodeRegion {};
|
||||||
|
|
||||||
u32 ConstantCycles;
|
u32 ConstantCycles {};
|
||||||
|
|
||||||
ARM* CurCPU;
|
ARM* CurCPU {};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ARMJIT_Compiler.h"
|
#include "ARMJIT_Compiler.h"
|
||||||
|
#include "../ARMJIT.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
|
@ -67,9 +68,9 @@ u8* Compiler::RewriteMemAccess(u8* pc)
|
||||||
|
|
||||||
bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
|
bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
|
||||||
{
|
{
|
||||||
u32 localAddr = LocaliseCodeAddress(Num, addr);
|
u32 localAddr = JIT.LocaliseCodeAddress(Num, addr);
|
||||||
|
|
||||||
int invalidLiteralIdx = InvalidLiterals.Find(localAddr);
|
int invalidLiteralIdx = JIT.InvalidLiterals.Find(localAddr);
|
||||||
if (invalidLiteralIdx != -1)
|
if (invalidLiteralIdx != -1)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -117,7 +118,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
||||||
if (size == 16)
|
if (size == 16)
|
||||||
addressMask = ~1;
|
addressMask = ~1;
|
||||||
|
|
||||||
if (LiteralOptimizations && rn == 15 && rd != 15 && op2.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
if (JIT.LiteralOptimizations && rn == 15 && rd != 15 && op2.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
||||||
{
|
{
|
||||||
u32 addr = R15 + op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
|
u32 addr = R15 + op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
||||||
Comp_AddCycles_CDI();
|
Comp_AddCycles_CDI();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addrIsStatic = LiteralOptimizations
|
bool addrIsStatic = JIT.LiteralOptimizations
|
||||||
&& RegCache.IsLiteral(rn) && op2.IsImm && !(flags & (memop_Writeback|memop_Post));
|
&& RegCache.IsLiteral(rn) && op2.IsImm && !(flags & (memop_Writeback|memop_Post));
|
||||||
u32 staticAddress;
|
u32 staticAddress;
|
||||||
if (addrIsStatic)
|
if (addrIsStatic)
|
||||||
|
@ -195,10 +196,10 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
||||||
MOV(32, rnMapped, R(finalAddr));
|
MOV(32, rnMapped, R(finalAddr));
|
||||||
|
|
||||||
u32 expectedTarget = Num == 0
|
u32 expectedTarget = Num == 0
|
||||||
? ARMJIT_Memory::ClassifyAddress9(CurInstr.DataRegion)
|
? JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
|
: JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||||
|
|
||||||
if (ARMJIT::FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || ARMJIT_Memory::IsFastmemCompatible(expectedTarget)))
|
if (JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || JIT.Memory.IsFastmemCompatible(expectedTarget)))
|
||||||
{
|
{
|
||||||
if (rdMapped.IsImm())
|
if (rdMapped.IsImm())
|
||||||
{
|
{
|
||||||
|
@ -216,7 +217,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
||||||
|
|
||||||
assert(patch.PatchFunc != NULL);
|
assert(patch.PatchFunc != NULL);
|
||||||
|
|
||||||
MOV(64, R(RSCRATCH), ImmPtr(Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start));
|
MOV(64, R(RSCRATCH), ImmPtr(Num == 0 ? JIT.Memory.FastMem9Start : JIT.Memory.FastMem7Start));
|
||||||
|
|
||||||
X64Reg maskedAddr = RSCRATCH3;
|
X64Reg maskedAddr = RSCRATCH3;
|
||||||
if (size > 8)
|
if (size > 8)
|
||||||
|
@ -267,7 +268,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
||||||
|
|
||||||
void* func = NULL;
|
void* func = NULL;
|
||||||
if (addrIsStatic)
|
if (addrIsStatic)
|
||||||
func = ARMJIT_Memory::GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
func = JIT.Memory.GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
||||||
|
|
||||||
if (func)
|
if (func)
|
||||||
{
|
{
|
||||||
|
@ -421,16 +422,16 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
s32 offset = (regsCount * 4) * (decrement ? -1 : 1);
|
s32 offset = (regsCount * 4) * (decrement ? -1 : 1);
|
||||||
|
|
||||||
int expectedTarget = Num == 0
|
int expectedTarget = Num == 0
|
||||||
? ARMJIT_Memory::ClassifyAddress9(CurInstr.DataRegion)
|
? JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
|
: JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||||
|
|
||||||
if (!store)
|
if (!store)
|
||||||
Comp_AddCycles_CDI();
|
Comp_AddCycles_CDI();
|
||||||
else
|
else
|
||||||
Comp_AddCycles_CD();
|
Comp_AddCycles_CD();
|
||||||
|
|
||||||
bool compileFastPath = FastMemory
|
bool compileFastPath = JIT.FastMemory
|
||||||
&& !usermode && (CurInstr.Cond() < 0xE || ARMJIT_Memory::IsFastmemCompatible(expectedTarget));
|
&& !usermode && (CurInstr.Cond() < 0xE || JIT.Memory.IsFastmemCompatible(expectedTarget));
|
||||||
|
|
||||||
// we need to make sure that the stack stays aligned to 16 bytes
|
// we need to make sure that the stack stays aligned to 16 bytes
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -453,7 +454,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
u8* fastPathStart = GetWritableCodePtr();
|
u8* fastPathStart = GetWritableCodePtr();
|
||||||
u8* loadStoreAddr[16];
|
u8* loadStoreAddr[16];
|
||||||
|
|
||||||
MOV(64, R(RSCRATCH2), ImmPtr(Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start));
|
MOV(64, R(RSCRATCH2), ImmPtr(Num == 0 ? JIT.Memory.FastMem9Start : JIT.Memory.FastMem7Start));
|
||||||
ADD(64, R(RSCRATCH2), R(RSCRATCH4));
|
ADD(64, R(RSCRATCH2), R(RSCRATCH4));
|
||||||
|
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
@ -807,7 +808,7 @@ void Compiler::T_Comp_LoadPCRel()
|
||||||
{
|
{
|
||||||
u32 offset = (CurInstr.Instr & 0xFF) << 2;
|
u32 offset = (CurInstr.Instr & 0xFF) << 2;
|
||||||
u32 addr = (R15 & ~0x2) + offset;
|
u32 addr = (R15 & ~0x2) + offset;
|
||||||
if (!LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
if (!JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
||||||
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
|
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ const u32 T_SVC = T_BranchAlways | T_WriteR14 | tk(tk_SVC);
|
||||||
#include "ARM_InstrTable.h"
|
#include "ARM_InstrTable.h"
|
||||||
#undef INSTRFUNC_PROTO
|
#undef INSTRFUNC_PROTO
|
||||||
|
|
||||||
Info Decode(bool thumb, u32 num, u32 instr)
|
Info Decode(bool thumb, u32 num, u32 instr, bool literaloptimizations)
|
||||||
{
|
{
|
||||||
const u8 FlagsReadPerCond[7] = {
|
const u8 FlagsReadPerCond[7] = {
|
||||||
flag_Z,
|
flag_Z,
|
||||||
|
@ -386,7 +386,7 @@ Info Decode(bool thumb, u32 num, u32 instr)
|
||||||
{
|
{
|
||||||
if (res.Kind == tk_LDR_PCREL)
|
if (res.Kind == tk_LDR_PCREL)
|
||||||
{
|
{
|
||||||
if (!ARMJIT::LiteralOptimizations)
|
if (!literaloptimizations)
|
||||||
res.SrcRegs |= 1 << 15;
|
res.SrcRegs |= 1 << 15;
|
||||||
res.SpecialKind = special_LoadLiteral;
|
res.SpecialKind = special_LoadLiteral;
|
||||||
}
|
}
|
||||||
|
|
|
@ -274,7 +274,7 @@ struct Info
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Info Decode(bool thumb, u32 num, u32 instr);
|
Info Decode(bool thumb, u32 num, u32 instr, bool literaloptimizations);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
src/CP15.cpp
23
src/CP15.cpp
|
@ -22,11 +22,8 @@
|
||||||
#include "DSi.h"
|
#include "DSi.h"
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
#include "ARMJIT.h"
|
|
||||||
#include "ARMJIT_Memory.h"
|
#include "ARMJIT_Memory.h"
|
||||||
#endif
|
#include "ARMJIT.h"
|
||||||
|
|
||||||
using Platform::Log;
|
using Platform::Log;
|
||||||
using Platform::LogLevel;
|
using Platform::LogLevel;
|
||||||
|
@ -125,9 +122,7 @@ void ARMv5::UpdateDTCMSetting()
|
||||||
|
|
||||||
if (newDTCMBase != DTCMBase || newDTCMMask != DTCMMask)
|
if (newDTCMBase != DTCMBase || newDTCMMask != DTCMMask)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
JIT.Memory.RemapDTCM(newDTCMBase, newDTCMSize);
|
||||||
ARMJIT_Memory::RemapDTCM(newDTCMBase, newDTCMSize);
|
|
||||||
#endif
|
|
||||||
DTCMBase = newDTCMBase;
|
DTCMBase = newDTCMBase;
|
||||||
DTCMMask = newDTCMMask;
|
DTCMMask = newDTCMMask;
|
||||||
}
|
}
|
||||||
|
@ -926,9 +921,7 @@ void ARMv5::DataWrite8(u32 addr, u8 val)
|
||||||
{
|
{
|
||||||
DataCycles = 1;
|
DataCycles = 1;
|
||||||
*(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
*(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||||
#ifdef JIT_ENABLED
|
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((addr & DTCMMask) == DTCMBase)
|
if ((addr & DTCMMask) == DTCMBase)
|
||||||
|
@ -958,9 +951,7 @@ void ARMv5::DataWrite16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
DataCycles = 1;
|
DataCycles = 1;
|
||||||
*(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
*(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||||
#ifdef JIT_ENABLED
|
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((addr & DTCMMask) == DTCMBase)
|
if ((addr & DTCMMask) == DTCMBase)
|
||||||
|
@ -990,9 +981,7 @@ void ARMv5::DataWrite32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
DataCycles = 1;
|
DataCycles = 1;
|
||||||
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||||
#ifdef JIT_ENABLED
|
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((addr & DTCMMask) == DTCMBase)
|
if ((addr & DTCMMask) == DTCMBase)
|
||||||
|
@ -1015,7 +1004,7 @@ void ARMv5::DataWrite32S(u32 addr, u32 val)
|
||||||
DataCycles += 1;
|
DataCycles += 1;
|
||||||
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
140
src/DSi.cpp
140
src/DSi.cpp
|
@ -28,10 +28,8 @@
|
||||||
#include "DSi_SPI_TSC.h"
|
#include "DSi_SPI_TSC.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
#include "ARMJIT.h"
|
#include "ARMJIT.h"
|
||||||
#include "ARMJIT_Memory.h"
|
#include "ARMJIT_Memory.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "DSi_NDMA.h"
|
#include "DSi_NDMA.h"
|
||||||
#include "DSi_I2C.h"
|
#include "DSi_I2C.h"
|
||||||
|
@ -99,11 +97,10 @@ void Set_SCFG_MC(u32 val);
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
#ifndef JIT_ENABLED
|
// Memory is owned by ARMJIT_Memory, don't free it
|
||||||
NWRAM_A = new u8[NWRAMSize];
|
NWRAM_A = NDS::JIT->Memory.GetNWRAM_A();
|
||||||
NWRAM_B = new u8[NWRAMSize];
|
NWRAM_B = NDS::JIT->Memory.GetNWRAM_B();
|
||||||
NWRAM_C = new u8[NWRAMSize];
|
NWRAM_C = NDS::JIT->Memory.GetNWRAM_C();
|
||||||
#endif
|
|
||||||
|
|
||||||
NDMAs[0] = new DSi_NDMA(0, 0, *NDS::GPU);
|
NDMAs[0] = new DSi_NDMA(0, 0, *NDS::GPU);
|
||||||
NDMAs[1] = new DSi_NDMA(0, 1, *NDS::GPU);
|
NDMAs[1] = new DSi_NDMA(0, 1, *NDS::GPU);
|
||||||
|
@ -127,15 +124,10 @@ bool Init()
|
||||||
|
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
#ifndef JIT_ENABLED
|
// Memory is owned externally
|
||||||
delete[] NWRAM_A;
|
|
||||||
delete[] NWRAM_B;
|
|
||||||
delete[] NWRAM_C;
|
|
||||||
|
|
||||||
NWRAM_A = nullptr;
|
NWRAM_A = nullptr;
|
||||||
NWRAM_B = nullptr;
|
NWRAM_B = nullptr;
|
||||||
NWRAM_C = nullptr;
|
NWRAM_C = nullptr;
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
@ -684,10 +676,8 @@ void SoftReset()
|
||||||
|
|
||||||
// also, BPTWL[0x70] could be abused to quickly boot specific titles
|
// also, BPTWL[0x70] could be abused to quickly boot specific titles
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->Reset();
|
||||||
ARMJIT_Memory::Reset();
|
NDS::JIT->CheckAndInvalidateITCM();
|
||||||
ARMJIT::CheckAndInvalidateITCM();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NDS::ARM9->Reset();
|
NDS::ARM9->Reset();
|
||||||
NDS::ARM7->Reset();
|
NDS::ARM7->Reset();
|
||||||
|
@ -1043,9 +1033,7 @@ void MapNWRAM_A(u32 num, u8 val)
|
||||||
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
||||||
if (oldval == val) return;
|
if (oldval == val) return;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->Memory.RemapNWRAM(0);
|
||||||
ARMJIT_Memory::RemapNWRAM(0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MBK[0][mbkn] &= ~(0xFF << mbks);
|
MBK[0][mbkn] &= ~(0xFF << mbks);
|
||||||
MBK[0][mbkn] |= (val << mbks);
|
MBK[0][mbkn] |= (val << mbks);
|
||||||
|
@ -1090,9 +1078,7 @@ void MapNWRAM_B(u32 num, u8 val)
|
||||||
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
||||||
if (oldval == val) return;
|
if (oldval == val) return;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->Memory.RemapNWRAM(1);
|
||||||
ARMJIT_Memory::RemapNWRAM(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MBK[0][mbkn] &= ~(0xFF << mbks);
|
MBK[0][mbkn] &= ~(0xFF << mbks);
|
||||||
MBK[0][mbkn] |= (val << mbks);
|
MBK[0][mbkn] |= (val << mbks);
|
||||||
|
@ -1139,9 +1125,7 @@ void MapNWRAM_C(u32 num, u8 val)
|
||||||
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
||||||
if (oldval == val) return;
|
if (oldval == val) return;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->Memory.RemapNWRAM(2);
|
||||||
ARMJIT_Memory::RemapNWRAM(2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MBK[0][mbkn] &= ~(0xFF << mbks);
|
MBK[0][mbkn] &= ~(0xFF << mbks);
|
||||||
MBK[0][mbkn] |= (val << mbks);
|
MBK[0][mbkn] |= (val << mbks);
|
||||||
|
@ -1190,9 +1174,7 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val)
|
||||||
u32 oldval = MBK[cpu][5+num];
|
u32 oldval = MBK[cpu][5+num];
|
||||||
if (oldval == val) return;
|
if (oldval == val) return;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->Memory.RemapNWRAM(num);
|
||||||
ARMJIT_Memory::RemapNWRAM(num);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MBK[cpu][5+num] = val;
|
MBK[cpu][5+num] = val;
|
||||||
|
|
||||||
|
@ -1468,9 +1450,7 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_A[page * 0x10000];
|
u8* ptr = &NWRAM_A[page * 0x10000];
|
||||||
*(u8*)&ptr[addr & 0xFFFF] = val;
|
*(u8*)&ptr[addr & 0xFFFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1488,9 +1468,7 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_B[page * 0x8000];
|
u8* ptr = &NWRAM_B[page * 0x8000];
|
||||||
*(u8*)&ptr[addr & 0x7FFF] = val;
|
*(u8*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1508,9 +1486,7 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_C[page * 0x8000];
|
u8* ptr = &NWRAM_C[page * 0x8000];
|
||||||
*(u8*)&ptr[addr & 0x7FFF] = val;
|
*(u8*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1523,9 +1499,7 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
if (!(SCFG_EXT[0] & (1<<13))) return;
|
if (!(SCFG_EXT[0] & (1<<13))) return;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(addr);
|
|
||||||
#endif
|
|
||||||
switch (addr & 0x00E00000)
|
switch (addr & 0x00E00000)
|
||||||
{
|
{
|
||||||
case 0x00000000: NDS::GPU->WriteVRAM_ABG<u8>(addr, val); return;
|
case 0x00000000: NDS::GPU->WriteVRAM_ABG<u8>(addr, val); return;
|
||||||
|
@ -1541,9 +1515,7 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x0C000000:
|
case 0x0C000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
*(u8*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1574,9 +1546,7 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_A[page * 0x10000];
|
u8* ptr = &NWRAM_A[page * 0x10000];
|
||||||
*(u16*)&ptr[addr & 0xFFFF] = val;
|
*(u16*)&ptr[addr & 0xFFFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1594,9 +1564,7 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_B[page * 0x8000];
|
u8* ptr = &NWRAM_B[page * 0x8000];
|
||||||
*(u16*)&ptr[addr & 0x7FFF] = val;
|
*(u16*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1614,9 +1582,7 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_C[page * 0x8000];
|
u8* ptr = &NWRAM_C[page * 0x8000];
|
||||||
*(u16*)&ptr[addr & 0x7FFF] = val;
|
*(u16*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1633,9 +1599,7 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x0C000000:
|
case 0x0C000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
*(u16*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1666,9 +1630,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_A[page * 0x10000];
|
u8* ptr = &NWRAM_A[page * 0x10000];
|
||||||
*(u32*)&ptr[addr & 0xFFFF] = val;
|
*(u32*)&ptr[addr & 0xFFFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1686,9 +1648,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_B[page * 0x8000];
|
u8* ptr = &NWRAM_B[page * 0x8000];
|
||||||
*(u32*)&ptr[addr & 0x7FFF] = val;
|
*(u32*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1706,9 +1666,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_C[page * 0x8000];
|
u8* ptr = &NWRAM_C[page * 0x8000];
|
||||||
*(u32*)&ptr[addr & 0x7FFF] = val;
|
*(u32*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1725,9 +1683,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x0C000000:
|
case 0x0C000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
*(u32*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1970,9 +1926,7 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_A[page * 0x10000];
|
u8* ptr = &NWRAM_A[page * 0x10000];
|
||||||
*(u8*)&ptr[addr & 0xFFFF] = val;
|
*(u8*)&ptr[addr & 0xFFFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1990,9 +1944,7 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_B[page * 0x8000];
|
u8* ptr = &NWRAM_B[page * 0x8000];
|
||||||
*(u8*)&ptr[addr & 0x7FFF] = val;
|
*(u8*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2010,9 +1962,7 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_C[page * 0x8000];
|
u8* ptr = &NWRAM_C[page * 0x8000];
|
||||||
*(u8*)&ptr[addr & 0x7FFF] = val;
|
*(u8*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2033,9 +1983,7 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
|
|
||||||
case 0x0C000000:
|
case 0x0C000000:
|
||||||
case 0x0C800000:
|
case 0x0C800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
*(u8*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2067,9 +2015,7 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_A[page * 0x10000];
|
u8* ptr = &NWRAM_A[page * 0x10000];
|
||||||
*(u16*)&ptr[addr & 0xFFFF] = val;
|
*(u16*)&ptr[addr & 0xFFFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2087,9 +2033,7 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_B[page * 0x8000];
|
u8* ptr = &NWRAM_B[page * 0x8000];
|
||||||
*(u16*)&ptr[addr & 0x7FFF] = val;
|
*(u16*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2107,9 +2051,7 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_C[page * 0x8000];
|
u8* ptr = &NWRAM_C[page * 0x8000];
|
||||||
*(u16*)&ptr[addr & 0x7FFF] = val;
|
*(u16*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2130,9 +2072,7 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
|
|
||||||
case 0x0C000000:
|
case 0x0C000000:
|
||||||
case 0x0C800000:
|
case 0x0C800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
*(u16*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2164,9 +2104,7 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_A[page * 0x10000];
|
u8* ptr = &NWRAM_A[page * 0x10000];
|
||||||
*(u32*)&ptr[addr & 0xFFFF] = val;
|
*(u32*)&ptr[addr & 0xFFFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2184,9 +2122,7 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_B[page * 0x8000];
|
u8* ptr = &NWRAM_B[page * 0x8000];
|
||||||
*(u32*)&ptr[addr & 0x7FFF] = val;
|
*(u32*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2204,9 +2140,7 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
continue;
|
continue;
|
||||||
u8* ptr = &NWRAM_C[page * 0x8000];
|
u8* ptr = &NWRAM_C[page * 0x8000];
|
||||||
*(u32*)&ptr[addr & 0x7FFF] = val;
|
*(u32*)&ptr[addr & 0x7FFF] = val;
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2227,9 +2161,7 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
|
|
||||||
case 0x0C000000:
|
case 0x0C000000:
|
||||||
case 0x0C800000:
|
case 0x0C800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
*(u32*)&NDS::MainRAM[addr & NDS::MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,7 @@
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
#include "GPU.h"
|
#include "GPU.h"
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
#include "ARMJIT.h"
|
#include "ARMJIT.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "GPU2D_Soft.h"
|
#include "GPU2D_Soft.h"
|
||||||
#include "GPU3D_Soft.h"
|
#include "GPU3D_Soft.h"
|
||||||
|
@ -66,7 +64,7 @@ enum
|
||||||
VRAMDirty need to be reset for the respective VRAM bank.
|
VRAMDirty need to be reset for the respective VRAM bank.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
GPU::GPU() noexcept : GPU2D_A(0, *this), GPU2D_B(1, *this)
|
GPU::GPU(ARMJIT::ARMJIT& jit) noexcept : GPU2D_A(0, *this), GPU2D_B(1, *this), JIT(jit)
|
||||||
{
|
{
|
||||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartHBlank, MemberEventFunc(GPU, StartHBlank));
|
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartHBlank, MemberEventFunc(GPU, StartHBlank));
|
||||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartScanline, MemberEventFunc(GPU, StartScanline));
|
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartScanline, MemberEventFunc(GPU, StartScanline));
|
||||||
|
@ -590,9 +588,7 @@ void GPU::MapVRAM_CD(u32 bank, u8 cnt) noexcept
|
||||||
VRAMMap_ARM7[ofs] |= bankmask;
|
VRAMMap_ARM7[ofs] |= bankmask;
|
||||||
memset(VRAMDirty[bank].Data, 0xFF, sizeof(VRAMDirty[bank].Data));
|
memset(VRAMDirty[bank].Data, 0xFF, sizeof(VRAMDirty[bank].Data));
|
||||||
VRAMSTAT |= (1 << (bank-2));
|
VRAMSTAT |= (1 << (bank-2));
|
||||||
#ifdef JIT_ENABLED
|
JIT.CheckAndInvalidateWVRAM(ofs);
|
||||||
ARMJIT::CheckAndInvalidateWVRAM(ofs);
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // texture
|
case 3: // texture
|
||||||
|
|
|
@ -35,6 +35,11 @@ namespace GPU3D
|
||||||
class GPU3D;
|
class GPU3D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
|
{
|
||||||
|
class ARMJIT;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Melon
|
namespace Melon
|
||||||
{
|
{
|
||||||
static constexpr u32 VRAMDirtyGranularity = 512;
|
static constexpr u32 VRAMDirtyGranularity = 512;
|
||||||
|
@ -70,7 +75,7 @@ struct RenderSettings
|
||||||
class GPU
|
class GPU
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GPU() noexcept;
|
GPU(ARMJIT::ARMJIT& jit) noexcept;
|
||||||
~GPU() noexcept;
|
~GPU() noexcept;
|
||||||
void Reset() noexcept;
|
void Reset() noexcept;
|
||||||
void Stop() noexcept;
|
void Stop() noexcept;
|
||||||
|
@ -539,6 +544,7 @@ public:
|
||||||
|
|
||||||
void SyncDirtyFlags() noexcept;
|
void SyncDirtyFlags() noexcept;
|
||||||
|
|
||||||
|
ARMJIT::ARMJIT& JIT;
|
||||||
u16 VCount = 0;
|
u16 VCount = 0;
|
||||||
u16 TotalScanlines = 0;
|
u16 TotalScanlines = 0;
|
||||||
u16 DispStat[2] {};
|
u16 DispStat[2] {};
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016-2023 melonDS team
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS 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, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS 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 for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MELONDS_JITBLOCK_H
|
||||||
|
#define MELONDS_JITBLOCK_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "TinyVector.h"
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
|
{
|
||||||
|
typedef void (*JitBlockEntry)();
|
||||||
|
|
||||||
|
class JitBlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
JitBlock(u32 num, u32 literalHash, u32 numAddresses, u32 numLiterals)
|
||||||
|
{
|
||||||
|
Num = num;
|
||||||
|
NumAddresses = numAddresses;
|
||||||
|
NumLiterals = numLiterals;
|
||||||
|
Data.SetLength(numAddresses * 2 + numLiterals);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 StartAddr;
|
||||||
|
u32 StartAddrLocal;
|
||||||
|
u32 InstrHash, LiteralHash;
|
||||||
|
u8 Num;
|
||||||
|
u16 NumAddresses;
|
||||||
|
u16 NumLiterals;
|
||||||
|
|
||||||
|
JitBlockEntry EntryPoint;
|
||||||
|
|
||||||
|
u32* AddressRanges()
|
||||||
|
{ return &Data[0]; }
|
||||||
|
u32* AddressMasks()
|
||||||
|
{ return &Data[NumAddresses]; }
|
||||||
|
u32* Literals()
|
||||||
|
{ return &Data[NumAddresses * 2]; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TinyVector<u32> Data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MELONDS_JITBLOCK_H
|
136
src/NDS.cpp
136
src/NDS.cpp
|
@ -35,16 +35,13 @@
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
#include "FreeBIOS.h"
|
#include "FreeBIOS.h"
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
#include "ARMJIT.h"
|
|
||||||
#include "ARMJIT_Memory.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "DSi.h"
|
#include "DSi.h"
|
||||||
#include "DSi_SPI_TSC.h"
|
#include "DSi_SPI_TSC.h"
|
||||||
#include "DSi_NWifi.h"
|
#include "DSi_NWifi.h"
|
||||||
#include "DSi_Camera.h"
|
#include "DSi_Camera.h"
|
||||||
#include "DSi_DSP.h"
|
#include "DSi_DSP.h"
|
||||||
|
#include "ARMJIT.h"
|
||||||
|
#include "ARMJIT_Memory.h"
|
||||||
|
|
||||||
using namespace Platform;
|
using namespace Platform;
|
||||||
|
|
||||||
|
@ -186,6 +183,7 @@ class Wifi* Wifi;
|
||||||
std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot;
|
std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot;
|
||||||
std::unique_ptr<GBACart::GBACartSlot> GBACartSlot;
|
std::unique_ptr<GBACart::GBACartSlot> GBACartSlot;
|
||||||
std::unique_ptr<Melon::GPU> GPU;
|
std::unique_ptr<Melon::GPU> GPU;
|
||||||
|
std::unique_ptr<ARMJIT::ARMJIT> JIT;
|
||||||
class AREngine* AREngine;
|
class AREngine* AREngine;
|
||||||
|
|
||||||
bool Running;
|
bool Running;
|
||||||
|
@ -205,17 +203,15 @@ bool Init()
|
||||||
RegisterEventFunc(Event_Div, 0, DivDone);
|
RegisterEventFunc(Event_Div, 0, DivDone);
|
||||||
RegisterEventFunc(Event_Sqrt, 0, SqrtDone);
|
RegisterEventFunc(Event_Sqrt, 0, SqrtDone);
|
||||||
|
|
||||||
GPU = std::make_unique<Melon::GPU>();
|
JIT = std::make_unique<ARMJIT::ARMJIT>();
|
||||||
ARM9 = new ARMv5(*GPU);
|
GPU = std::make_unique<Melon::GPU>(*JIT);
|
||||||
ARM7 = new ARMv4(*GPU);
|
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
MainRAM = JIT->Memory.GetMainRAM();
|
||||||
ARMJIT::Init();
|
SharedWRAM = JIT->Memory.GetSharedWRAM();
|
||||||
#else
|
ARM7WRAM = JIT->Memory.GetARM7WRAM();
|
||||||
MainRAM = new u8[0x1000000];
|
|
||||||
ARM7WRAM = new u8[ARM7WRAMSize];
|
ARM9 = new ARMv5(*JIT, *GPU);
|
||||||
SharedWRAM = new u8[SharedWRAMSize];
|
ARM7 = new ARMv4(*JIT, *GPU);
|
||||||
#endif
|
|
||||||
|
|
||||||
DMAs[0] = new DMA(0, 0, *GPU);
|
DMAs[0] = new DMA(0, 0, *GPU);
|
||||||
DMAs[1] = new DMA(0, 1, *GPU);
|
DMAs[1] = new DMA(0, 1, *GPU);
|
||||||
|
@ -242,10 +238,6 @@ bool Init()
|
||||||
|
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
ARMJIT::DeInit();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
delete ARM9; ARM9 = nullptr;
|
delete ARM9; ARM9 = nullptr;
|
||||||
delete ARM7; ARM7 = nullptr;
|
delete ARM7; ARM7 = nullptr;
|
||||||
|
|
||||||
|
@ -270,6 +262,8 @@ void DeInit()
|
||||||
|
|
||||||
UnregisterEventFunc(Event_Div, 0);
|
UnregisterEventFunc(Event_Div, 0);
|
||||||
UnregisterEventFunc(Event_Sqrt, 0);
|
UnregisterEventFunc(Event_Sqrt, 0);
|
||||||
|
|
||||||
|
JIT = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -548,9 +542,7 @@ void Reset()
|
||||||
|
|
||||||
// BIOS files are now loaded by the frontend
|
// BIOS files are now loaded by the frontend
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
JIT->Reset();
|
||||||
ARMJIT::Reset();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ConsoleType == 1)
|
if (ConsoleType == 1)
|
||||||
{
|
{
|
||||||
|
@ -869,8 +861,8 @@ bool DoSavestate(Savestate* file)
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
if (!file->Saving)
|
if (!file->Saving)
|
||||||
{
|
{
|
||||||
ARMJIT::ResetBlockCache();
|
JIT->ResetBlockCache();
|
||||||
ARMJIT_Memory::Reset();
|
JIT->Memory.Reset();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1401,9 +1393,7 @@ void MapSharedWRAM(u8 val)
|
||||||
if (val == WRAMCnt)
|
if (val == WRAMCnt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->Memory.RemapSWRAM();
|
||||||
ARMJIT_Memory::RemapSWRAM();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WRAMCnt = val;
|
WRAMCnt = val;
|
||||||
|
|
||||||
|
@ -2315,18 +2305,14 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
switch (addr & 0xFF000000)
|
switch (addr & 0xFF000000)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
*(u8*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -2361,18 +2347,14 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
switch (addr & 0xFF000000)
|
switch (addr & 0xFF000000)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
*(u16*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -2387,9 +2369,7 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(addr);
|
|
||||||
#endif
|
|
||||||
switch (addr & 0x00E00000)
|
switch (addr & 0x00E00000)
|
||||||
{
|
{
|
||||||
case 0x00000000: GPU->WriteVRAM_ABG<u16>(addr, val); return;
|
case 0x00000000: GPU->WriteVRAM_ABG<u16>(addr, val); return;
|
||||||
|
@ -2429,18 +2409,14 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
switch (addr & 0xFF000000)
|
switch (addr & 0xFF000000)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
*(u32*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -2455,9 +2431,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(addr);
|
|
||||||
#endif
|
|
||||||
switch (addr & 0x00E00000)
|
switch (addr & 0x00E00000)
|
||||||
{
|
{
|
||||||
case 0x00000000: GPU->WriteVRAM_ABG<u32>(addr, val); return;
|
case 0x00000000: GPU->WriteVRAM_ABG<u32>(addr, val); return;
|
||||||
|
@ -2738,34 +2712,26 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
case 0x02800000:
|
case 0x02800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM7.Mem)
|
if (SWRAM_ARM7.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
*(u8*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
*(u8*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x03800000:
|
case 0x03800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
|
||||||
#endif
|
|
||||||
*(u8*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
*(u8*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2775,9 +2741,7 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
case 0x06800000:
|
case 0x06800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
GPU->WriteVRAM_ARM7<u8>(addr, val);
|
GPU->WriteVRAM_ARM7<u8>(addr, val);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2808,34 +2772,26 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
case 0x02800000:
|
case 0x02800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM7.Mem)
|
if (SWRAM_ARM7.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
*(u16*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
*(u16*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x03800000:
|
case 0x03800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
|
||||||
#endif
|
|
||||||
*(u16*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
*(u16*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2854,9 +2810,7 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
case 0x06800000:
|
case 0x06800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
GPU->WriteVRAM_ARM7<u16>(addr, val);
|
GPU->WriteVRAM_ARM7<u16>(addr, val);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2889,34 +2843,26 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
case 0x02800000:
|
case 0x02800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM7.Mem)
|
if (SWRAM_ARM7.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
*(u32*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
*(u32*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x03800000:
|
case 0x03800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(addr);
|
|
||||||
#endif
|
|
||||||
*(u32*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
*(u32*)&ARM7WRAM[addr & (ARM7WRAMSize - 1)] = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2936,9 +2882,7 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
|
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
case 0x06800000:
|
case 0x06800000:
|
||||||
#ifdef JIT_ENABLED
|
NDS::JIT->CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(addr);
|
|
||||||
#endif
|
|
||||||
GPU->WriteVRAM_ARM7<u32>(addr, val);
|
GPU->WriteVRAM_ARM7<u32>(addr, val);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,11 @@ namespace Melon
|
||||||
class GPU;
|
class GPU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
|
{
|
||||||
|
class ARMJIT;
|
||||||
|
}
|
||||||
|
|
||||||
namespace NDS
|
namespace NDS
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -269,6 +274,7 @@ extern class Wifi* Wifi;
|
||||||
extern std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot;
|
extern std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot;
|
||||||
extern std::unique_ptr<GBACart::GBACartSlot> GBACartSlot;
|
extern std::unique_ptr<GBACart::GBACartSlot> GBACartSlot;
|
||||||
extern std::unique_ptr<Melon::GPU> GPU;
|
extern std::unique_ptr<Melon::GPU> GPU;
|
||||||
|
extern std::unique_ptr<ARMJIT::ARMJIT> JIT;
|
||||||
extern class AREngine* AREngine;
|
extern class AREngine* AREngine;
|
||||||
|
|
||||||
const u32 ARM7WRAMSize = 0x10000;
|
const u32 ARM7WRAMSize = 0x10000;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef NDSCART_H
|
#ifndef NDSCART_H
|
||||||
#define NDSCART_H
|
#define NDSCART_H
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
Copyright 2016-2023 melonDS team, RSDuck
|
||||||
|
|
||||||
|
This file is part of melonDS.
|
||||||
|
|
||||||
|
melonDS 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, either version 3 of the License, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
melonDS 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 for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MELONDS_TINYVECTOR_H
|
||||||
|
#define MELONDS_TINYVECTOR_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
namespace ARMJIT
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
TinyVector
|
||||||
|
- because reinventing the wheel is the best!
|
||||||
|
|
||||||
|
- meant to be used very often, with not so many elements
|
||||||
|
max 1 << 16 elements
|
||||||
|
- doesn't allocate while no elements are inserted
|
||||||
|
- not stl confirmant of course
|
||||||
|
- probably only works with POD types
|
||||||
|
- remove operations don't preserve order, but O(1)!
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
struct __attribute__((packed)) TinyVector
|
||||||
|
{
|
||||||
|
T* Data = NULL;
|
||||||
|
u16 Capacity = 0;
|
||||||
|
u16 Length = 0;
|
||||||
|
|
||||||
|
~TinyVector()
|
||||||
|
{
|
||||||
|
delete[] Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeCapacity(u32 capacity)
|
||||||
|
{
|
||||||
|
assert(capacity <= UINT16_MAX);
|
||||||
|
assert(capacity > Capacity);
|
||||||
|
T* newMem = new T[capacity];
|
||||||
|
if (Data != NULL)
|
||||||
|
memcpy(newMem, Data, sizeof(T) * Length);
|
||||||
|
|
||||||
|
T* oldData = Data;
|
||||||
|
Data = newMem;
|
||||||
|
if (oldData != NULL)
|
||||||
|
delete[] oldData;
|
||||||
|
|
||||||
|
Capacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLength(u16 length)
|
||||||
|
{
|
||||||
|
if (Capacity < length)
|
||||||
|
MakeCapacity(length);
|
||||||
|
|
||||||
|
Length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
Length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(T element)
|
||||||
|
{
|
||||||
|
assert(Length + 1 <= UINT16_MAX);
|
||||||
|
if (Length + 1 > Capacity)
|
||||||
|
MakeCapacity(((Capacity + 4) * 3) / 2);
|
||||||
|
|
||||||
|
Data[Length++] = element;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Remove(int index)
|
||||||
|
{
|
||||||
|
assert(Length > 0);
|
||||||
|
assert(index >= 0 && index < Length);
|
||||||
|
|
||||||
|
Length--;
|
||||||
|
Data[index] = Data[Length];
|
||||||
|
/*for (int i = index; i < Length; i++)
|
||||||
|
Data[i] = Data[i + 1];*/
|
||||||
|
}
|
||||||
|
|
||||||
|
int Find(T needle)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Length; i++)
|
||||||
|
{
|
||||||
|
if (Data[i] == needle)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RemoveByValue(T needle)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Length; i++)
|
||||||
|
{
|
||||||
|
if (Data[i] == needle)
|
||||||
|
{
|
||||||
|
Remove(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](int index)
|
||||||
|
{
|
||||||
|
assert(index >= 0 && index < Length);
|
||||||
|
return Data[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MELONDS_TINYVECTOR_H
|
Loading…
Reference in New Issue