mem_map_funcs.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2
  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/hle.h"
  9. #include "hle/config_mem.h"
  10. namespace Memory {
  11. std::map<u32, MemoryBlock> g_heap_map;
  12. std::map<u32, MemoryBlock> g_heap_gsp_map;
  13. std::map<u32, MemoryBlock> g_shared_map;
  14. /// Convert a physical address (or firmware-specific virtual address) to primary virtual address
  15. u32 _VirtualAddress(const u32 addr) {
  16. // Our memory interface read/write functions assume virtual addresses. Put any physical address
  17. // to virtual address translations here. This is obviously quite hacky... But we're not doing
  18. // any MMU emulation yet or anything
  19. if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) {
  20. return VirtualAddressFromPhysical_FCRAM(addr);
  21. // Virtual address mapping FW0B
  22. } else if ((addr >= FCRAM_VADDR_FW0B) && (addr < FCRAM_VADDR_FW0B_END)) {
  23. return VirtualAddressFromPhysical_FCRAM(addr);
  24. // Hardware IO
  25. // TODO(bunnei): FixMe
  26. // This isn't going to work... The physical address of HARDWARE_IO conflicts with the virtual
  27. // address of shared memory.
  28. //} else if ((addr >= HARDWARE_IO_PADDR) && (addr < HARDWARE_IO_PADDR_END)) {
  29. // return (addr + 0x0EB00000);
  30. }
  31. return addr;
  32. }
  33. template <typename T>
  34. inline void _Read(T &var, const u32 addr) {
  35. // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
  36. // TODO: Make sure this represents the mirrors in a correct way.
  37. // Could just do a base-relative read, too.... TODO
  38. const u32 vaddr = _VirtualAddress(addr);
  39. // Kernel memory command buffer
  40. if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
  41. var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]);
  42. // Hardware I/O register reads
  43. // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
  44. } else if ((vaddr >= HARDWARE_IO_VADDR) && (vaddr < HARDWARE_IO_VADDR_END)) {
  45. HW::Read<T>(var, vaddr);
  46. // ExeFS:/.code is loaded here
  47. } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
  48. var = *((const T*)&g_exefs_code[vaddr & EXEFS_CODE_MASK]);
  49. // FCRAM - GSP heap
  50. } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
  51. var = *((const T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK]);
  52. // FCRAM - application heap
  53. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  54. var = *((const T*)&g_heap[vaddr & HEAP_MASK]);
  55. // Shared memory
  56. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  57. var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
  58. // System memory
  59. } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
  60. var = *((const T*)&g_system_mem[vaddr & SYSTEM_MEMORY_MASK]);
  61. // Config memory
  62. } else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) {
  63. ConfigMem::Read<T>(var, vaddr);
  64. // VRAM
  65. } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  66. var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
  67. } else {
  68. //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
  69. }
  70. }
  71. template <typename T>
  72. inline void _Write(u32 addr, const T data) {
  73. u32 vaddr = _VirtualAddress(addr);
  74. // Kernel memory command buffer
  75. if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
  76. *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data;
  77. // Hardware I/O register writes
  78. // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
  79. } else if ((vaddr >= HARDWARE_IO_VADDR) && (vaddr < HARDWARE_IO_VADDR_END)) {
  80. HW::Write<T>(vaddr, data);
  81. // ExeFS:/.code is loaded here
  82. } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
  83. *(T*)&g_exefs_code[vaddr & EXEFS_CODE_MASK] = data;
  84. // FCRAM - GSP heap
  85. } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
  86. *(T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK] = data;
  87. // FCRAM - application heap
  88. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  89. *(T*)&g_heap[vaddr & HEAP_MASK] = data;
  90. // Shared memory
  91. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  92. *(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data;
  93. // System memory
  94. } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
  95. *(T*)&g_system_mem[vaddr & SYSTEM_MEMORY_MASK] = data;
  96. // VRAM
  97. } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  98. *(T*)&g_vram[vaddr & VRAM_MASK] = data;
  99. //} else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
  100. // _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
  101. //} else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
  102. // _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory");
  103. //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
  104. // _assert_msg_(MEMMAP, false, "umimplemented write to shared page");
  105. // Error out...
  106. } else {
  107. _assert_msg_(MEMMAP, false, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8,
  108. data, vaddr);
  109. }
  110. }
  111. u8 *GetPointer(const u32 addr) {
  112. const u32 vaddr = _VirtualAddress(addr);
  113. // Kernel memory command buffer
  114. if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
  115. return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK);
  116. // ExeFS:/.code is loaded here
  117. } else if ((vaddr >= EXEFS_CODE_VADDR) && (vaddr < EXEFS_CODE_VADDR_END)) {
  118. return g_exefs_code + (vaddr & EXEFS_CODE_MASK);
  119. // FCRAM - GSP heap
  120. } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
  121. return g_heap_gsp + (vaddr & HEAP_GSP_MASK);
  122. // FCRAM - application heap
  123. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  124. return g_heap + (vaddr & HEAP_MASK);
  125. // Shared memory
  126. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  127. return g_shared_mem + (vaddr & SHARED_MEMORY_MASK);
  128. // System memory
  129. } else if ((vaddr >= SYSTEM_MEMORY_VADDR) && (vaddr < SYSTEM_MEMORY_VADDR_END)) {
  130. return g_system_mem + (vaddr & SYSTEM_MEMORY_MASK);
  131. // VRAM
  132. } else if ((vaddr > VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  133. return g_vram + (vaddr & VRAM_MASK);
  134. } else {
  135. ERROR_LOG(MEMMAP, "unknown GetPointer @ 0x%08x", vaddr);
  136. return 0;
  137. }
  138. }
  139. /**
  140. * Maps a block of memory in shared memory
  141. * @param handle Handle to map memory block for
  142. * @param addr Address to map memory block to
  143. * @param permissions Memory map permissions
  144. */
  145. u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) {
  146. MemoryBlock block;
  147. block.handle = handle;
  148. block.base_address = addr;
  149. block.permissions = permissions;
  150. if (g_shared_map.size() > 0) {
  151. const MemoryBlock last_block = g_shared_map.rbegin()->second;
  152. block.address = last_block.address + last_block.size;
  153. }
  154. g_shared_map[block.GetVirtualAddress()] = block;
  155. return block.GetVirtualAddress();
  156. }
  157. /**
  158. * Maps a block of memory on the heap
  159. * @param size Size of block in bytes
  160. * @param operation Memory map operation type
  161. * @param flags Memory allocation flags
  162. */
  163. u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
  164. MemoryBlock block;
  165. block.base_address = HEAP_VADDR;
  166. block.size = size;
  167. block.operation = operation;
  168. block.permissions = permissions;
  169. if (g_heap_map.size() > 0) {
  170. const MemoryBlock last_block = g_heap_map.rbegin()->second;
  171. block.address = last_block.address + last_block.size;
  172. }
  173. g_heap_map[block.GetVirtualAddress()] = block;
  174. return block.GetVirtualAddress();
  175. }
  176. /**
  177. * Maps a block of memory on the GSP heap
  178. * @param size Size of block in bytes
  179. * @param operation Memory map operation type
  180. * @param flags Memory allocation flags
  181. */
  182. u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
  183. MemoryBlock block;
  184. block.base_address = HEAP_GSP_VADDR;
  185. block.size = size;
  186. block.operation = operation;
  187. block.permissions = permissions;
  188. if (g_heap_gsp_map.size() > 0) {
  189. const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second;
  190. block.address = last_block.address + last_block.size;
  191. }
  192. g_heap_gsp_map[block.GetVirtualAddress()] = block;
  193. return block.GetVirtualAddress();
  194. }
  195. u8 Read8(const u32 addr) {
  196. u8 _var = 0;
  197. _Read<u8>(_var, addr);
  198. return (u8)_var;
  199. }
  200. u16 Read16(const u32 addr) {
  201. u16_le _var = 0;
  202. _Read<u16_le>(_var, addr);
  203. return (u16)_var;
  204. }
  205. u32 Read32(const u32 addr) {
  206. u32_le _var = 0;
  207. _Read<u32_le>(_var, addr);
  208. return _var;
  209. }
  210. u64 Read64(const u32 addr) {
  211. u64_le _var = 0;
  212. _Read<u64_le>(_var, addr);
  213. return _var;
  214. }
  215. u32 Read8_ZX(const u32 addr) {
  216. return (u32)Read8(addr);
  217. }
  218. u32 Read16_ZX(const u32 addr) {
  219. return (u32)Read16(addr);
  220. }
  221. void Write8(const u32 addr, const u8 data) {
  222. _Write<u8>(addr, data);
  223. }
  224. void Write16(const u32 addr, const u16 data) {
  225. _Write<u16_le>(addr, data);
  226. }
  227. void Write32(const u32 addr, const u32 data) {
  228. _Write<u32_le>(addr, data);
  229. }
  230. void Write64(const u32 addr, const u64 data) {
  231. _Write<u64_le>(addr, data);
  232. }
  233. } // namespace