27e2940f7e9f8fdca72fa8c093634d58af96ad92
[picodrive.git] / pico / memory.h
1 // memory map related stuff
2
3 #include "pico_port.h"
4
5 #define M68K_MEM_SHIFT 16
6 // minimum size we can map
7 #define M68K_BANK_SIZE (1 << M68K_MEM_SHIFT)
8 #define M68K_BANK_MASK (M68K_BANK_SIZE - 1)
9
10 extern uptr m68k_read8_map  [0x1000000 >> M68K_MEM_SHIFT];
11 extern uptr m68k_read16_map [0x1000000 >> M68K_MEM_SHIFT];
12 extern uptr m68k_write8_map [0x1000000 >> M68K_MEM_SHIFT];
13 extern uptr m68k_write16_map[0x1000000 >> M68K_MEM_SHIFT];
14
15 extern uptr s68k_read8_map  [0x1000000 >> M68K_MEM_SHIFT];
16 extern uptr s68k_read16_map [0x1000000 >> M68K_MEM_SHIFT];
17 extern uptr s68k_write8_map [0x1000000 >> M68K_MEM_SHIFT];
18 extern uptr s68k_write16_map[0x1000000 >> M68K_MEM_SHIFT];
19
20 // top-level handlers that cores can use
21 // (or alternatively build them into themselves)
22 // XXX: unhandled: *16 and *32 might cross the bank boundaries
23 typedef u32  (cpu68k_read_f)(u32 a);
24 typedef void (cpu68k_write_f)(u32 a, u32 d);
25
26 extern u32 m68k_read8(u32 a);
27 extern u32 m68k_read16(u32 a);
28 extern u32 m68k_read32(u32 a);
29 extern void m68k_write8(u32 a, u8 d);
30 extern void m68k_write16(u32 a, u16 d);
31 extern void m68k_write32(u32 a, u32 d);
32
33 extern u32 s68k_read8(u32 a);
34 extern u32 s68k_read16(u32 a);
35 extern u32 s68k_read32(u32 a);
36 extern void s68k_write8(u32 a, u8 d);
37 extern void s68k_write16(u32 a, u16 d);
38 extern void s68k_write32(u32 a, u32 d);
39
40 // z80
41 #define Z80_MEM_SHIFT 10 // must be <=10 to allow 1KB pages for SMS Sega mapper
42 extern uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT];
43 extern uptr z80_write_map[0x10000 >> Z80_MEM_SHIFT];
44 typedef unsigned char (z80_read_f)(unsigned short a);
45 typedef void (z80_write_f)(unsigned int a, unsigned char data);
46
47 void z80_map_set(uptr *map, u16 start_addr, u16 end_addr,
48     const void *func_or_mh, int is_func);
49 void cpu68k_map_set(uptr *map, u32 start_addr, u32 end_addr,
50     const void *func_or_mh, int is_func);
51 void cpu68k_map_read_mem(u32 start_addr, u32 end_addr, void *ptr, int is_sub);
52 void cpu68k_map_all_ram(u32 start_addr, u32 end_addr, void *ptr, int is_sub);
53 void cpu68k_map_read_funcs(u32 start_addr, u32 end_addr, u32 (*r8)(u32), u32 (*r16)(u32), int is_sub);
54 void cpu68k_map_all_funcs(u32 start_addr, u32 end_addr, u32 (*r8)(u32), u32 (*r16)(u32), void (*w8)(u32, u32), void (*w16)(u32, u32), int is_sub);
55 void m68k_map_unmap(u32 start_addr, u32 end_addr);
56
57 #define MAP_FLAG ((uptr)1 << (sizeof(uptr) * 8 - 1))
58 #define map_flag_set(x) ((x) & MAP_FLAG)
59
60 #define MAKE_68K_READ8(name, map)               \
61 u32 name(u32 a)                                 \
62 {                                               \
63   uptr v;                                       \
64   a &= 0x00ffffff;                              \
65   v = map[a >> M68K_MEM_SHIFT];                 \
66   if (map_flag_set(v))                          \
67     return ((cpu68k_read_f *)(v << 1))(a);      \
68   else                                          \
69     return *(u8 *)((v << 1) + MEM_BE2(a));      \
70 }
71
72 #define MAKE_68K_READ16(name, map)              \
73 u32 name(u32 a)                                 \
74 {                                               \
75   uptr v;                                       \
76   a &= 0x00fffffe;                              \
77   v = map[a >> M68K_MEM_SHIFT];                 \
78   if (map_flag_set(v))                          \
79     return ((cpu68k_read_f *)(v << 1))(a);      \
80   else                                          \
81     return *(u16 *)((v << 1) + a);              \
82 }
83
84 #define MAKE_68K_READ32(name, map)              \
85 u32 name(u32 a)                                 \
86 {                                               \
87   uptr v, vs;                                   \
88   u32 d;                                        \
89   a &= 0x00fffffe;                              \
90   v = map[a >> M68K_MEM_SHIFT];                 \
91   vs = v << 1;                                  \
92   if (map_flag_set(v)) {                        \
93     d  = ((cpu68k_read_f *)vs)(a) << 16;        \
94     d |= ((cpu68k_read_f *)vs)(a + 2);          \
95   }                                             \
96   else {                                        \
97     u16 *m = (u16 *)(vs + a);                   \
98     d = (m[0] << 16) | m[1];                    \
99   }                                             \
100   return d;                                     \
101 }
102
103 #define MAKE_68K_WRITE8(name, map)              \
104 void name(u32 a, u8 d)                          \
105 {                                               \
106   uptr v;                                       \
107   a &= 0x00ffffff;                              \
108   v = map[a >> M68K_MEM_SHIFT];                 \
109   if (map_flag_set(v))                          \
110     ((cpu68k_write_f *)(v << 1))(a, d);         \
111   else                                          \
112     *(u8 *)((v << 1) + MEM_BE2(a)) = d;         \
113 }
114
115 #define MAKE_68K_WRITE16(name, map)             \
116 void name(u32 a, u16 d)                         \
117 {                                               \
118   uptr v;                                       \
119   a &= 0x00fffffe;                              \
120   v = map[a >> M68K_MEM_SHIFT];                 \
121   if (map_flag_set(v))                          \
122     ((cpu68k_write_f *)(v << 1))(a, d);         \
123   else                                          \
124     *(u16 *)((v << 1) + a) = d;                 \
125 }
126
127 #define MAKE_68K_WRITE32(name, map)             \
128 void name(u32 a, u32 d)                         \
129 {                                               \
130   uptr v, vs;                                   \
131   a &= 0x00fffffe;                              \
132   v = map[a >> M68K_MEM_SHIFT];                 \
133   vs = v << 1;                                  \
134   if (map_flag_set(v)) {                        \
135     ((cpu68k_write_f *)vs)(a, d >> 16);         \
136     ((cpu68k_write_f *)vs)(a + 2, d);           \
137   }                                             \
138   else {                                        \
139     u16 *m = (u16 *)(vs + a);                   \
140     m[0] = d >> 16;                             \
141     m[1] = d;                                   \
142   }                                             \
143 }
144
145 #ifdef NEED_DMA_SOURCE // meh
146
147 static __inline void *m68k_dma_source(u32 a)
148 {
149   u8 *base;
150   uptr v;
151   v = m68k_read16_map[a >> M68K_MEM_SHIFT];
152   if (map_flag_set(v)) {
153     if (a >= Pico.romsize) // Rom
154       return NULL;
155     base = Pico.rom;
156   }
157   else
158     base = (void *)(v << 1);
159   return base + (a & 0xfe0000);
160 }
161
162 #endif
163
164 // 32x
165 typedef struct {
166   uptr addr; // stores (membase >> 1) or ((handler >> 1) | (1<<31))
167   u32 mask;
168 } sh2_memmap;