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