diff options
| author | 2014-04-18 17:52:49 -0400 | |
|---|---|---|
| committer | 2014-04-18 17:52:49 -0400 | |
| commit | 958bca606e80110e05d7c142dda3097fddc96503 (patch) | |
| tree | 576917751444b4dfdb476d040b4e075bde431b7b /src/core/mem_map_funcs.cpp | |
| parent | Init window size from VideoCore. Start changing the default window behavior... (diff) | |
| parent | renamed hw_lcd module to just lcd (diff) | |
| download | yuzu-958bca606e80110e05d7c142dda3097fddc96503.tar.gz yuzu-958bca606e80110e05d7c142dda3097fddc96503.tar.xz yuzu-958bca606e80110e05d7c142dda3097fddc96503.zip | |
Merge branch 'hle-interface'
Diffstat (limited to 'src/core/mem_map_funcs.cpp')
| -rw-r--r-- | src/core/mem_map_funcs.cpp | 197 |
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 | ||
| 10 | namespace Memory { | 13 | namespace Memory { |
| 11 | 14 | ||
| 15 | std::map<u32, HeapBlock> g_heap_gsp_map; | ||
| 16 | |||
| 17 | /// Convert a physical address to virtual address | ||
| 18 | u32 _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 | |||
| 12 | template <typename T> | 28 | template <typename T> |
| 13 | inline void _Read(T &var, const u32 addr) { | 29 | inline 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 | ||
| 47 | template <typename T> | 63 | template <typename T> |
| 48 | inline void _Write(u32 addr, const T data) { | 64 | inline 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 | ||
| 102 | bool IsValidAddress(const u32 addr) { | 106 | u8 *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 | ||
| 116 | u8 *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. | 128 | u32 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 | ||
| 150 | u8 Read8(const u32 addr) { | 145 | u8 Read8(const u32 addr) { |