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:
Jesse Talavera-Greenberg 2023-11-18 10:40:54 -05:00 committed by GitHub
parent f2d7a29015
commit 544fefa27f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 894 additions and 889 deletions

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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(&region[(addressRanges[j] & 0x7FFF000) / 512])) if (!PageContainsCode(&region[(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 = &region[(addressRanges[j] & 0x7FFFFFF) / 512]; AddressRange* range = &region[(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(&region[(localAddr & 0x7FFF000) / 512])) && !PageContainsCode(&region[(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, *))

View File

@ -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

View File

@ -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++)
{ {

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
} }
}

View File

@ -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

View File

@ -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"

View File

@ -17,6 +17,7 @@
*/ */
#include "ARMJIT_Compiler.h" #include "ARMJIT_Compiler.h"
#include "../ARM.h"
using namespace Gen; using namespace Gen;

View File

@ -17,6 +17,7 @@
*/ */
#include "ARMJIT_Compiler.h" #include "ARMJIT_Compiler.h"
#include "../ARM.h"
using namespace Gen; using namespace Gen;

View File

@ -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;

View File

@ -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 {};
}; };
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -274,7 +274,7 @@ struct Info
} }
}; };
Info Decode(bool thumb, u32 num, u32 instr); Info Decode(bool thumb, u32 num, u32 instr, bool literaloptimizations);
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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] {};

61
src/JitBlock.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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>

131
src/TinyVector.h Normal file
View File

@ -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