summaryrefslogtreecommitdiff
path: root/src/core/mem_map_funcs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/mem_map_funcs.cpp')
-rw-r--r--src/core/mem_map_funcs.cpp197
1 files changed, 96 insertions, 101 deletions
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 4c0e08b3f..af4cfacbd 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -2,149 +2,144 @@
2// Licensed under GPLv2 2// Licensed under GPLv2
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map>
6
5#include "common/common.h" 7#include "common/common.h"
6 8
7#include "core/mem_map.h" 9#include "core/mem_map.h"
8#include "core/hw/hw.h" 10#include "core/hw/hw.h"
11#include "hle/hle.h"
9 12
10namespace Memory { 13namespace Memory {
11 14
15std::map<u32, HeapBlock> g_heap_gsp_map;
16
17/// Convert a physical address to virtual address
18u32 _AddressPhysicalToVirtual(const u32 addr) {
19 // Our memory interface read/write functions assume virtual addresses. Put any physical address
20 // to virtual address translations here. This is obviously quite hacky... But we're not doing
21 // any MMU emulation yet or anything
22 if ((addr >= FCRAM_PADDR) && (addr < (FCRAM_PADDR_END))) {
23 return (addr & FCRAM_MASK) | FCRAM_VADDR;
24 }
25 return addr;
26}
27
12template <typename T> 28template <typename T>
13inline void _Read(T &var, const u32 addr) { 29inline void _Read(T &var, const u32 addr) {
14 // TODO: Figure out the fastest order of tests for both read and write (they are probably different). 30 // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
15 // TODO: Make sure this represents the mirrors in a correct way. 31 // TODO: Make sure this represents the mirrors in a correct way.
16 // Could just do a base-relative read, too.... TODO 32 // Could just do a base-relative read, too.... TODO
17 33
34 const u32 vaddr = _AddressPhysicalToVirtual(addr);
35
36 // Memory allocated for HLE use that can be addressed from the emulated application
37 // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
38 // core running the user application (appcore)
39 if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) {
40 HLE::Read<T>(var, vaddr);
41
18 // Hardware I/O register reads 42 // Hardware I/O register reads
19 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space 43 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
20 if ((addr & 0xFF000000) == 0x10000000 || (addr & 0xFF000000) == 0x1E000000) { 44 } else if ((vaddr & 0xFF000000) == 0x10000000 || (vaddr & 0xFF000000) == 0x1E000000) {
21 HW::Read<T>(var, addr); 45 HW::Read<T>(var, vaddr);
22 46
23 // FCRAM virtual address reads 47 // FCRAM - GSP heap
24 } else if ((addr & 0x3E000000) == 0x08000000) { 48 } else if ((vaddr > HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
25 var = *((const T*)&g_fcram[addr & MEM_FCRAM_MASK]); 49 var = *((const T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK]);
26 50
27 // Scratchpad memory 51 // FCRAM - application heap
28 } else if (addr > MEM_SCRATCHPAD_VADDR && addr <= (MEM_SCRATCHPAD_VADDR + MEM_SCRATCHPAD_SIZE)) { 52 } else if ((vaddr > HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
29 var = *((const T*)&g_scratchpad[addr & MEM_SCRATCHPAD_MASK]); 53 var = *((const T*)&g_heap[vaddr & HEAP_MASK]);
30 54
31 /*else if ((addr & 0x3F800000) == 0x04000000) { 55 /*else if ((vaddr & 0x3F800000) == 0x04000000) {
32 var = *((const T*)&m_pVRAM[addr & VRAM_MASK]); 56 var = *((const T*)&m_pVRAM[vaddr & VRAM_MASK]);*/
33 }*/
34
35 // HACK(bunnei): There is no layer yet to translate virtual addresses to physical addresses.
36 // Until we progress far enough along, we'll accept all physical address reads here. I think
37 // that this is typically a corner-case from usermode software unless they are trying to do
38 // bare-metal things (e.g. early 3DS homebrew writes directly to the FB @ 0x20184E60, etc.
39 } else if (((addr & 0xF0000000) == MEM_FCRAM_PADDR) && (addr < (MEM_FCRAM_PADDR_END))) {
40 var = *((const T*)&g_fcram[addr & MEM_FCRAM_MASK]);
41 57
42 } else { 58 } else {
43 _assert_msg_(MEMMAP, false, "unknown memory read"); 59 //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
44 } 60 }
45} 61}
46 62
47template <typename T> 63template <typename T>
48inline void _Write(u32 addr, const T data) { 64inline void _Write(u32 addr, const T data) {
65 u32 vaddr = _AddressPhysicalToVirtual(addr);
49 66
67 // Memory allocated for HLE use that can be addressed from the emulated application
68 // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
69 // core running the user application (appcore)
70 if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) {
71 HLE::Write<T>(vaddr, data);
72
50 // Hardware I/O register writes 73 // Hardware I/O register writes
51 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space 74 // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
52 if ((addr & 0xFF000000) == 0x10000000 || (addr & 0xFF000000) == 0x1E000000) { 75 } else if ((vaddr & 0xFF000000) == 0x10000000 || (vaddr & 0xFF000000) == 0x1E000000) {
53 HW::Write<const T>(addr, data); 76 HW::Write<T>(vaddr, data);
54 77
55 // ExeFS:/.code is loaded here: 78 // FCRAM - GSP heap
56 } else if ((addr & 0xFFF00000) == 0x00100000) { 79 } else if ((vaddr > HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
57 // TODO(ShizZy): This is dumb... handle correctly. From 3DBrew: 80 *(T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK] = data;
58 // http://3dbrew.org/wiki/Memory_layout#ARM11_User-land_memory_regions 81
59 // The ExeFS:/.code is loaded here, executables must be loaded to the 0x00100000 region when 82 // FCRAM - application heap
60 // the exheader "special memory" flag is clear. The 0x03F00000-byte size restriction only 83 } else if ((vaddr > HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
61 // applies when this flag is clear. Executables are usually loaded to 0x14000000 when the 84 *(T*)&g_heap[vaddr & HEAP_MASK] = data;
62 // exheader "special memory" flag is set, however this address can be arbitrary. 85
63 *(T*)&g_fcram[addr & MEM_FCRAM_MASK] = data; 86 } else if ((vaddr & 0xFF000000) == 0x14000000) {
64
65 // Scratchpad memory
66 } else if (addr > MEM_SCRATCHPAD_VADDR && addr <= (MEM_SCRATCHPAD_VADDR + MEM_SCRATCHPAD_SIZE)) {
67 *(T*)&g_scratchpad[addr & MEM_SCRATCHPAD_MASK] = data;
68
69 // Heap mapped by ControlMemory:
70 } else if ((addr & 0x3E000000) == 0x08000000) {
71 // TODO(ShizZy): Writes to this virtual address should be put in physical memory at FCRAM + GSP
72 // heap size... the following is writing to FCRAM + 0, which is actually supposed to be the
73 // application's GSP heap
74 *(T*)&g_fcram[addr & MEM_FCRAM_MASK] = data;
75
76 } else if ((addr & 0xFF000000) == 0x14000000) {
77 _assert_msg_(MEMMAP, false, "umimplemented write to GSP heap"); 87 _assert_msg_(MEMMAP, false, "umimplemented write to GSP heap");
78 } else if ((addr & 0xFFF00000) == 0x1EC00000) { 88 } else if ((vaddr & 0xFFF00000) == 0x1EC00000) {
79 _assert_msg_(MEMMAP, false, "umimplemented write to IO registers"); 89 _assert_msg_(MEMMAP, false, "umimplemented write to IO registers");
80 } else if ((addr & 0xFF000000) == 0x1F000000) { 90 } else if ((vaddr & 0xFF000000) == 0x1F000000) {
81 _assert_msg_(MEMMAP, false, "umimplemented write to VRAM"); 91 _assert_msg_(MEMMAP, false, "umimplemented write to VRAM");
82 } else if ((addr & 0xFFF00000) == 0x1FF00000) { 92 } else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
83 _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory"); 93 _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
84 } else if ((addr & 0xFFFF0000) == 0x1FF80000) { 94 } else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
85 _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory"); 95 _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory");
86 } else if ((addr & 0xFFFFF000) == 0x1FF81000) { 96 } else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
87 _assert_msg_(MEMMAP, false, "umimplemented write to shared page"); 97 _assert_msg_(MEMMAP, false, "umimplemented write to shared page");
88 98
89 // HACK(bunnei): There is no layer yet to translate virtual addresses to physical addresses.
90 // Until we progress far enough along, we'll accept all physical address writes here. I think
91 // that this is typically a corner-case from usermode software unless they are trying to do
92 // bare-metal things (e.g. early 3DS homebrew writes directly to the FB @ 0x20184E60, etc.
93 } else if (((addr & 0xF0000000) == MEM_FCRAM_PADDR) && (addr < (MEM_FCRAM_PADDR_END))) {
94 *(T*)&g_fcram[addr & MEM_FCRAM_MASK] = data;
95
96 // Error out... 99 // Error out...
97 } else { 100 } else {
98 _assert_msg_(MEMMAP, false, "unknown memory write"); 101 _assert_msg_(MEMMAP, false, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8,
102 data, vaddr);
99 } 103 }
100} 104}
101 105
102bool IsValidAddress(const u32 addr) { 106u8 *GetPointer(const u32 addr) {
103 if ((addr & 0x3E000000) == 0x08000000) { 107 const u32 vaddr = _AddressPhysicalToVirtual(addr);
104 return true; 108
105 } else if ((addr & 0x3F800000) == 0x04000000) { 109 // FCRAM - GSP heap
106 return true; 110 if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
107 } else if ((addr & 0xBFFF0000) == 0x00010000) { 111 return g_heap_gsp + (vaddr & HEAP_GSP_MASK);
108 return true; 112
109 } else if ((addr & 0x3F000000) >= 0x08000000 && (addr & 0x3F000000) < 0x08000000 + MEM_FCRAM_MASK) { 113 // FCRAM - application heap
110 return true; 114 } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
115 return g_heap + (vaddr & HEAP_MASK);
116
111 } else { 117 } else {
112 return false; 118 ERROR_LOG(MEMMAP, "Unknown GetPointer @ 0x%08x", vaddr);
119 return 0;
113 } 120 }
114} 121}
115 122
116u8 *GetPointer(const u32 addr) { 123/**
117 // TODO(bunnei): Just a stub for now... ImplementMe! 124 * Maps a block of memory on the GSP heap
118 if ((addr & 0x3E000000) == 0x08000000) { 125 * @param size Size of block in bytes
119 return g_fcram + (addr & MEM_FCRAM_MASK); 126 * @param flags Memory allocation flags
120 127 */
121 // HACK(bunnei): There is no layer yet to translate virtual addresses to physical addresses. 128u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
122 // Until we progress far enough along, we'll accept all physical address reads here. I think 129 HeapBlock block;
123 // that this is typically a corner-case from usermode software unless they are trying to do 130
124 // bare-metal things (e.g. early 3DS homebrew writes directly to the FB @ 0x20184E60, etc. 131 block.base_address = HEAP_GSP_VADDR;
125 } else if (((addr & 0xF0000000) == MEM_FCRAM_PADDR) && (addr < (MEM_FCRAM_PADDR_END))) { 132 block.size = size;
126 return g_fcram + (addr & MEM_FCRAM_MASK); 133 block.operation = operation;
127 134 block.permissions = permissions;
128 //else if ((addr & 0x3F800000) == 0x04000000) { 135
129 // return g_vram + (addr & MEM_VRAM_MASK); 136 if (g_heap_gsp_map.size() > 0) {
130 //} 137 const HeapBlock last_block = g_heap_gsp_map.rbegin()->second;
131 //else if ((addr & 0x3F000000) >= 0x08000000 && (addr & 0x3F000000) < 0x08000000 + g_MemorySize) { 138 block.address = last_block.address + last_block.size;
132 // return m_pRAM + (addr & g_MemoryMask);
133 //}
134 } else {
135 //ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", addr, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
136 ERROR_LOG(MEMMAP, "Unknown GetPointer %08x", addr);
137 static bool reported = false;
138 //if (!reported) {
139 // Reporting::ReportMessage("Unknown GetPointer %08x PC %08x LR %08x", addr, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
140 // reported = true;
141 //}
142 //if (!g_Config.bIgnoreBadMemAccess) {
143 // Core_EnableStepping(true);
144 // host->SetDebugMode(true);
145 //}
146 return 0;
147 } 139 }
140 g_heap_gsp_map[block.GetVirtualAddress()] = block;
141
142 return block.GetVirtualAddress();
148} 143}
149 144
150u8 Read8(const u32 addr) { 145u8 Read8(const u32 addr) {