mem_map_funcs.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. namespace Memory {
  10. std::map<u32, MemoryBlock> g_heap_map;
  11. std::map<u32, MemoryBlock> g_heap_gsp_map;
  12. std::map<u32, MemoryBlock> g_shared_map;
  13. /// Convert a physical address (or firmware-specific virtual address) to primary virtual address
  14. u32 _VirtualAddress(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 >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) {
  19. return VirtualAddressFromPhysical_FCRAM(addr);
  20. // Virtual address mapping FW0B
  21. } else if ((addr >= FRAM_VADDR_FW0B) && (addr < FRAM_VADDR_FW0B_END)) {
  22. return VirtualAddressFromPhysical_FCRAM(addr);
  23. // Hardware IO
  24. // TODO(bunnei): FixMe
  25. // This isn't going to work... The physical address of HARDWARE_IO conflicts with the virtual
  26. // address of shared memory.
  27. //} else if ((addr >= HARDWARE_IO_PADDR) && (addr < HARDWARE_IO_PADDR_END)) {
  28. // return (addr + 0x0EB00000);
  29. }
  30. return addr;
  31. }
  32. template <typename T>
  33. inline void _Read(T &var, const u32 addr) {
  34. // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
  35. // TODO: Make sure this represents the mirrors in a correct way.
  36. // Could just do a base-relative read, too.... TODO
  37. const u32 vaddr = _VirtualAddress(addr);
  38. // Memory allocated for HLE use that can be addressed from the emulated application
  39. // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
  40. // core running the user application (appcore)
  41. if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) {
  42. HLE::Read<T>(var, vaddr);
  43. // Hardware I/O register reads
  44. // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
  45. } else if ((vaddr >= HARDWARE_IO_VADDR) && (vaddr < HARDWARE_IO_VADDR_END)) {
  46. HW::Read<T>(var, vaddr);
  47. // FCRAM - GSP heap
  48. } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
  49. var = *((const T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK]);
  50. // FCRAM - application heap
  51. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  52. var = *((const T*)&g_heap[vaddr & HEAP_MASK]);
  53. // Shared memory
  54. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  55. var = *((const T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK]);
  56. // VRAM
  57. } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  58. var = *((const T*)&g_vram[vaddr & VRAM_MASK]);
  59. } else {
  60. //_assert_msg_(MEMMAP, false, "unknown Read%d @ 0x%08X", sizeof(var) * 8, vaddr);
  61. }
  62. }
  63. template <typename T>
  64. inline void _Write(u32 addr, const T data) {
  65. u32 vaddr = _VirtualAddress(addr);
  66. // Memory allocated for HLE use that can be addressed from the emulated application
  67. // The primary use of this is sharing a commandbuffer between the HLE OS (syscore) and the LLE
  68. // core running the user application (appcore)
  69. if (vaddr >= HLE::CMD_BUFFER_ADDR && vaddr < HLE::CMD_BUFFER_ADDR_END) {
  70. HLE::Write<T>(vaddr, data);
  71. // Hardware I/O register writes
  72. // 0x10XXXXXX- is physical address space, 0x1EXXXXXX is virtual address space
  73. } else if ((vaddr >= HARDWARE_IO_VADDR) && (vaddr < HARDWARE_IO_VADDR_END)) {
  74. HW::Write<T>(vaddr, data);
  75. // FCRAM - GSP heap
  76. } else if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
  77. *(T*)&g_heap_gsp[vaddr & HEAP_GSP_MASK] = data;
  78. // FCRAM - application heap
  79. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  80. *(T*)&g_heap[vaddr & HEAP_MASK] = data;
  81. // Shared memory
  82. } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  83. *(T*)&g_shared_mem[vaddr & SHARED_MEMORY_MASK] = data;
  84. // VRAM
  85. } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  86. *(T*)&g_vram[vaddr & VRAM_MASK] = data;
  87. } else if ((vaddr & 0xFFF00000) == 0x1FF00000) {
  88. _assert_msg_(MEMMAP, false, "umimplemented write to DSP memory");
  89. } else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
  90. _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory");
  91. } else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
  92. _assert_msg_(MEMMAP, false, "umimplemented write to shared page");
  93. // Error out...
  94. } else {
  95. _assert_msg_(MEMMAP, false, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8,
  96. data, vaddr);
  97. }
  98. }
  99. u8 *GetPointer(const u32 addr) {
  100. const u32 vaddr = _VirtualAddress(addr);
  101. // FCRAM - GSP heap
  102. if ((vaddr >= HEAP_GSP_VADDR) && (vaddr < HEAP_GSP_VADDR_END)) {
  103. return g_heap_gsp + (vaddr & HEAP_GSP_MASK);
  104. // FCRAM - application heap
  105. } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
  106. return g_heap + (vaddr & HEAP_MASK);
  107. // Shared memory
  108. } else if ((vaddr > SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
  109. return g_shared_mem + (vaddr & SHARED_MEMORY_MASK);
  110. // VRAM
  111. } else if ((vaddr > VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
  112. return g_vram + (vaddr & VRAM_MASK);
  113. } else {
  114. ERROR_LOG(MEMMAP, "unknown GetPointer @ 0x%08x", vaddr);
  115. return 0;
  116. }
  117. }
  118. /**
  119. * Maps a block of memory in shared memory
  120. * @param handle Handle to map memory block for
  121. * @param addr Address to map memory block to
  122. * @param permissions Memory map permissions
  123. */
  124. u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) {
  125. MemoryBlock block;
  126. block.handle = handle;
  127. block.base_address = addr;
  128. block.permissions = permissions;
  129. if (g_shared_map.size() > 0) {
  130. const MemoryBlock last_block = g_shared_map.rbegin()->second;
  131. block.address = last_block.address + last_block.size;
  132. }
  133. g_shared_map[block.GetVirtualAddress()] = block;
  134. return block.GetVirtualAddress();
  135. }
  136. /**
  137. * Maps a block of memory on the heap
  138. * @param size Size of block in bytes
  139. * @param operation Memory map operation type
  140. * @param flags Memory allocation flags
  141. */
  142. u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
  143. MemoryBlock block;
  144. block.base_address = HEAP_VADDR;
  145. block.size = size;
  146. block.operation = operation;
  147. block.permissions = permissions;
  148. if (g_heap_map.size() > 0) {
  149. const MemoryBlock last_block = g_heap_map.rbegin()->second;
  150. block.address = last_block.address + last_block.size;
  151. }
  152. g_heap_map[block.GetVirtualAddress()] = block;
  153. return block.GetVirtualAddress();
  154. }
  155. /**
  156. * Maps a block of memory on the GSP heap
  157. * @param size Size of block in bytes
  158. * @param operation Memory map operation type
  159. * @param flags Memory allocation flags
  160. */
  161. u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
  162. MemoryBlock block;
  163. block.base_address = HEAP_GSP_VADDR;
  164. block.size = size;
  165. block.operation = operation;
  166. block.permissions = permissions;
  167. if (g_heap_gsp_map.size() > 0) {
  168. const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second;
  169. block.address = last_block.address + last_block.size;
  170. }
  171. g_heap_gsp_map[block.GetVirtualAddress()] = block;
  172. return block.GetVirtualAddress();
  173. }
  174. u8 Read8(const u32 addr) {
  175. u8 _var = 0;
  176. _Read<u8>(_var, addr);
  177. return (u8)_var;
  178. }
  179. u16 Read16(const u32 addr) {
  180. u16_le _var = 0;
  181. _Read<u16_le>(_var, addr);
  182. return (u16)_var;
  183. }
  184. u32 Read32(const u32 addr) {
  185. u32_le _var = 0;
  186. _Read<u32_le>(_var, addr);
  187. return _var;
  188. }
  189. u64 Read64(const u32 addr) {
  190. u64_le _var = 0;
  191. _Read<u64_le>(_var, addr);
  192. return _var;
  193. }
  194. u32 Read8_ZX(const u32 addr) {
  195. return (u32)Read8(addr);
  196. }
  197. u32 Read16_ZX(const u32 addr) {
  198. return (u32)Read16(addr);
  199. }
  200. void Write8(const u32 addr, const u8 data) {
  201. _Write<u8>(addr, data);
  202. }
  203. void Write16(const u32 addr, const u16 data) {
  204. _Write<u16_le>(addr, data);
  205. }
  206. void Write32(const u32 addr, const u32 data) {
  207. _Write<u32_le>(addr, data);
  208. }
  209. void Write64(const u32 addr, const u64 data) {
  210. _Write<u64_le>(addr, data);
  211. }
  212. } // namespace