diff options
Diffstat (limited to 'src/ARMJIT_Memory.cpp')
-rw-r--r-- | src/ARMJIT_Memory.cpp | 636 |
1 files changed, 443 insertions, 193 deletions
diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp index 162827d..0276c65 100644 --- a/src/ARMJIT_Memory.cpp +++ b/src/ARMJIT_Memory.cpp @@ -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); -}; -#else struct FaultDescription { - u64 GetPC() - { - return 0; - } - - u32 GetEmulatedAddr() - { - return 0; - } - u64 RealAddr() - { - return 0; - } - - void RestoreAndRepeat(s64 offset); + u32 EmulatedFaultAddr; + u64 FaultPC; }; -#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; + + 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; - ARMJIT_Memory::FaultHandler(&desc); + 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); + + MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MemoryTotalSize, NULL); - NDS::MainRAM = MemoryBase + MemBlockMainRAMOffset; - NDS::SharedWRAM = MemoryBase + MemBlockSWRAMOffset; - NDS::ARM7WRAM = MemoryBase + MemBlockARM7WRAMOffset; - NDS::ARM9->DTCM = MemoryBase + MemBlockDTCMOffset; + 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; + mirrorStart = addr & ~(ITCMPhysicalSize - 1); + mirrorSize = ITCMPhysicalSize; return true; } return false; - case memregion_DTCM: + case memregion_MainRAM: + mirrorStart = addr & ~NDS::MainRAMMask; + mirrorSize = NDS::MainRAMMask + 1; + return true; + case memregion_BIOS9: if (num == 0) { - mappingStart = NDS::ARM9->DTCMBase; - mappingSize = NDS::ARM9->DTCMSize; - memorySize = DTCMPhysicalSize; + mirrorStart = addr & ~0xFFF; + mirrorSize = 0x1000; return true; } return false; - case memregion_BIOS9: - if (num == 0) + case memregion_BIOS7: + if (num == 1) { - mappingStart = 0xFFFF0000; - mappingSize = 0x10000; - memorySize = 0x1000; + mirrorStart = 0; + mirrorSize = 0x4000; return true; } return false; - case memregion_MainRAM: - mappingStart = 0x2000000; - mappingSize = 0x1000000; - memorySize = NDS::MainRAMSize; - return true; - case memregion_SWRAM: - mappingStart = 0x3000000; + case memregion_SharedWRAM: if (num == 0 && NDS::SWRAM_ARM9.Mem) { - mappingSize = 0x1000000; + mirrorStart = addr & ~NDS::SWRAM_ARM9.Mask; + mirrorSize = NDS::SWRAM_ARM9.Mask + 1; 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; + mirrorStart = addr & ~NDS::SWRAM_ARM7.Mask; + mirrorSize = NDS::SWRAM_ARM7.Mask + 1; memoryOffset = NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM; - memorySize = NDS::SWRAM_ARM7.Mask + 1; + return true; + } + return false; + case memregion_WRAM7: + if (num == 1) + { + mirrorStart = addr & ~(NDS::ARM7WRAMSize - 1); + mirrorSize = NDS::ARM7WRAMSize; return true; } return false; case memregion_VRAM: 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; - return true; + mirrorStart = addr & ~0xFFFFF; + mirrorSize = 0x100000; } return false; - case memregion_BIOS7: + case memregion_VWRAM: if (num == 1) { - mappingStart = 0; - mappingSize = 0x4000; - memorySize = 0x4000; + mirrorStart = addr & ~0x3FFFF; + mirrorSize = 0x40000; return true; } return false; - case memregion_WRAM7: - if (num == 1) + case memregion_NewSharedWRAM_A: { - if (NDS::SWRAM_ARM7.Mem) + u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]]; + if (ptr) { - mappingStart = 0x3800000; - mappingSize = 0x800000; + memoryOffset = ptr - DSi::NWRAM_A; + mirrorStart = addr & ~0xFFFF; + mirrorSize = 0x10000; + return true; } - else + return false; // zero filled memory + } + case memregion_NewSharedWRAM_B: + { + u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]]; + if (ptr) { - mappingStart = 0x3000000; - mappingSize = 0x1000000; + memoryOffset = ptr - DSi::NWRAM_B; + mirrorStart = addr & ~0x7FFF; + mirrorSize = 0x8000; + return true; } - memorySize = NDS::ARM7WRAMSize; + 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_VWRAM: + case memregion_BIOS7DSi: if (num == 1) { - mappingStart = 0x6000000; - mappingSize = 0x1000000; - memorySize = 0x20000; + 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 + } + 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) + { + 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 { - 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*)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: |