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