src/memory.h

Tue, 21 May 2013 22:48:32 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 21 May 2013 22:48:32 +0100
branch
experimental_memory_mapper_v2
changeset 145
2d6de28c6e6c
parent 128
3246b74d96bc
permissions
-rw-r--r--

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