1 //
2 // mmu.cpp
3 //
4 // Jaguar Memory Manager Unit
5 //
6 // by James Hammons
7 //
8 // JLH = James Hammons <jlhamm@acm.org>
9 //
10 // WHO WHEN WHAT
11 // --- ---------- -----------------------------------------------------------
12 // JLH 11/25/2009 Created this file. :-)
13 //
14
15 #include <stdlib.h> // For NULL definition
16
17 #include <boolean.h>
18
19 #include "mmu.h"
20
21 #include "jagbios.h"
22 #include "wavetable.h"
23
24 /*
25 Addresses to be handled:
26
27 SYSTEM SETUP REGISTERS
28
29 *MEMCON1 Memory Control Register 1 F00000 RW
30 *MEMCON2 Memory Control Register 2 F00002 RW
31 HC Horizontal Count F00004 RW
32 VC Vertical Count F00006 RW
33 LPH Light Pen Horizontal F00008 RO
34 LPV Light Pen Vertical F0000A RO
35 OB[0-3] Object Data Field F00010-16 RO
36 OLP Object List Pointer F00020-23 WO
37 OBF Object Flag F00026 WO
38 VMODE Video Mode F00028 WO
39 BORD1 Border Colour (Red & Green) F0002A WO
40 BORD2 Border Colour (Blue) F0002C WO
41 *HP Horizontal Period F0002E WO
42 *HBB Horizontal Blank Begin F00030 WO
43 *HBE Horizontal Blank End F00032 WO
44 *HS Horizontal Sync F00034 WO
45 *HVS Horizontal Vertical Sync F00036 WO
46 HDB1 Horizontal Display Begin 1 F00038 WO
47 HDB2 Horizontal Display Begin 2 F0003A WO
48 HDE Horizontal Display End F0003C WO
49 *VP Vertical Period F0003E WO
50 *VBB Vertical Blank Begin F00040 WO
51 *VBE Vertical Blank End F00042 WO
52 *VS Vertical Sync F00044 WO
53 VDB Vertical Display Begin F00046 WO
54 VDE Vertical Display End F00048 WO
55 *VEB Vertical Equalization Begin F0004A WO
56 *VEE Vertical Equalization End F0004C WO
57 VI Vertical Interrupt F0004E WO
58 PIT[0-1] Programmable Interrupt Timer F00050-52 WO
59 *HEQ Horizontal Equalization End F00054 WO
60 BG Background Colour F00058 WO
61 INT1 CPU Interrupt Control Register F000E0 RW
62 INT2 CPU Interrupt Resume Register F000E2 WO
63 CLUT Colour Look-Up Table F00400-7FE RW
64 LBUF Line Buffer F00800-1D9E RW
65
66 GPU REGISTERS
67
68 G_FLAGS GPU Flags Register F02100 RW
69 G_MTXC Matrix Control Register F02104 WO
70 G_MTXA Matrix Address Register F02108 WO
71 G_END Data Organization Register F0210C WO
72 G_PC GPU Program Counter F02110 RW
73 G_CTRL GPU Control/Status Register F02114 RW
74 G_HIDATA High Data Register F02118 RW
75 G_REMAIN Divide Unit Remainder F0211C RO
76 G_DIVCTRL Divide Unit Control F0211C WO
77
78 BLITTER REGISTERS
79
80 A1_BASE A1 Base Register F02200 WO
81 A1_FLAGS Flags Register F02204 WO
82 A1_CLIP A1 Clipping Size F02208 WO
83 A1_PIXEL A1 Pixel Pointer F0220C WO
84 F02204 RO
85 A1_STEP A1 Step Value F02210 WO
86 A1_FSTEP A1 Step Fraction Value F02214 WO
87 A1_FPIXEL A1 Pixel Pointer Fraction F02218 RW
88 A1_INC A1 Increment F0221C WO
89 A1_FINC A1 Increment Fraction F02220 WO
90 A2_BASE A2 Base Register F02224 WO
91 A2_FLAGS A2 Flags Register F02228 WO
92 A2_MASK A2 Window Mask F0222C WO
93 A2_PIXEL A2 Pixel Pointer F02230 WO
94 F0222C RO
95 A2_STEP A2 Step Value F02234 WO
96 B_CMD Command/Status Register F02238 RW
97 B_COUNT Counters Register F0223C WO
98 B_SRCD Source Data Register F02240 WO
99 B_DSTD Destination Data Register F02248 WO
100 B_DSTZ Destination Z Register F02250 WO
101 B_SRCZ1 Source Z Register 1 F02258 WO
102 B_SRCZ2 Source Z Register 2 F02260 WO
103 B_PATD Pattern Data Register F02268 WO
104 B_IINC Intensity Increment F02270 WO
105 B_ZINC Z Increment F02274 WO
106 B_STOP Collision Control F02278 WO
107 B_I3 Intensity 3 F0227C WO
108 B_I2 Intensity 2 F02280 WO
109 B_I1 Intensity 1 F02284 WO
110 B_I0 Intensity 0 F02288 WO
111 B_Z3 Z 3 F0228C WO
112 B_Z2 Z 2 F02290 WO
113 B_Z1 Z 1 F02294 WO
114 B_Z0 Z 0 F02298 WO
115
116 JERRY REGISTERS
117
118 *CLK1 Processor Clock Divider F10010 WO
119 *CLK2 Video Clock Divider F10012 WO
120 *CLK3 Chroma Clock Divider F10014 WO
121 JPIT1 Timer 1 Pre-scaler F10000 WO
122 JPIT3 Timer 2 Pre-scaler F10004 WO
123 JPIT2 Timer 1 Divider F10002 WO
124 JPIT4 Timer 2 Divider F10006 WO
125 J_INT Interrup Control Register F10020 RW
126 SCLK Serial Clock Frequency F1A150 WO
127 SMODE Serial Mode F1A154 WO
128 LTXD Left Transmit Data F1A148 WO
129 RTXD Right Transmit Data F1A14C WO
130 LRXD Left Receive Data F1A148 RO
131 RRXD Right Receive Data F1A14C RO
132 L_I2S Left I2S Serial Interface F1A148 RW
133 R_I2S Right I2S Serial Interface F1A14C RW
134 SSTAT Serial Status F1A150 RO
135 ASICLK Asynchronous Serial Interface Clock F10034 RW
136 ASICTRL Asynchronous Serial Control F10032 WO
137 ASISTAT Asynchronous Serial Status F10032 RO
138 ASIDATA Asynchronous Serial Data F10030 RW
139
140 JOYSTICK REGISTERS
141
142 JOYSTICK Joystick Register F14000 RW
143 JOYBUTS Button Register F14002 RW
144
145 DSP REGISTERS
146
147 D_FLAGS DSP Flags Register F1A100 RW
148 D_MTXC DSP Matrix Control Register F1A104 WO
149 D_MTXA DSP Matrix Address Register F1A108 WO
150 D_END DSP Data Organization Register F1A10C WO
151 D_PC DSP Program Counter F1A110 RW
152 D_CTRL DSP Control/Status Register F1A114 RW
153 D_MOD Modulo Instruction Mask F1A118 WO
154 D_REMAIN Divide Unit Remainder F1A11C RO
155 D_DIVCTRL Divide Unit Control F1A11C WO
156 D_MACHI MAC High Result Bits F1A120 RO
157 */
158
159 enum MemType { MM_NOP = 0, MM_RAM = 1, MM_ROM = 2, MM_IO_R = 4, MM_IO_W = 8, MM_IO = 12 };
160
161 struct MemDesc {
162 uint32_t startAddr;
163 uint32_t endAddr;
164 enum MemType type;
165 // (void (* ioFunc)(uint32, uint32)); // <-- could also be a pointer to RAM...
166 void * readFunc; // This is read & write with MM_IO
167 void * writeFunc;
168 uint32_t mask;
169 };
170
171
172 struct MemDesc memoryMap[] = {
173 { 0x000000, 0x3FFFFF, MM_RAM, &jaguarMainRAM },
174 { 0x800000, 0xDFFEFF, MM_ROM, &jaguarMainROM },
175
176 { 0xDFFF00, 0xDFFF03, MM_IO, &butch }, // base of Butch == interrupt control register, R/W
177 { 0xDFFF04, 0xDFFF07, MM_IO, &dscntrl }, // DSA control register, R/W
178 { 0xDFFF0A, 0xDFFF0B, MM_IO, &ds_data }, // DSA TX/RX data, R/W
179 { 0xDFFF10, 0xDFFF13, MM_IO, &i2cntrl }, // i2s bus control register, R/W
180 { 0xDFFF14, 0xDFFF17, MM_IO, &sbcntrl }, // CD subcode control register, R/W
181 { 0xDFFF18, 0xDFFF1B, MM_IO, &subdata }, // Subcode data register A
182 { 0xDFFF1C, 0xDFFF1F, MM_IO, &subdatb }, // Subcode data register B
183 { 0xDFFF20, 0xDFFF23, MM_IO, &sb_time }, // Subcode time and compare enable (D24)
184 { 0xDFFF24, 0xDFFF27, MM_IO, &fifo_data }, // i2s FIFO data
185 { 0xDFFF28, 0xDFFF2B, MM_IO, &i2sdat2 }, // i2s FIFO data (old)
186 { 0xDFFF2C, 0xDFFF2F, MM_IO, &unknown }, // Seems to be some sort of I2S interface
187
188 { 0xE00000, 0xE1FFFF, MM_ROM, jaguarBootROM },
189
190 // TOM REGISTERS
191
192 { 0xF00000, 0xF00001, MM_IO, &memcon1 }, // *MEMCON1 Memory Control Register 1 F00000 RW
193 { 0xF00002, 0xF00003, MM_IO, &memcon2 }, // *MEMCON2 Memory Control Register 2 F00002 RW
194 { 0xF00004, 0xF00005, MM_IO, &hc }, // HC Horizontal Count F00004 RW
195 { 0xF00006, 0xF00007, MM_IO, &vc }, // VC Vertical Count F00006 RW
196 { 0xF00008, 0xF00009, MM_IO_R, &lph }, // LPH Light Pen Horizontal F00008 RO
197 { 0xF0000A, 0xF0000B, MM_IO_R, &lpv }, // LPV Light Pen Vertical F0000A RO
198 { 0xF00010, 0xF00017, MM_IO_R, &obData }, // OB[0-3] Object Data Field F00010-16 RO
199 { 0xF00020, 0xF00023, MM_IO_W, &olp }, // OLP Object List Pointer F00020-23 WO
200 { 0xF00026, 0xF00027, MM_IO_W, &obf }, // OBF Object Flag F00026 WO
201 { 0xF00028, 0xF00029, MM_IO_W, &vmode }, // VMODE Video Mode F00028 WO
202 { 0xF0002A, 0xF0002B, MM_IO_W, &bord1 }, // BORD1 Border Colour (Red & Green) F0002A WO
203 { 0xF0002C, 0xF0002D, MM_IO_W, &bord2 }, // BORD2 Border Colour (Blue) F0002C WO
204 { 0xF0002E, 0xF0002F, MM_IO_W, &hp }, // *HP Horizontal Period F0002E WO
205 { 0xF00030, 0xF00031, MM_IO_W, &hbb }, // *HBB Horizontal Blank Begin F00030 WO
206 { 0xF00032, 0xF00033, MM_IO_W, &hbe }, // *HBE Horizontal Blank End F00032 WO
207 { 0xF00034, 0xF00035, MM_IO_W, &hs }, // *HS Horizontal Sync F00034 WO
208 { 0xF00036, 0xF00037, MM_IO_W, &hvs }, // *HVS Horizontal Vertical Sync F00036 WO
209 { 0xF00038, 0xF00039, MM_IO_W, &hdb1 }, // HDB1 Horizontal Display Begin 1 F00038 WO
210 { 0xF0003A, 0xF0003B, MM_IO_W, &hdb2 }, // HDB2 Horizontal Display Begin 2 F0003A WO
211 { 0xF0003C, 0xF0003D, MM_IO_W, &hde }, // HDE Horizontal Display End F0003C WO
212 { 0xF0003E, 0xF0003F, MM_IO_W, &vp }, // *VP Vertical Period F0003E WO
213 { 0xF00040, 0xF00041, MM_IO_W, &vbb }, // *VBB Vertical Blank Begin F00040 WO
214 { 0xF00042, 0xF00043, MM_IO_W, &vbe }, // *VBE Vertical Blank End F00042 WO
215 { 0xF00044, 0xF00045, MM_IO_W, &vs }, // *VS Vertical Sync F00044 WO
216 { 0xF00046, 0xF00047, MM_IO_W, &vdb }, // VDB Vertical Display Begin F00046 WO
217 { 0xF00048, 0xF00049, MM_IO_W, &vde }, // VDE Vertical Display End F00048 WO
218 { 0xF0004A, 0xF0004B, MM_IO_W, &veb }, // *VEB Vertical Equalization Begin F0004A WO
219 { 0xF0004C, 0xF0004D, MM_IO_W, &vee }, // *VEE Vertical Equalization End F0004C WO
220 { 0xF0004E, 0xF0004F, MM_IO_W, &vi }, // VI Vertical Interrupt F0004E WO
221 { 0xF00050, 0xF00051, MM_IO_W, &pit0 }, // PIT[0-1] Programmable Interrupt Timer F00050-52 WO
222 { 0xF00052, 0xF00053, MM_IO_W, &pit1 },
223 { 0xF00054, 0xF00055, MM_IO_W, &heq }, // *HEQ Horizontal Equalization End F00054 WO
224 { 0xF00058, 0xF0005B, MM_IO_W, &bg }, // BG Background Colour F00058 WO
225 { 0xF000E0, 0xF000E1, MM_IO, &int1 }, // INT1 CPU Interrupt Control Register F000E0 RW
226 { 0xF000E2, 0xF000E3, MM_IO_W, &int2 }, // INT2 CPU Interrupt Resume Register F000E2 WO
227 //Some of these RAM spaces may be 16- or 32-bit only... in which case, we need
228 //to cast appropriately (in memory.cpp, that is)...
229 { 0xF00400, 0xF005FF, MM_RAM, &clut }, // CLUT Colour Look-Up Table F00400-7FE RW
230 { 0xF00600, 0xF007FF, MM_RAM, &clut },
231 { 0xF00800, 0xF01D9F, MM_RAM, &lbuf }, // LBUF Line Buffer F00800-1D9E RW
232 //Need high speed RAM interface for GPU & DSP (we have it now...)
233
234 // GPU REGISTERS
235
236 { 0xF02100, 0xF02103, MM_IO, &g_flags }, // G_FLAGS GPU Flags Register F02100 RW
237 { 0xF02104, 0xF02107, MM_IO_W, &g_mtxc }, // G_MTXC Matrix Control Register F02104 WO
238 { 0xF02108, 0xF0210B, MM_IO_W, &g_mtxa }, // G_MTXA Matrix Address Register F02108 WO
239 { 0xF0210C, 0xF0210F, MM_IO_W, &g_end }, // G_END Data Organization Register F0210C WO
240 { 0xF02110, 0xF02113, MM_IO, &g_pc }, // G_PC GPU Program Counter F02110 RW
241 { 0xF02114, 0xF02117, MM_IO, &g_ctrl }, // G_CTRL GPU Control/Status Register F02114 RW
242 { 0xF02118, 0xF0211B, MM_IO, &g_hidata }, // G_HIDATA High Data Register F02118 RW
243 { 0xF0211C, 0xF0211F, MM_IO, &g_remain, &g_divctrl }, // G_REMAIN Divide Unit Remainder F0211C RO
244 // G_DIVCTRL Divide Unit Control F0211C WO
245 { 0xF03000, 0xF03FFF, MM_RAM, &gpuRAM },
246
247 // BLITTER REGISTERS
248
249 { 0xF02200, 0xF02203, MM_IO_W, &a1_base }, // A1_BASE A1 Base Register F02200 WO
250 { 0xF02204, 0xF02207, MM_IO, &a1_pixel, &a1_flags }, // A1_FLAGS Flags Register F02204 WO
251 { 0xF02208, 0xF0220B, MM_IO_W, &a1_clip }, // A1_CLIP A1 Clipping Size F02208 WO
252 { 0xF0220C, 0xF0220F, MM_IO_W, &a1_pixel }, // A1_PIXEL A1 Pixel Pointer F0220C WO
253 // F02204 RO
254 { 0xF02210, 0xF02213, MM_IO_W, &a1_step }, // A1_STEP A1 Step Value F02210 WO
255 { 0xF02214, 0xF02217, MM_IO_W, &a1_fstep }, // A1_FSTEP A1 Step Fraction Value F02214 WO
256 { 0xF02218, 0xF0221B, MM_IO, &a1_fpixel }, // A1_FPIXEL A1 Pixel Pointer Fraction F02218 RW
257 { 0xF0221C, 0xF0221F, MM_IO_W, &a1_inc }, // A1_INC A1 Increment F0221C WO
258 { 0xF02220, 0xF02223, MM_IO_W, &a1_finc }, // A1_FINC A1 Increment Fraction F02220 WO
259 { 0xF02224, 0xF02227, MM_IO_W, &a2_base }, // A2_BASE A2 Base Register F02224 WO
260 { 0xF02228, 0xF0222B, MM_IO_W, &a2_flags }, // A2_FLAGS A2 Flags Register F02228 WO
261 { 0xF0222C, 0xF0222F, MM_IO, &a2_pixel, &a2_mask }, // A2_MASK A2 Window Mask F0222C WO
262 { 0xF02230, 0xF02233, MM_IO_W, &a2_pixel }, // A2_PIXEL A2 Pixel Pointer F02230 WO
263 // F0222C RO
264 { 0xF02234, 0xF02237, MM_IO_W, &a2_step }, // A2_STEP A2 Step Value F02234 WO
265 { 0xF02238, 0xF0223B, MM_IO, &b_cmd }, // B_CMD Command/Status Register F02238 RW
266 { 0xF0223C, 0xF0223F, MM_IO_W, &b_count }, // B_COUNT Counters Register F0223C WO
267 { 0xF02240, 0xF02247, MM_IO_W, &b_srcd }, // B_SRCD Source Data Register F02240 WO
268 { 0xF02248, 0xF0224F, MM_IO_W, &b_dstd }, // B_DSTD Destination Data Register F02248 WO
269 { 0xF02250, 0xF02258, MM_IO_W, &b_dstz }, // B_DSTZ Destination Z Register F02250 WO
270 { 0xF02258, 0xF0225F, MM_IO_W, &b_srcz1 }, // B_SRCZ1 Source Z Register 1 F02258 WO
271 { 0xF02260, 0xF02267, MM_IO_W, &b_srcz2 }, // B_SRCZ2 Source Z Register 2 F02260 WO
272 { 0xF02268, 0xF0226F, MM_IO_W, &b_patd }, // B_PATD Pattern Data Register F02268 WO
273 { 0xF02270, 0xF02273, MM_IO_W, &b_iinc }, // B_IINC Intensity Increment F02270 WO
274 { 0xF02274, 0xF02277, MM_IO_W, &b_zinc }, // B_ZINC Z Increment F02274 WO
275 { 0xF02278, 0xF0227B, MM_IO_W, &b_stop }, // B_STOP Collision Control F02278 WO
276 { 0xF0227C, 0xF0227F, MM_IO_W, &b_i3 }, // B_I3 Intensity 3 F0227C WO
277 { 0xF02280, 0xF02283, MM_IO_W, &b_i2 }, // B_I2 Intensity 2 F02280 WO
278 { 0xF02284, 0xF02287, MM_IO_W, &b_i1 }, // B_I1 Intensity 1 F02284 WO
279 { 0xF02288, 0xF0228B, MM_IO_W, &b_i0 }, // B_I0 Intensity 0 F02288 WO
280 { 0xF0228C, 0xF0228F, MM_IO_W, &b_z3 }, // B_Z3 Z 3 F0228C WO
281 { 0xF02290, 0xF02293, MM_IO_W, &b_z2 }, // B_Z2 Z 2 F02290 WO
282 { 0xF02294, 0xF02297, MM_IO_W, &b_z1 }, // B_Z1 Z 1 F02294 WO
283 { 0xF02298, 0xF0229B, MM_IO_W, &b_z0 }, // B_Z0 Z 0 F02298 WO
284
285 // JTRM sez ALL GPU address space is accessible from $8000 offset as "fast" 32-bit WO access
286 // Dunno if anything actually USED it tho... :-P
287 { 0xF0A100, 0xF0A103, MM_IO_W, &g_flags }, // G_FLAGS GPU Flags Register F02100 RW
288 { 0xF0A104, 0xF0A107, MM_IO_W, &g_mtxc }, // G_MTXC Matrix Control Register F02104 WO
289 { 0xF0A108, 0xF0A10B, MM_IO_W, &g_mtxa }, // G_MTXA Matrix Address Register F02108 WO
290 { 0xF0A10C, 0xF0A10F, MM_IO_W, &g_end }, // G_END Data Organization Register F0210C WO
291 { 0xF0A110, 0xF0A113, MM_IO_W, &g_pc }, // G_PC GPU Program Counter F02110 RW
292 { 0xF0A114, 0xF0A117, MM_IO_W, &g_ctrl }, // G_CTRL GPU Control/Status Register F02114 RW
293 { 0xF0A118, 0xF0A11B, MM_IO_W, &g_hidata }, // G_HIDATA High Data Register F02118 RW
294 { 0xF0A11C, 0xF0A11F, MM_IO_W, &g_divctrl }, // G_REMAIN Divide Unit Remainder F0211C RO
295 { 0xF0B000, 0xF0BFFF, MM_IO_W, &gpuRAM }, // "Fast" interface to GPU RAM
296
297 // JERRY REGISTERS
298
299 { 0xF10000, 0xF10001, MM_IO_W, &jpit1 }, // JPIT1 Timer 1 Pre-scaler F10000 WO
300 { 0xF10002, 0xF10003, MM_IO_W, &jpit2 }, // JPIT2 Timer 1 Divider F10002 WO
301 { 0xF10004, 0xF10005, MM_IO_W, &jpit3 }, // JPIT3 Timer 2 Pre-scaler F10004 WO
302 { 0xF10006, 0xF10007, MM_IO_W, &jpit4 }, // JPIT4 Timer 2 Divider F10006 WO
303 { 0xF10010, 0xF10011, MM_IO_W, &clk1 }, // *CLK1 Processor Clock Divider F10010 WO
304 { 0xF10012, 0xF10013, MM_IO_W, &clk2 }, // *CLK2 Video Clock Divider F10012 WO
305 { 0xF10014, 0xF10015, MM_IO_W, &clk3 }, // *CLK3 Chroma Clock Divider F10014 WO
306 { 0xF10020, 0xF10021, MM_IO, &j_int }, // J_INT Interrup Control Register F10020 RW
307 { 0xF10030, 0xF10031, MM_IO, &asidata }, // ASIDATA Asynchronous Serial Data F10030 RW
308 { 0xF10032, 0xF10033, MM_IO, &asistat, &asictrl }, // ASICTRL Asynchronous Serial Control F10032 WO
309 // ASISTAT Asynchronous Serial Status F10032 RO
310 { 0xF10034, 0xF10035, MM_IO, &asiclk }, // ASICLK Asynchronous Serial Interface Clock F10034 RW
311 { 0xF10036, 0xF10037, MM_IO_R, &jpit1 }, // JPIT1 Timer 1 Pre-scaler F10036 RO
312 { 0xF10038, 0xF10039, MM_IO_R, &jpit2 }, // JPIT2 Timer 1 Divider F10038 RO
313 { 0xF1003A, 0xF1003B, MM_IO_R, &jpit3 }, // JPIT3 Timer 2 Pre-scaler F1003A RO
314 { 0xF1003C, 0xF1003D, MM_IO_R, &jpit4 }, // JPIT4 Timer 2 Divider F1003C RO
315
316 { 0xF14000, 0xF14001, MM_IO, &joystick }, // JOYSTICK Joystick Register F14000 RW
317 { 0xF14002, 0xF14003, MM_IO, &joybuts }, // JOYBUTS Button Register F14002 RW
318
319 // DSP REGISTERS
320
321 { 0xF1A100, 0xF1A103, MM_IO, &d_flags }, // D_FLAGS DSP Flags Register F1A100 RW
322 { 0xF1A104, 0xF1A107, MM_IO_W, &d_mtxc }, // D_MTXC DSP Matrix Control Register F1A104 WO
323 { 0xF1A108, 0xF1A10B, MM_IO_W, &d_mtxa }, // D_MTXA DSP Matrix Address Register F1A108 WO
324 { 0xF1A10C, 0xF1A10F, MM_IO_W, &d_end }, // D_END DSP Data Organization Register F1A10C WO
325 { 0xF1A110, 0xF1A113, MM_IO, &d_pc }, // D_PC DSP Program Counter F1A110 RW
326 { 0xF1A114, 0xF1A117, MM_IO, &d_ctrl }, // D_CTRL DSP Control/Status Register F1A114 RW
327 { 0xF1A118, 0xF1A11B, MM_IO_W, &d_mod }, // D_MOD Modulo Instruction Mask F1A118 WO
328 { 0xF1A11C, 0xF1A11F, MM_IO_W, &d_remain, &d_divctrl }, // D_REMAIN Divide Unit Remainder F1A11C RO
329 // D_DIVCTRL Divide Unit Control F1A11C WO
330 { 0xF1A120, 0xF1A123, MM_IO_R, &d_machi }, // D_MACHI MAC High Result Bits F1A120 RO
331
332
333 { 0xF1A148, 0xF1A149, MM_IO, &lrxd, <xd }, // LTXD Left Transmit Data F1A148 WO
334 // LRXD Left Receive Data F1A148 RO
335 // L_I2S Left I2S Serial Interface F1A148 RW
336 { 0xF1A14C, 0xF1A14D, MM_IO, &rrxd, &rtxd }, // RTXD Right Transmit Data F1A14C WO
337 // RRXD Right Receive Data F1A14C RO
338 // R_I2S Right I2S Serial Interface F1A14C RW
339 { 0xF1A150, 0xF1A150, MM_IO, &sstat, &sclk }, // SCLK Serial Clock Frequency F1A150 WO
340 // SSTAT Serial Status F1A150 RO
341 { 0xF1A154, 0xF1A157, MM_IO_W, &smode }, // SMODE Serial Mode F1A154 WO
342
343 { 0xF1B000, 0xF1CFFF, MM_RAM, &dspRAM }, // F1B000-F1CFFF R/W xxxxxxxx xxxxxxxx Local DSP RAM
344 { 0xF1D000, 0xF1DFFF, MM_ROM, waveTableROM },
345 // hi-speed interface for DSP??? Ain't no such thang...
346 { 0xFFFFFF, 0xFFFFFF, MM_NOP } // End of memory address sentinel
347 };
348
MMUWrite8(uint32_t address,uint8_t data,uint32_t who)349 void MMUWrite8(uint32_t address, uint8_t data, uint32_t who/*= UNKNOWN*/)
350 {
351 }
352
MMUWrite16(uint32_t address,uint16_t data,uint32_t who)353 void MMUWrite16(uint32_t address, uint16_t data, uint32_t who/*= UNKNOWN*/)
354 {
355 }
356
MMUWrite32(uint32_t address,uint32_t data,uint32_t who)357 void MMUWrite32(uint32_t address, uint32_t data, uint32_t who/*= UNKNOWN*/)
358 {
359 }
360
MMUWrite64(uint32_t address,uint64_t data,uint32_t who)361 void MMUWrite64(uint32_t address, uint64_t data, uint32_t who/*= UNKNOWN*/)
362 {
363 }
364
365 #define FUNC_CAST(retVal, function, params) (*(retVal(*)(params))function)
366
MMURead8(uint32_t address,uint32_t who)367 uint8_t MMURead8(uint32_t address, uint32_t who/*= UNKNOWN*/)
368 {
369 // Search for address in the memory map
370 // NOTE: This assumes that all entries are linear and sorted in ascending order!
371
372 struct MemDesc memory;
373 uint32_t offset;
374 uint8_t byte = 0xFE;
375 uint8_t byteShift[8] = { 0, 8, 16, 24, 32, 40, 48, 56 };
376 uint32_t i = 0;
377
378 while (true)
379 {
380 if (address <= memoryMap[i].endAddr)
381 {
382 if (address >= memoryMap[i].startAddr)
383 {
384 memory = memoryMap[i];
385 break;
386 }
387 return 0xFF; // Wasn't found...
388 }
389
390 i++;
391
392 if (memoryMap[i].startAddr == 0xFFFFFF)
393 return 0xFF; // Exhausted the list, so bail!
394 }
395
396 offset = address - memory.startAddr;
397
398 if (memory.type == MM_RAM || memory.type == MM_ROM)
399 byte = ((uint8_t *)memory.readFunc)[offset];
400 else if (memory.type == MM_IO_R || memory.type == MM_IO)
401 {
402 uint64_t retVal = FUNC_CAST(uint64_t, memory.readFunc, uint32_t)(offset);
403 byte = (retVal >> byteShift[offset]) & 0xFF;
404 }
405 else if (memory.type == MM_IO_W)
406 byte = 0xFF; // Write only, what do we return? A fixed value?
407
408 return byte;
409 }
410
MMURead16(uint32_t address,uint32_t who)411 uint16_t MMURead16(uint32_t address, uint32_t who)
412 {
413 return 0;
414 }
415
MMURead32(uint32_t address,uint32_t who)416 uint32_t MMURead32(uint32_t address, uint32_t who)
417 {
418 return 0;
419 }
420
MMURead64(uint32_t address,uint32_t who)421 uint64_t MMURead64(uint32_t address, uint32_t who)
422 {
423 return 0;
424 }
425
426