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