mem_map_funcs.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <map>
  5. #include "common/common.h"
  6. #include "core/mem_map.h"
  7. #include "core/hw/hw.h"
  8. #include "hle/config_mem.h"
  9. #include "hle/shared_page.h"
  10. namespace Memory {
  11. static std::map<u32, MemoryBlock> heap_map;
  12. static std::map<u32, MemoryBlock> heap_linear_map;
  13. /// Convert a physical address to virtual address
  14. VAddr PhysicalToVirtualAddress(const PAddr addr) {
  15. // Our memory interface read/write functions assume virtual addresses. Put any physical address
  16. // to virtual address translations here. This is quite hacky, but necessary until we implement
  17. // proper MMU emulation.
  18. // TODO: Screw it, I'll let bunnei figure out how to do this properly.
  19. if (addr == 0) {
  20. return 0;
  21. } else if ((addr >= VRAM_PADDR) && (addr < VRAM_PADDR_END)) {
  22. return addr - VRAM_PADDR + VRAM_VADDR;
  23. } else if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) {
  24. return addr - FCRAM_PADDR + HEAP_LINEAR_VADDR;
  25. }
  26. LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr);
  27. return addr;
  28. }
  29. /// Convert a physical address to virtual address
  30. PAddr VirtualToPhysicalAddress(const VAddr addr) {
  31. // Our memory interface read/write functions assume virtual addresses. Put any physical address
  32. // to virtual address translations here. This is quite hacky, but necessary until we implement
  33. // proper MMU emulation.
  34. // TODO: Screw it, I'll let bunnei figure out how to do this properly.
  35. if (addr == 0) {
  36. return 0;
  37. } else if ((addr >= VRAM_VADDR) && (addr < VRAM_VADDR_END)) {
  38. return addr - VRAM_VADDR + VRAM_PADDR;
  39. } else if ((addr >= HEAP_LINEAR_VADDR) && (addr < HEAP_LINEAR_VADDR_END)) {
  40. return addr - HEAP_LINEAR_VADDR + FCRAM_PADDR;
  41. }
  42. LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr);
  43. return addr;
  44. }
  45. template <typename T>
  46. inline void Read(T &var, const VAddr vaddr) {
  47. // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
  48. // TODO: Make sure this represents the mirrors in a correct way.
  49. // Could just do a base-relative read, too.... TODO
  50. // Kernel memory command buffer
  51. if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
  52. var = *((const T*)&g_kernel_mem[vaddr - KERNEL_MEMORY_VADDR]);
  53. // ExeFS:/.code is loaded here
  54. } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
  55. var = *((const T*)&g_exefs_code[vaddr - EXEFS_CODE_VADDR]);
  56. // FCRAM - linear heap
  57. } else if ((vaddr >= HEAP_LINEAR_VADDR) && (vaddr < HEAP_LINEAR_VADDR_END)) {
  58. var = *((const T*)&g_heap_linear[vaddr - HEAP_LINEAR_VADDR]);
  59. // FCRAM - application heap
  60. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  61. var = *((const T*)&g_heap[vaddr - HEAP_VADDR]);
  62. // Shared memory
  63. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  64. var = *((const T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR]);
  65. // System memory
  66. } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
  67. var = *((const T*)&g_system_mem[vaddr - SYSTEM_MEMORY_VADDR]);
  68. // Config memory
  69. } else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) {
  70. ConfigMem::Read<T>(var, vaddr);
  71. // Shared page
  72. } else if ((vaddr >= SHARED_PAGE_VADDR) && (vaddr < SHARED_PAGE_VADDR_END)) {
  73. SharedPage::Read<T>(var, vaddr);
  74. // DSP memory
  75. } else if ((vaddr >= DSP_MEMORY_VADDR) && (vaddr < DSP_MEMORY_VADDR_END)) {
  76. var = *((const T*)&g_dsp_mem[vaddr - DSP_MEMORY_VADDR]);
  77. // VRAM
  78. } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  79. var = *((const T*)&g_vram[vaddr - VRAM_VADDR]);
  80. } else {
  81. LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr);
  82. }
  83. }
  84. template <typename T>
  85. inline void Write(const VAddr vaddr, const T data) {
  86. // Kernel memory command buffer
  87. if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
  88. *(T*)&g_kernel_mem[vaddr - KERNEL_MEMORY_VADDR] = data;
  89. // ExeFS:/.code is loaded here
  90. } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
  91. *(T*)&g_exefs_code[vaddr - EXEFS_CODE_VADDR] = data;
  92. // FCRAM - linear heap
  93. } else if ((vaddr >= HEAP_LINEAR_VADDR) && (vaddr < HEAP_LINEAR_VADDR_END)) {
  94. *(T*)&g_heap_linear[vaddr - HEAP_LINEAR_VADDR] = data;
  95. // FCRAM - application heap
  96. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  97. *(T*)&g_heap[vaddr - HEAP_VADDR] = data;
  98. // Shared memory
  99. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  100. *(T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR] = data;
  101. // System memory
  102. } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
  103. *(T*)&g_system_mem[vaddr - SYSTEM_MEMORY_VADDR] = data;
  104. // VRAM
  105. } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  106. *(T*)&g_vram[vaddr - VRAM_VADDR] = data;
  107. // DSP memory
  108. } else if ((vaddr >= DSP_MEMORY_VADDR) && (vaddr < DSP_MEMORY_VADDR_END)) {
  109. *(T*)&g_dsp_mem[vaddr - DSP_MEMORY_VADDR] = data;
  110. //} else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
  111. // ASSERT_MSG(MEMMAP, false, "umimplemented write to Configuration Memory");
  112. //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
  113. // ASSERT_MSG(MEMMAP, false, "umimplemented write to shared page");
  114. // Error out...
  115. } else {
  116. LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr);
  117. }
  118. }
  119. u8 *GetPointer(const VAddr vaddr) {
  120. // Kernel memory command buffer
  121. if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
  122. return g_kernel_mem + (vaddr - KERNEL_MEMORY_VADDR);
  123. // ExeFS:/.code is loaded here
  124. } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
  125. return g_exefs_code + (vaddr - EXEFS_CODE_VADDR);
  126. // FCRAM - linear heap
  127. } else if ((vaddr >= HEAP_LINEAR_VADDR) && (vaddr < HEAP_LINEAR_VADDR_END)) {
  128. return g_heap_linear + (vaddr - HEAP_LINEAR_VADDR);
  129. // FCRAM - application heap
  130. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  131. return g_heap + (vaddr - HEAP_VADDR);
  132. // Shared memory
  133. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  134. return g_shared_mem + (vaddr - SHARED_MEMORY_VADDR);
  135. // System memory
  136. } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
  137. return g_system_mem + (vaddr - SYSTEM_MEMORY_VADDR);
  138. // VRAM
  139. } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  140. return g_vram + (vaddr - VRAM_VADDR);
  141. } else {
  142. LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr);
  143. return 0;
  144. }
  145. }
  146. u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
  147. MemoryBlock block;
  148. block.base_address = HEAP_VADDR;
  149. block.size = size;
  150. block.operation = operation;
  151. block.permissions = permissions;
  152. if (heap_map.size() > 0) {
  153. const MemoryBlock last_block = heap_map.rbegin()->second;
  154. block.address = last_block.address + last_block.size;
  155. }
  156. heap_map[block.GetVirtualAddress()] = block;
  157. return block.GetVirtualAddress();
  158. }
  159. u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) {
  160. MemoryBlock block;
  161. block.base_address = HEAP_LINEAR_VADDR;
  162. block.size = size;
  163. block.operation = operation;
  164. block.permissions = permissions;
  165. if (heap_linear_map.size() > 0) {
  166. const MemoryBlock last_block = heap_linear_map.rbegin()->second;
  167. block.address = last_block.address + last_block.size;
  168. }
  169. heap_linear_map[block.GetVirtualAddress()] = block;
  170. return block.GetVirtualAddress();
  171. }
  172. void MemBlock_Init() {
  173. }
  174. void MemBlock_Shutdown() {
  175. heap_map.clear();
  176. heap_linear_map.clear();
  177. }
  178. u8 Read8(const VAddr addr) {
  179. u8 data = 0;
  180. Read<u8>(data, addr);
  181. return data;
  182. }
  183. u16 Read16(const VAddr addr) {
  184. u16_le data = 0;
  185. Read<u16_le>(data, addr);
  186. return (u16)data;
  187. }
  188. u32 Read32(const VAddr addr) {
  189. u32_le data = 0;
  190. Read<u32_le>(data, addr);
  191. return (u32)data;
  192. }
  193. u64 Read64(const VAddr addr) {
  194. u64_le data = 0;
  195. Read<u64_le>(data, addr);
  196. return (u64)data;
  197. }
  198. u32 Read8_ZX(const VAddr addr) {
  199. return (u32)Read8(addr);
  200. }
  201. u32 Read16_ZX(const VAddr addr) {
  202. return (u32)Read16(addr);
  203. }
  204. void Write8(const VAddr addr, const u8 data) {
  205. Write<u8>(addr, data);
  206. }
  207. void Write16(const VAddr addr, const u16 data) {
  208. Write<u16_le>(addr, data);
  209. }
  210. void Write32(const VAddr addr, const u32 data) {
  211. Write<u32_le>(addr, data);
  212. }
  213. void Write64(const VAddr addr, const u64 data) {
  214. Write<u64_le>(addr, data);
  215. }
  216. void WriteBlock(const VAddr addr, const u8* data, const size_t size) {
  217. u32 offset = 0;
  218. while (offset < (size & ~3)) {
  219. Write32(addr + offset, *(u32*)&data[offset]);
  220. offset += 4;
  221. }
  222. if (size & 2) {
  223. Write16(addr + offset, *(u16*)&data[offset]);
  224. offset += 2;
  225. }
  226. if (size & 1)
  227. Write8(addr + offset, data[offset]);
  228. }
  229. } // namespace