reconcile DSi and JIT, fastmem for x64 and Windows

This commit is contained in:
RSDuck
2020-06-30 23:50:41 +02:00
parent ea6d03581b
commit c5381d2911
29 changed files with 1691 additions and 5492 deletions

View File

@ -1,5 +1,7 @@
#ifdef __SWITCH__
#if defined(__SWITCH__)
#include "switch/compat_switch.h"
#elif defined(_WIN32)
#include <windows.h>
#endif
#include "ARMJIT_Memory.h"
@ -7,6 +9,7 @@
#include "ARMJIT_Internal.h"
#include "ARMJIT_Compiler.h"
#include "DSi.h"
#include "GPU.h"
#include "GPU3D.h"
#include "Wifi.h"
@ -37,66 +40,24 @@
namespace ARMJIT_Memory
{
#ifdef __aarch64__
struct FaultDescription
{
u64 IntegerRegisters[33];
u64 FaultAddr;
u32 GetEmulatedAddr()
{
// now this is podracing
return (u32)IntegerRegisters[0];
}
u64 RealAddr()
{
return FaultAddr;
}
u64 GetPC()
{
return IntegerRegisters[32];
}
void RestoreAndRepeat(s64 offset);
u32 EmulatedFaultAddr;
u64 FaultPC;
};
#else
struct FaultDescription
{
u64 GetPC()
{
return 0;
}
u32 GetEmulatedAddr()
{
return 0;
}
u64 RealAddr()
{
return 0;
}
void RestoreAndRepeat(s64 offset);
};
#endif
void FaultHandler(FaultDescription* faultDesc);
bool FaultHandler(FaultDescription* faultDesc, s32& offset);
}
#ifdef __aarch64__
extern "C" void ARM_RestoreContext(u64* registers) __attribute__((noreturn));
#endif
#ifdef __SWITCH__
#if defined(__SWITCH__)
// with LTO the symbols seem to be not properly overriden
// if they're somewhere else
extern "C"
{
void ARM_RestoreContext(u64* registers) __attribute__((noreturn));
extern char __start__;
extern char __rodata_start;
@ -106,57 +67,85 @@ u64 __nx_exception_stack_size = 0x8000;
void __libnx_exception_handler(ThreadExceptionDump* ctx)
{
ARMJIT_Memory::FaultDescription desc;
memcpy(desc.IntegerRegisters, &ctx->cpu_gprs[0].x, 8*29);
desc.IntegerRegisters[29] = ctx->fp.x;
desc.IntegerRegisters[30] = ctx->lr.x;
desc.IntegerRegisters[31] = ctx->sp.x;
desc.IntegerRegisters[32] = ctx->pc.x;
desc.EmulatedFaultAddr = ctx->cpu_gprs[0].w;
desc.FaultPC = ctx->pc.x;
ARMJIT_Memory::FaultHandler(&desc);
u64 integerRegisters[33];
memcpy(integerRegisters, &ctx->cpu_gprs[0].x, 8*29);
integerRegisters[29] = ctx->fp.x;
integerRegisters[30] = ctx->lr.x;
integerRegisters[31] = ctx->sp.x;
integerRegisters[32] = ctx->pc.x;
s32 offset;
if (ARMJIT_Memory::FaultHandler(&desc, offset))
{
integerRegisters[32] += offset;
ARM_RestoreContext(integerRegisters);
}
if (ctx->pc.x >= (u64)&__start__ && ctx->pc.x < (u64)&__rodata_start)
{
printf("non JIT fault in .text at 0x%x (type %d) (trying to access 0x%x?)\n",
printf("unintentional fault in .text at 0x%x (type %d) (trying to access 0x%x?)\n",
ctx->pc.x - (u64)&__start__, ctx->error_desc, ctx->far.x);
}
else
{
printf("non JIT fault somewhere in deep (address) space at %x (type %d)\n", ctx->pc.x, ctx->error_desc);
printf("unintentional fault somewhere in deep (address) space at %x (type %d)\n", ctx->pc.x, ctx->error_desc);
}
}
}
#elif defined(_WIN32)
static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
{
if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_CONTINUE_SEARCH;
ARMJIT_Memory::FaultDescription desc;
desc.EmulatedFaultAddr = exceptionInfo->ContextRecord->Rcx;
desc.FaultPC = exceptionInfo->ContextRecord->Rip;
s32 offset = 0;
if (ARMJIT_Memory::FaultHandler(&desc, offset))
{
exceptionInfo->ContextRecord->Rip += offset;
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
namespace ARMJIT_Memory
{
#ifdef __aarch64__
void FaultDescription::RestoreAndRepeat(s64 offset)
{
IntegerRegisters[32] += offset;
void* FastMem9Start, *FastMem7Start;
ARM_RestoreContext(IntegerRegisters);
#ifdef _WIN32
inline u32 RoundUp(u32 size)
{
return (size + 0xFFFF) & ~0xFFFF;
}
#else
void FaultDescription::RestoreAndRepeat(s64 offset)
inline u32 RoundUp(u32 size)
{
return size;
}
#endif
void* FastMem9Start, *FastMem7Start;
const u32 MemoryTotalSize =
NDS::MainRAMSize
+ NDS::SharedWRAMSize
+ NDS::ARM7WRAMSize
+ DTCMPhysicalSize;
const u32 MemBlockMainRAMOffset = 0;
const u32 MemBlockSWRAMOffset = NDS::MainRAMSize;
const u32 MemBlockARM7WRAMOffset = NDS::MainRAMSize + NDS::SharedWRAMSize;
const u32 MemBlockDTCMOffset = NDS::MainRAMSize + NDS::SharedWRAMSize + NDS::ARM7WRAMSize;
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] =
{
@ -173,6 +162,11 @@ const u32 OffsetsPerRegion[memregions_Count] =
UINT32_MAX,
UINT32_MAX,
UINT32_MAX,
UINT32_MAX,
UINT32_MAX,
MemBlockNWRAM_AOffset,
MemBlockNWRAM_BOffset,
MemBlockNWRAM_COffset
};
enum
@ -186,11 +180,13 @@ enum
u8 MappingStatus9[1 << (32-12)];
u8 MappingStatus7[1 << (32-12)];
#ifdef __SWITCH__
#if defined(__SWITCH__)
u8* MemoryBase;
u8* MemoryBaseCodeMem;
#else
#elif defined(_WIN32)
u8* MemoryBase;
HANDLE MemoryFile;
LPVOID ExceptionHandlerHandle;
#endif
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
@ -200,6 +196,9 @@ bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
Result r = (svcMapProcessMemory(dst, envGetOwnProcessHandle(),
(u64)(MemoryBaseCodeMem + offset), size));
return R_SUCCEEDED(r);
#elif defined(_WIN32)
bool r = MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, offset, size, dst) == dst;
return r;
#endif
}
@ -209,8 +208,24 @@ bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size)
#ifdef __SWITCH__
Result r = svcUnmapProcessMemory(dst, envGetOwnProcessHandle(),
(u64)(MemoryBaseCodeMem + offset), size);
printf("%x\n", r);
return R_SUCCEEDED(r);
#else
return UnmapViewOfFile(dst);
#endif
}
void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
{
u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
#if defined(_WIN32)
DWORD winProtection, oldProtection;
if (protection == 0)
winProtection = PAGE_NOACCESS;
else if (protection == 1)
winProtection = PAGE_READONLY;
else
winProtection = PAGE_READWRITE;
VirtualProtect(dst, size, winProtection, &oldProtection);
#endif
}
@ -230,7 +245,6 @@ struct Mapping
if (skipDTCM && Addr + offset == NDS::ARM9->DTCMBase)
{
offset += NDS::ARM9->DTCMSize;
printf("%x skip\n", NDS::ARM9->DTCMSize);
}
else
{
@ -245,6 +259,7 @@ struct Mapping
offset += 0x1000;
}
#ifdef __SWITCH__
if (status == memstate_MappedRW)
{
u32 segmentSize = offset - segmentOffset;
@ -252,8 +267,12 @@ struct Mapping
bool success = UnmapFromRange(Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
assert(success);
}
#endif
}
}
#if defined(_WIN32)
UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
#endif
}
};
ARMJIT::TinyVector<Mapping> Mappings[memregions_Count];
@ -268,6 +287,8 @@ void SetCodeProtection(int region, u32 offset, bool protect)
Mapping& mapping = Mappings[region][i];
u32 effectiveAddr = mapping.Addr + (offset - mapping.LocalOffset);
if (offset < mapping.LocalOffset || offset >= mapping.LocalOffset + mapping.Size)
continue;
if (mapping.Num == 0
&& region != memregion_DTCM
&& effectiveAddr >= NDS::ARM9->DTCMBase
@ -276,16 +297,20 @@ void SetCodeProtection(int region, u32 offset, bool protect)
u8* states = (u8*)(mapping.Num == 0 ? MappingStatus9 : MappingStatus7);
printf("%d %x %d\n", states[effectiveAddr >> 12], effectiveAddr, mapping.Num);
printf("%x %d %x %x %x %d\n", effectiveAddr, mapping.Num, mapping.Addr, mapping.LocalOffset, mapping.Size, states[effectiveAddr >> 12]);
assert(states[effectiveAddr >> 12] == (protect ? memstate_MappedRW : memstate_MappedProtected));
states[effectiveAddr >> 12] = protect ? memstate_MappedProtected : memstate_MappedRW;
#if defined(__SWITCH__)
bool success;
if (protect)
success = UnmapFromRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
else
success = MapIntoRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
assert(success);
#elif defined(_WIN32)
SetCodeProtectionRange(effectiveAddr, 0x1000, mapping.Num, protect ? 1 : 2);
#endif
}
}
@ -314,8 +339,8 @@ void RemapDTCM(u32 newBase, u32 newSize)
printf("mapping %d %x %x %x %x\n", region, mapping.Addr, mapping.Size, mapping.Num, mapping.LocalOffset);
bool oldOverlap = NDS::ARM9->DTCMSize > 0 && ((oldDTCMBase >= start && oldDTCMBase < end) || (oldDTCBEnd >= start && oldDTCBEnd < end));
bool newOverlap = newSize > 0 && ((newBase >= start && newBase < end) || (newEnd >= start && newEnd < end));
bool oldOverlap = NDS::ARM9->DTCMSize > 0 && !(oldDTCMBase >= end || oldDTCBEnd < start);
bool newOverlap = newSize > 0 && !(newBase >= end || newEnd < start);
if (mapping.Num == 0 && (oldOverlap || newOverlap))
{
@ -336,19 +361,50 @@ void RemapDTCM(u32 newBase, u32 newSize)
Mappings[memregion_DTCM].Clear();
}
void RemapNWRAM(int num)
{
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length;)
{
Mapping& mapping = Mappings[memregion_SharedWRAM][i];
if (!(DSi::NWRAMStart[mapping.Num][num] >= mapping.Addr + mapping.Size
|| DSi::NWRAMEnd[mapping.Num][num] < mapping.Addr))
{
mapping.Unmap(memregion_SharedWRAM);
Mappings[memregion_SharedWRAM].Remove(i);
}
else
{
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].Clear();
}
void RemapSWRAM()
{
printf("remapping SWRAM\n");
for (int i = 0; i < Mappings[memregion_SWRAM].Length; i++)
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length; i++)
{
Mappings[memregion_SWRAM][i].Unmap(memregion_SWRAM);
Mappings[memregion_SharedWRAM][i].Unmap(memregion_SharedWRAM);
}
Mappings[memregion_SWRAM].Clear();
Mappings[memregion_SharedWRAM].Clear();
for (int i = 0; i < Mappings[memregion_WRAM7].Length; i++)
{
Mappings[memregion_WRAM7][i].Unmap(memregion_WRAM7);
}
Mappings[memregion_WRAM7].Clear();
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < Mappings[memregion_NewSharedWRAM_A + j].Length; i++)
{
Mappings[memregion_NewSharedWRAM_A + j][i].Unmap(memregion_NewSharedWRAM_A + j);
}
Mappings[memregion_NewSharedWRAM_A + j].Clear();
}
}
bool MapAtAddress(u32 addr)
@ -359,33 +415,36 @@ bool MapAtAddress(u32 addr)
? ClassifyAddress9(addr)
: ClassifyAddress7(addr);
if (!IsMappable(region))
if (!IsFastmemCompatible(region))
return false;
u32 mappingStart, mappingSize, memoryOffset, memorySize;
bool isMapped = GetRegionMapping(region, num, mappingStart, mappingSize, memoryOffset, memorySize);
return false;
u32 mirrorStart, mirrorSize, memoryOffset;
bool isMapped = GetMirrorLocation(region, num, addr, memoryOffset, mirrorStart, mirrorSize);
if (!isMapped)
return false;
// this calculation even works with DTCM
// which doesn't have to be aligned to it's own size
u32 mirrorStart = (addr - mappingStart) / memorySize * memorySize + mappingStart;
u8* states = num == 0 ? MappingStatus9 : MappingStatus7;
printf("trying to create mapping %08x %d %x %d %x\n", addr, num, memorySize, region, memoryOffset);
printf("trying to create mapping %x, %x %d %d\n", mirrorStart, mirrorSize, region, num);
bool isExecutable = ARMJIT::CodeMemRegions[region];
ARMJIT::AddressRange* range = ARMJIT::CodeMemRegions[region] + memoryOffset;
#if defined(_WIN32)
bool succeded = MapIntoRange(mirrorStart, num, OffsetsPerRegion[region] + memoryOffset, mirrorSize);
assert(succeded);
#endif
ARMJIT::AddressRange* range = ARMJIT::CodeMemRegions[region] + memoryOffset / 512;
// this overcomplicated piece of code basically just finds whole pieces of code memory
// which can be mapped
u32 offset = 0;
bool skipDTCM = num == 0 && region != memregion_DTCM;
while (offset < memorySize)
while (offset < mirrorSize)
{
if (skipDTCM && mirrorStart + offset == NDS::ARM9->DTCMBase)
{
SetCodeProtectionRange(NDS::ARM9->DTCMBase, NDS::ARM9->DTCMSize, 0, 0);
offset += NDS::ARM9->DTCMSize;
}
else
@ -393,7 +452,7 @@ bool MapAtAddress(u32 addr)
u32 sectionOffset = offset;
bool hasCode = isExecutable && ARMJIT::PageContainsCode(&range[offset / 512]);
while ((!isExecutable || ARMJIT::PageContainsCode(&range[offset / 512]) == hasCode)
&& offset < memorySize
&& offset < mirrorSize
&& (!skipDTCM || mirrorStart + offset != NDS::ARM9->DTCMBase))
{
assert(states[(mirrorStart + offset) >> 12] == memstate_Unmapped);
@ -403,41 +462,49 @@ bool MapAtAddress(u32 addr)
u32 sectionSize = offset - sectionOffset;
#if defined(__SWITCH__)
if (!hasCode)
{
printf("trying to map %x (size: %x) from %x\n", mirrorStart + sectionOffset, sectionSize, sectionOffset + memoryOffset + OffsetsPerRegion[region]);
bool succeded = MapIntoRange(mirrorStart + sectionOffset, num, sectionOffset + memoryOffset + OffsetsPerRegion[region], sectionSize);
assert(succeded);
}
#elif defined(_WIN32)
if (hasCode)
{
SetCodeProtectionRange(mirrorStart + offset, sectionSize, num, 1);
}
#endif
}
}
Mapping mapping{mirrorStart, memorySize, memoryOffset, num};
assert(num == 0 || num == 1);
Mapping mapping{mirrorStart, mirrorSize, memoryOffset, num};
Mappings[region].Add(mapping);
printf("mapped mirror at %08x-%08x\n", mirrorStart, mirrorStart + memorySize - 1);
printf("mapped mirror at %08x-%08x\n", mirrorStart, mirrorStart + mirrorSize - 1);
return true;
}
void FaultHandler(FaultDescription* faultDesc)
bool FaultHandler(FaultDescription* faultDesc, s32& offset)
{
if (ARMJIT::JITCompiler->IsJITFault(faultDesc->GetPC()))
if (ARMJIT::JITCompiler->IsJITFault(faultDesc->FaultPC))
{
bool rewriteToSlowPath = true;
u32 addr = faultDesc->GetEmulatedAddr();
u32 addr = faultDesc->EmulatedFaultAddr;
if ((NDS::CurCPU == 0 ? MappingStatus9 : MappingStatus7)[addr >> 12] == memstate_Unmapped)
rewriteToSlowPath = !MapAtAddress(faultDesc->GetEmulatedAddr());
rewriteToSlowPath = !MapAtAddress(faultDesc->EmulatedFaultAddr);
s64 offset = 0;
if (rewriteToSlowPath)
{
offset = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc->GetPC());
offset = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc->FaultPC);
}
faultDesc->RestoreAndRepeat(offset);
return true;
}
return false;
}
void Init()
@ -459,18 +526,34 @@ void Init()
FastMem7Start = virtmemReserve(0x100000000);
assert(FastMem7Start);
NDS::MainRAM = MemoryBaseCodeMem + MemBlockMainRAMOffset;
NDS::SharedWRAM = MemoryBaseCodeMem + MemBlockSWRAMOffset;
NDS::ARM7WRAM = MemoryBaseCodeMem + MemBlockARM7WRAMOffset;
NDS::ARM9->DTCM = MemoryBaseCodeMem + MemBlockDTCMOffset;
#else
MemoryBase = new u8[MemoryTotalSize];
u8* basePtr = MemoryBaseCodeMem;
#elif defined(_WIN32)
ExceptionHandlerHandle = AddVectoredExceptionHandler(1, ExceptionHandler);
NDS::MainRAM = MemoryBase + MemBlockMainRAMOffset;
NDS::SharedWRAM = MemoryBase + MemBlockSWRAMOffset;
NDS::ARM7WRAM = MemoryBase + MemBlockARM7WRAMOffset;
NDS::ARM9->DTCM = MemoryBase + MemBlockDTCMOffset;
MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MemoryTotalSize, NULL);
MemoryBase = (u8*)VirtualAlloc(NULL, MemoryTotalSize, MEM_RESERVE, PAGE_READWRITE);
FastMem9Start = VirtualAlloc(NULL, 0x100000000, MEM_RESERVE, PAGE_READWRITE);
FastMem7Start = VirtualAlloc(NULL, 0x100000000, MEM_RESERVE, PAGE_READWRITE);
// only free them after they have all been reserved
// so they can't overlap
VirtualFree(MemoryBase, 0, MEM_RELEASE);
VirtualFree(FastMem9Start, 0, MEM_RELEASE);
VirtualFree(FastMem7Start, 0, MEM_RELEASE);
MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, MemoryTotalSize, MemoryBase);
u8* basePtr = MemoryBase;
#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()
@ -482,8 +565,11 @@ void DeInit()
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
virtmemFree(MemoryBaseCodeMem, MemoryTotalSize);
free(MemoryBase);
#else
delete[] MemoryBase;
#elif defined(_WIN32)
assert(UnmapViewOfFile(MemoryBase));
CloseHandle(MemoryFile);
RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
#endif
}
@ -505,12 +591,23 @@ void Reset()
printf("done resetting jit mem\n");
}
bool IsMappable(int region)
bool IsFastmemCompatible(int region)
{
#ifdef _WIN32
/*
TODO: with some hacks, the smaller shared WRAM regions
could be mapped in some occaisons as well
*/
if (region == memregion_DTCM
|| region == memregion_SharedWRAM
|| region == memregion_NewSharedWRAM_B
|| region == memregion_NewSharedWRAM_C)
return false;
#endif
return OffsetsPerRegion[region] != UINT32_MAX;
}
bool GetRegionMapping(int region, u32 num, u32& mappingStart, u32& mappingSize, u32& memoryOffset, u32& memorySize)
bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mirrorStart, u32& mirrorSize)
{
memoryOffset = 0;
switch (region)
@ -518,137 +615,251 @@ bool GetRegionMapping(int region, u32 num, u32& mappingStart, u32& mappingSize,
case memregion_ITCM:
if (num == 0)
{
mappingStart = 0;
mappingSize = NDS::ARM9->ITCMSize;
memorySize = ITCMPhysicalSize;
return true;
}
return false;
case memregion_DTCM:
if (num == 0)
{
mappingStart = NDS::ARM9->DTCMBase;
mappingSize = NDS::ARM9->DTCMSize;
memorySize = DTCMPhysicalSize;
return true;
}
return false;
case memregion_BIOS9:
if (num == 0)
{
mappingStart = 0xFFFF0000;
mappingSize = 0x10000;
memorySize = 0x1000;
mirrorStart = addr & ~(ITCMPhysicalSize - 1);
mirrorSize = ITCMPhysicalSize;
return true;
}
return false;
case memregion_MainRAM:
mappingStart = 0x2000000;
mappingSize = 0x1000000;
memorySize = NDS::MainRAMSize;
mirrorStart = addr & ~NDS::MainRAMMask;
mirrorSize = NDS::MainRAMMask + 1;
return true;
case memregion_SWRAM:
mappingStart = 0x3000000;
if (num == 0 && NDS::SWRAM_ARM9.Mem)
{
mappingSize = 0x1000000;
memoryOffset = NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM;
memorySize = NDS::SWRAM_ARM9.Mask + 1;
return true;
}
else if (num == 1 && NDS::SWRAM_ARM7.Mem)
{
mappingSize = 0x800000;
memoryOffset = NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM;
memorySize = NDS::SWRAM_ARM7.Mask + 1;
return true;
}
return false;
case memregion_VRAM:
case memregion_BIOS9:
if (num == 0)
{
// this is a gross simplification
// mostly to make code on vram working
// it doesn't take any of the actual VRAM mappings into account
mappingStart = 0x6000000;
mappingSize = 0x1000000;
memorySize = 0x100000;
mirrorStart = addr & ~0xFFF;
mirrorSize = 0x1000;
return true;
}
return false;
case memregion_BIOS7:
if (num == 1)
{
mappingStart = 0;
mappingSize = 0x4000;
memorySize = 0x4000;
mirrorStart = 0;
mirrorSize = 0x4000;
return true;
}
return false;
case memregion_SharedWRAM:
if (num == 0 && NDS::SWRAM_ARM9.Mem)
{
mirrorStart = addr & ~NDS::SWRAM_ARM9.Mask;
mirrorSize = NDS::SWRAM_ARM9.Mask + 1;
memoryOffset = NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM;
return true;
}
else if (num == 1 && NDS::SWRAM_ARM7.Mem)
{
mirrorStart = addr & ~NDS::SWRAM_ARM7.Mask;
mirrorSize = NDS::SWRAM_ARM7.Mask + 1;
memoryOffset = NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM;
return true;
}
return false;
case memregion_WRAM7:
if (num == 1)
{
if (NDS::SWRAM_ARM7.Mem)
{
mappingStart = 0x3800000;
mappingSize = 0x800000;
}
else
{
mappingStart = 0x3000000;
mappingSize = 0x1000000;
}
memorySize = NDS::ARM7WRAMSize;
mirrorStart = addr & ~(NDS::ARM7WRAMSize - 1);
mirrorSize = NDS::ARM7WRAMSize;
return true;
}
return false;
case memregion_VRAM:
if (num == 0)
{
mirrorStart = addr & ~0xFFFFF;
mirrorSize = 0x100000;
}
return false;
case memregion_VWRAM:
if (num == 1)
{
mappingStart = 0x6000000;
mappingSize = 0x1000000;
memorySize = 0x20000;
mirrorStart = addr & ~0x3FFFF;
mirrorSize = 0x40000;
return true;
}
return false;
case memregion_NewSharedWRAM_A:
{
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
if (ptr)
{
memoryOffset = ptr - DSi::NWRAM_A;
mirrorStart = addr & ~0xFFFF;
mirrorSize = 0x10000;
return true;
}
return false; // zero filled memory
}
case memregion_NewSharedWRAM_B:
{
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
if (ptr)
{
memoryOffset = ptr - DSi::NWRAM_B;
mirrorStart = addr & ~0x7FFF;
mirrorSize = 0x8000;
return true;
}
return false; // zero filled memory
}
case memregion_NewSharedWRAM_C:
{
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
if (ptr)
{
memoryOffset = ptr - DSi::NWRAM_C;
mirrorStart = addr & ~0x7FFF;
mirrorSize = 0x8000;
return true;
}
return false; // zero filled memory
}
case memregion_BIOS9DSi:
if (num == 0)
{
mirrorStart = addr & ~0xFFFF;
mirrorSize = DSi::SCFG_BIOS & (1<<0) ? 0x8000 : 0x10000;
return true;
}
return false;
case memregion_BIOS7DSi:
if (num == 1)
{
mirrorStart = addr & ~0xFFFF;
mirrorSize = DSi::SCFG_BIOS & (1<<8) ? 0x8000 : 0x10000;
return true;
}
return false;
default:
// for the JIT we don't are about the rest
assert(false && "For the time being this should only be used for code");
return false;
}
}
u32 LocaliseAddress(int region, u32 num, u32 addr)
{
switch (region)
{
case memregion_ITCM:
return (addr & (ITCMPhysicalSize - 1)) | (memregion_ITCM << 27);
case memregion_MainRAM:
return (addr & NDS::MainRAMMask) | (memregion_MainRAM << 27);
case memregion_BIOS9:
return (addr & 0xFFF) | (memregion_BIOS9 << 27);
case memregion_BIOS7:
return (addr & 0x3FFF) | (memregion_BIOS7 << 27);
case memregion_SharedWRAM:
if (num == 0)
return ((addr & NDS::SWRAM_ARM9.Mask) + (NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM)) | (memregion_SharedWRAM << 27);
else
return ((addr & NDS::SWRAM_ARM7.Mask) + (NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM)) | (memregion_SharedWRAM << 27);
case memregion_WRAM7:
return (addr & (NDS::ARM7WRAMSize - 1)) | (memregion_WRAM7 << 27);
case memregion_VRAM:
// TODO: take mapping properly into account
return (addr & 0xFFFFF) | (memregion_VRAM << 27);
case memregion_VWRAM:
// same here
return (addr & 0x3FFFF) | (memregion_VWRAM << 27);
case memregion_NewSharedWRAM_A:
{
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
if (ptr)
return (ptr - DSi::NWRAM_A + (addr & 0xFFFF)) | (memregion_NewSharedWRAM_A << 27);
else
return memregion_Other << 27; // zero filled memory
}
case memregion_NewSharedWRAM_B:
{
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
if (ptr)
return (ptr - DSi::NWRAM_B + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_B << 27);
else
return memregion_Other << 27;
}
case memregion_NewSharedWRAM_C:
{
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
if (ptr)
return (ptr - DSi::NWRAM_C + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_C << 27);
else
return memregion_Other << 27;
}
case memregion_BIOS9DSi:
case memregion_BIOS7DSi:
return (addr & 0xFFFF) | (region << 27);
default:
assert(false && "This should only be needed for regions which can contain code");
return memregion_Other << 27;
}
}
int ClassifyAddress9(u32 addr)
{
if (addr < NDS::ARM9->ITCMSize)
return memregion_ITCM;
else if (addr >= NDS::ARM9->DTCMBase && addr < (NDS::ARM9->DTCMBase + NDS::ARM9->DTCMSize))
return memregion_DTCM;
else if ((addr & 0xFFFFF000) == 0xFFFF0000)
return memregion_BIOS9;
else
{
return memregion_ITCM;
}
else if (addr >= NDS::ARM9->DTCMBase && addr < (NDS::ARM9->DTCMBase + NDS::ARM9->DTCMSize))
{
return memregion_DTCM;
}
else
{
if (NDS::ConsoleType == 1 && addr >= 0xFFFF0000 && !(DSi::SCFG_BIOS & (1<<1)))
{
if ((addr >= 0xFFFF8000) && (DSi::SCFG_BIOS & (1<<0)))
return memregion_Other;
return memregion_BIOS9DSi;
}
else if ((addr & 0xFFFFF000) == 0xFFFF0000)
{
return memregion_BIOS9;
}
switch (addr & 0xFF000000)
{
case 0x02000000:
return memregion_MainRAM;
case 0x03000000:
if (NDS::ConsoleType == 1)
{
if (addr >= DSi::NWRAMStart[0][0] && addr < DSi::NWRAMEnd[0][0])
return memregion_NewSharedWRAM_A;
if (addr >= DSi::NWRAMStart[0][1] && addr < DSi::NWRAMEnd[0][1])
return memregion_NewSharedWRAM_B;
if (addr >= DSi::NWRAMStart[0][2] && addr < DSi::NWRAMEnd[0][2])
return memregion_NewSharedWRAM_C;
}
if (NDS::SWRAM_ARM9.Mem)
return memregion_SWRAM;
else
return memregion_Other;
return memregion_SharedWRAM;
return memregion_Other;
case 0x04000000:
return memregion_IO9;
case 0x06000000:
return memregion_VRAM;
default:
return memregion_Other;
}
}
return memregion_Other;
}
int ClassifyAddress7(u32 addr)
{
if (addr < 0x00004000)
if (NDS::ConsoleType == 1 && addr < 0x00010000 && !(DSi::SCFG_BIOS & (1<<9)))
{
if (addr >= 0x00008000 && DSi::SCFG_BIOS & (1<<8))
return memregion_Other;
return memregion_BIOS7DSi;
}
else if (addr < 0x00004000)
{
return memregion_BIOS7;
}
else
{
switch (addr & 0xFF800000)
@ -657,10 +868,19 @@ int ClassifyAddress7(u32 addr)
case 0x02800000:
return memregion_MainRAM;
case 0x03000000:
if (NDS::ConsoleType == 1)
{
if (addr >= DSi::NWRAMStart[1][0] && addr < DSi::NWRAMEnd[1][0])
return memregion_NewSharedWRAM_A;
if (addr >= DSi::NWRAMStart[1][1] && addr < DSi::NWRAMEnd[1][1])
return memregion_NewSharedWRAM_B;
if (addr >= DSi::NWRAMStart[1][2] && addr < DSi::NWRAMEnd[1][2])
return memregion_NewSharedWRAM_C;
}
if (NDS::SWRAM_ARM7.Mem)
return memregion_SWRAM;
else
return memregion_WRAM7;
return memregion_SharedWRAM;
return memregion_WRAM7;
case 0x03800000:
return memregion_WRAM7;
case 0x04000000:
@ -740,14 +960,29 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
}
}
switch (size | store)
if (NDS::ConsoleType == 0)
{
case 8: return (void*)NDS::ARM9IORead8;
case 9: return (void*)NDS::ARM9IOWrite8;
case 16: return (void*)NDS::ARM9IORead16;
case 17: return (void*)NDS::ARM9IOWrite16;
case 32: return (void*)NDS::ARM9IORead32;
case 33: return (void*)NDS::ARM9IOWrite32;
switch (size | store)
{
case 8: return (void*)NDS::ARM9IORead8;
case 9: return (void*)NDS::ARM9IOWrite8;
case 16: return (void*)NDS::ARM9IORead16;
case 17: return (void*)NDS::ARM9IOWrite16;
case 32: return (void*)NDS::ARM9IORead32;
case 33: return (void*)NDS::ARM9IOWrite32;
}
}
else
{
switch (size | store)
{
case 8: return (void*)DSi::ARM9IORead8;
case 9: return (void*)DSi::ARM9IOWrite8;
case 16: return (void*)DSi::ARM9IORead16;
case 17: return (void*)DSi::ARM9IOWrite16;
case 32: return (void*)DSi::ARM9IORead32;
case 33: return (void*)DSi::ARM9IOWrite32;
}
}
break;
case 0x06000000:
@ -781,14 +1016,29 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
}
}
switch (size | store)
if (NDS::ConsoleType == 0)
{
case 8: return (void*)NDS::ARM7IORead8;
case 9: return (void*)NDS::ARM7IOWrite8;
case 16: return (void*)NDS::ARM7IORead16;
case 17: return (void*)NDS::ARM7IOWrite16;
case 32: return (void*)NDS::ARM7IORead32;
case 33: return (void*)NDS::ARM7IOWrite32;
switch (size | store)
{
case 8: return (void*)NDS::ARM7IORead8;
case 9: return (void*)NDS::ARM7IOWrite8;
case 16: return (void*)NDS::ARM7IORead16;
case 17: return (void*)NDS::ARM7IOWrite16;
case 32: return (void*)NDS::ARM7IORead32;
case 33: return (void*)NDS::ARM7IOWrite32;
}
}
else
{
switch (size | store)
{
case 8: return (void*)DSi::ARM7IORead8;
case 9: return (void*)DSi::ARM7IOWrite8;
case 16: return (void*)DSi::ARM7IORead16;
case 17: return (void*)DSi::ARM7IOWrite16;
case 32: return (void*)DSi::ARM7IORead32;
case 33: return (void*)DSi::ARM7IOWrite32;
}
}
break;
case 0x04800000: