Tue, 21 May 2013 22:48:32 +0100
Code clean up
* Tighten optimisation and warning options to find more potential issues
* Remove unused variable in keyboard code
* Display error message if ROMs fail to load
* Fix format string bugs in WD2010
philpem@40 | 1 | #ifndef _MEMORY_H |
philpem@40 | 2 | #define _MEMORY_H |
philpem@40 | 3 | |
philpem@40 | 4 | /*********************************** |
philpem@40 | 5 | * Array read/write utility macros |
philpem@40 | 6 | * "Don't Repeat Yourself" :) |
philpem@40 | 7 | ***********************************/ |
philpem@40 | 8 | |
philpem@40 | 9 | /// Array read, 32-bit |
philpem@40 | 10 | #define RD32(array, address, andmask) \ |
philpem@40 | 11 | (((uint32_t)array[(address + 0) & (andmask)] << 24) | \ |
philpem@40 | 12 | ((uint32_t)array[(address + 1) & (andmask)] << 16) | \ |
philpem@40 | 13 | ((uint32_t)array[(address + 2) & (andmask)] << 8) | \ |
philpem@40 | 14 | ((uint32_t)array[(address + 3) & (andmask)])) |
philpem@40 | 15 | |
philpem@40 | 16 | /// Array read, 16-bit |
philpem@40 | 17 | #define RD16(array, address, andmask) \ |
philpem@40 | 18 | (((uint32_t)array[(address + 0) & (andmask)] << 8) | \ |
philpem@40 | 19 | ((uint32_t)array[(address + 1) & (andmask)])) |
philpem@40 | 20 | |
philpem@40 | 21 | /// Array read, 8-bit |
philpem@40 | 22 | #define RD8(array, address, andmask) \ |
philpem@40 | 23 | ((uint32_t)array[(address + 0) & (andmask)]) |
philpem@40 | 24 | |
philpem@40 | 25 | /// Array write, 32-bit |
philpem@70 | 26 | #define WR32(array, address, andmask, value) do { \ |
philpem@40 | 27 | array[(address + 0) & (andmask)] = (value >> 24) & 0xff; \ |
philpem@40 | 28 | array[(address + 1) & (andmask)] = (value >> 16) & 0xff; \ |
philpem@40 | 29 | array[(address + 2) & (andmask)] = (value >> 8) & 0xff; \ |
philpem@40 | 30 | array[(address + 3) & (andmask)] = value & 0xff; \ |
philpem@70 | 31 | } while (0) |
philpem@40 | 32 | |
philpem@40 | 33 | /// Array write, 16-bit |
philpem@70 | 34 | #define WR16(array, address, andmask, value) do { \ |
philpem@40 | 35 | array[(address + 0) & (andmask)] = (value >> 8) & 0xff; \ |
philpem@40 | 36 | array[(address + 1) & (andmask)] = value & 0xff; \ |
philpem@70 | 37 | } while (0) |
philpem@40 | 38 | |
philpem@40 | 39 | /// Array write, 8-bit |
philpem@70 | 40 | #define WR8(array, address, andmask, value) do { \ |
philpem@70 | 41 | array[(address + 0) & (andmask)] = value & 0xff; \ |
philpem@70 | 42 | } while (0) |
philpem@40 | 43 | |
philpem@40 | 44 | /****************** |
philpem@40 | 45 | * Memory mapping |
philpem@40 | 46 | ******************/ |
philpem@40 | 47 | |
philpem@128 | 48 | /*** |
philpem@128 | 49 | * An entry in MAP RAM looks like this: |
philpem@128 | 50 | * |
philpem@128 | 51 | * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
philpem@128 | 52 | * +-----------------------------------------------+ |
philpem@128 | 53 | * | | | | | | | MA[21..12] ADDRESS BITS | |
philpem@128 | 54 | * +-----------------------------------------------+ |
philpem@128 | 55 | * |
philpem@128 | 56 | * Bits 0 thru 9: High 10 address bits (mapping) |
philpem@128 | 57 | * Bits 10 thru 15: Page bits |
philpem@128 | 58 | * B10: PS4 |
philpem@128 | 59 | * B11: PS3 |
philpem@128 | 60 | * B12: PS2 |
philpem@128 | 61 | * B13: PS0 |
philpem@128 | 62 | * B14: PS1 |
philpem@128 | 63 | * B15: WE+ |
philpem@128 | 64 | * |
philpem@128 | 65 | * Page bit meanings: |
philpem@128 | 66 | * PS4, 3 and 2 are unused. |
philpem@128 | 67 | * PS1:PS0: |
philpem@128 | 68 | * PS1 PS0 Meaning |
philpem@128 | 69 | * --- --- ------- |
philpem@128 | 70 | * 0 0 Page not present |
philpem@128 | 71 | * 0 1 Page present but has not been accessed |
philpem@128 | 72 | * 1 0 Page has been accessed but not written |
philpem@128 | 73 | * 1 1 Page has been accessed and written to (is dirty) |
philpem@128 | 74 | * |
philpem@128 | 75 | * WE+: Write Enable. Set to 1 if the page is writable. |
philpem@128 | 76 | * |
philpem@128 | 77 | * Each RAM page is 4096 bytes. |
philpem@128 | 78 | */ |
philpem@40 | 79 | |
philpem@128 | 80 | /// Known page bits and their values |
philpem@128 | 81 | enum { |
philpem@128 | 82 | PAGE_BIT_PS0 = 0x08, ///< PS0 page status bit |
philpem@128 | 83 | PAGE_BIT_PS1 = 0x10, ///< PS1 (page accessed) page bit |
philpem@128 | 84 | PAGE_BIT_WE = 0x20 ///< WE (write enable) page bit |
philpem@128 | 85 | }; |
philpem@128 | 86 | |
philpem@128 | 87 | /// Get the Map RAM entry for the specified page |
philpem@128 | 88 | #define MAPRAM(page) (((uint16_t)state.map[page*2] << 8) + ((uint16_t)state.map[(page*2)+1])) |
philpem@128 | 89 | /// Get the page number for a given address |
philpem@128 | 90 | #define MAP_ADDR_TO_PAGE(addr) (((addr) >> 12) & 0x3FF) |
philpem@128 | 91 | /// Get the Map RAM entry for the specified virtual address |
philpem@128 | 92 | #define MAPRAM_ADDR(addr) (MAPRAM(MAP_ADDR_TO_PAGE(addr))) |
philpem@128 | 93 | /// Map an address from CPU address space to physical memory |
philpem@128 | 94 | #define MAP_ADDR(addr) (((MAPRAM_ADDR(addr) & 0x3FF) << 12) | (addr & 0xFFF)) |
philpem@128 | 95 | /// Get the page bits associated with the mapping for a given physical memory address |
philpem@128 | 96 | #define MAP_PAGEBITS(addr) ((MAPRAM_ADDR(addr) >> 10) & 0x3F) |
philpem@128 | 97 | |
philpem@128 | 98 | #if 0 |
philpem@40 | 99 | /** |
philpem@40 | 100 | * @brief Check memory access permissions for a given address. |
philpem@40 | 101 | * @param addr Address. |
philpem@40 | 102 | * @param writing true if writing to memory, false if reading. |
philpem@40 | 103 | * @return One of the MEM_STATUS constants, specifying whether the access is |
philpem@40 | 104 | * permitted, or what error occurred. |
philpem@40 | 105 | */ |
philpem@40 | 106 | MEM_STATUS checkMemoryAccess(uint32_t addr, bool writing); |
philpem@40 | 107 | |
philpem@40 | 108 | /** |
philpem@112 | 109 | * @brief Check access flags for a DMA transfer and trigger an exception if |
philpem@112 | 110 | * the access is not permitted |
philpem@112 | 111 | * @param reading true if reading from memory, false if writing |
philpem@112 | 112 | */ |
philpem@112 | 113 | bool access_check_dma(int reading); |
philpem@128 | 114 | #endif |
philpem@128 | 115 | |
philpem@128 | 116 | |
philpem@128 | 117 | /** |
philpem@128 | 118 | * Check memory access permissions for a DMA operation. |
philpem@128 | 119 | * @return true if the access is permitted, false if not |
philpem@128 | 120 | */ |
philpem@128 | 121 | bool access_check_dma(void); |
philpem@112 | 122 | |
philpem@40 | 123 | #endif |