port to 64bit. Some gcc 4.4 warning fixes
[picodrive.git] / pico / 32x / memory.c
1 /*
2  * SH2 addr lines:
3  * iii. .cc. ..xx *   // Internal, Cs, x
4  *
5  * Register map:
6  * a15100 F....... R.....EA  F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm
7  * a15102 ........ ......SM  ?                 4002 // intS intM
8  * a15104 ........ ......10  ........ hhhhhhhh 4004 // bk1 bk0 Hint
9  * a15106 F....... .....SDR  UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb]
10  * a15108           (32bit DREQ src)           4008
11  * a1510c           (32bit DREQ dst)           400c
12  * a15110          llllllll llllll00           4010 // DREQ Len
13  * a15112           (16bit FIFO reg)           4012
14  * a15114 ?                  (16bit VRES clr)  4014
15  * a15116 ?                  (16bit Vint clr)  4016
16  * a15118 ?                  (16bit Hint clr)  4018
17  * a1511a ........ .......C  (16bit CMD clr)   401a // Cm
18  * a1511c ?                  (16bit PWM clr)   401c
19  * a1511e ?                  ?                 401e
20  * a15120            (16 bytes comm)           2020
21  * a15130                 (PWM)                2030
22  */
23 #include "../pico_int.h"
24 #include "../memory.h"
25 #ifdef DRC_SH2
26 #include "../../cpu/sh2/compiler.h"
27 #endif
28
29 #if 0
30 #undef ash2_end_run
31 #undef SekEndRun
32 #define ash2_end_run(x)
33 #define SekEndRun(x)
34 #endif
35
36 static const char str_mars[] = "MARS";
37
38 void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
39 struct Pico32xMem *Pico32xMem;
40
41 static void bank_switch(int b);
42
43 // poll detection
44 #define POLL_THRESHOLD 6
45
46 struct poll_det {
47   u32 addr, cycles, cyc_max;
48   int cnt, flag;
49 };
50 static struct poll_det m68k_poll, sh2_poll[2];
51
52 static int p32x_poll_detect(struct poll_det *pd, u32 a, u32 cycles, int is_vdp)
53 {
54   int ret = 0, flag = pd->flag;
55
56   if (is_vdp)
57     flag <<= 3;
58
59   if (a - 2 <= pd->addr && pd->addr <= a + 2 && cycles - pd->cycles <= pd->cyc_max) {
60     pd->cnt++;
61     if (pd->cnt > POLL_THRESHOLD) {
62       if (!(Pico32x.emu_flags & flag)) {
63         elprintf(EL_32X, "%s poll addr %08x, cyc %u",
64           flag & (P32XF_68KPOLL|P32XF_68KVPOLL) ? "m68k" :
65           (flag & (P32XF_MSH2POLL|P32XF_MSH2VPOLL) ? "msh2" : "ssh2"), a, cycles - pd->cycles);
66         ret = 1;
67       }
68       Pico32x.emu_flags |= flag;
69     }
70   }
71   else {
72     pd->cnt = 0;
73     pd->addr = a;
74   }
75   pd->cycles = cycles;
76
77   return ret;
78 }
79
80 static int p32x_poll_undetect(struct poll_det *pd, int is_vdp)
81 {
82   int ret = 0, flag = pd->flag;
83   if (is_vdp)
84     flag <<= 3; // VDP only
85   else
86     flag |= flag << 3; // both
87   if (Pico32x.emu_flags & flag) {
88     elprintf(EL_32X, "poll %02x -> %02x", Pico32x.emu_flags, Pico32x.emu_flags & ~flag);
89     ret = 1;
90   }
91   Pico32x.emu_flags &= ~flag;
92   pd->addr = pd->cnt = 0;
93   return ret;
94 }
95
96 void p32x_poll_event(int cpu_mask, int is_vdp)
97 {
98   if (cpu_mask & 1)
99     p32x_poll_undetect(&sh2_poll[0], is_vdp);
100   if (cpu_mask & 2)
101     p32x_poll_undetect(&sh2_poll[1], is_vdp);
102 }
103
104 // SH2 faking
105 //#define FAKE_SH2
106 int p32x_csum_faked;
107 #ifdef FAKE_SH2
108 static const u16 comm_fakevals[] = {
109   0x4d5f, 0x4f4b, // M_OK
110   0x535f, 0x4f4b, // S_OK
111   0x4D41, 0x5346, // MASF - Brutal Unleashed
112   0x5331, 0x4d31, // Darxide
113   0x5332, 0x4d32,
114   0x5333, 0x4d33,
115   0x0000, 0x0000, // eq for doom
116   0x0002, // Mortal Kombat
117 //  0, // pad
118 };
119
120 static u32 sh2_comm_faker(u32 a)
121 {
122   static int f = 0;
123   if (a == 0x28 && !p32x_csum_faked) {
124     p32x_csum_faked = 1;
125     return *(unsigned short *)(Pico.rom + 0x18e);
126   }
127   if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
128     f = 0;
129   return comm_fakevals[f++];
130 }
131 #endif
132
133 // DMAC handling
134 static struct {
135   unsigned int sar0, dar0, tcr0; // src addr, dst addr, transfer count
136   unsigned int chcr0; // chan ctl
137   unsigned int sar1, dar1, tcr1; // same for chan 1
138   unsigned int chcr1;
139   int pad[4];
140   unsigned int dmaor;
141 } * dmac0;
142
143 static void dma_68k2sh2_do(void)
144 {
145   unsigned short *dreqlen = &Pico32x.regs[0x10 / 2];
146   int i;
147
148   if (dmac0->tcr0 != *dreqlen)
149     elprintf(EL_32X|EL_ANOMALY, "tcr0 and dreq len differ: %d != %d", dmac0->tcr0, *dreqlen);
150
151   // HACK: assume bus is busy and SH2 is halted
152   // XXX: use different mechanism for this, not poll det
153   Pico32x.emu_flags |= P32XF_MSH2POLL; // id ? P32XF_SSH2POLL : P32XF_MSH2POLL;
154
155   for (i = 0; i < Pico32x.dmac_ptr && dmac0->tcr0 > 0; i++) {
156     elprintf(EL_32X, "dmaw [%08x] %04x, left %d", dmac0->dar0, Pico32x.dmac_fifo[i], *dreqlen);
157     p32x_sh2_write16(dmac0->dar0, Pico32x.dmac_fifo[i], &msh2);
158     dmac0->dar0 += 2;
159     dmac0->tcr0--;
160     (*dreqlen)--;
161   }
162
163   Pico32x.dmac_ptr = 0; // HACK
164   Pico32x.regs[6 / 2] &= ~P32XS_FULL;
165   if (*dreqlen == 0)
166     Pico32x.regs[6 / 2] &= ~P32XS_68S; // transfer complete
167   if (dmac0->tcr0 == 0) {
168     dmac0->chcr0 |= 2; // DMA has ended normally
169     p32x_poll_undetect(&sh2_poll[0], 0);
170   }
171 }
172
173 // ------------------------------------------------------------------
174 // 68k regs
175
176 static u32 p32x_reg_read16(u32 a)
177 {
178   a &= 0x3e;
179
180   if (a == 2) // INTM, INTS
181     return ((Pico32x.sh2irqi[0] & P32XI_CMD) >> 4) | ((Pico32x.sh2irqi[1] & P32XI_CMD) >> 3);
182 #if 0
183   if ((a & 0x30) == 0x20)
184     return sh2_comm_faker(a);
185 #else
186   if ((a & 0x30) == 0x20) {
187     // evil X-Men proto polls in a dbra loop and expects it to expire..
188     static u32 dr2 = 0;
189     if (SekDar(2) != dr2)
190       m68k_poll.cnt = 0;
191     dr2 = SekDar(2);
192
193     if (p32x_poll_detect(&m68k_poll, a, SekCyclesDoneT(), 0)) {
194       SekSetStop(1);
195       SekEndTimeslice(16);
196     }
197     dr2 = SekDar(2);
198   }
199 #endif
200
201   if ((a & 0x30) == 0x30)
202     return p32x_pwm_read16(a);
203
204   return Pico32x.regs[a / 2];
205 }
206
207 static void p32x_reg_write8(u32 a, u32 d)
208 {
209   u16 *r = Pico32x.regs;
210   a &= 0x3f;
211
212   // for things like bset on comm port
213   m68k_poll.cnt = 0;
214
215   switch (a) {
216     case 0: // adapter ctl
217       r[0] = (r[0] & ~P32XS_FM) | ((d << 8) & P32XS_FM);
218       return;
219     case 1: // adapter ctl, RES bit writeable
220       if ((d ^ r[0]) & d & P32XS_nRES)
221         p32x_reset_sh2s();
222       r[0] = (r[0] & ~P32XS_nRES) | (d & P32XS_nRES);
223       return;
224     case 3: // irq ctl
225       if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
226         Pico32x.sh2irqi[0] |= P32XI_CMD;
227         p32x_update_irls();
228         SekEndRun(16);
229       }
230       if ((d & 2) && !(Pico32x.sh2irqi[1] & P32XI_CMD)) {
231         Pico32x.sh2irqi[1] |= P32XI_CMD;
232         p32x_update_irls();
233         SekEndRun(16);
234       }
235       return;
236     case 5: // bank
237       d &= 7;
238       if (r[4 / 2] != d) {
239         r[4 / 2] = d;
240         bank_switch(d);
241       }
242       return;
243     case 7: // DREQ ctl
244       r[6 / 2] = (r[6 / 2] & P32XS_FULL) | (d & (P32XS_68S|P32XS_DMA|P32XS_RV));
245       return;
246     case 0x1b: // TV
247       r[0x1a / 2] = d;
248       return;
249   }
250
251   if ((a & 0x30) == 0x20) {
252     u8 *r8 = (u8 *)r;
253     r8[a ^ 1] = d;
254     p32x_poll_undetect(&sh2_poll[0], 0);
255     p32x_poll_undetect(&sh2_poll[1], 0);
256     // if some SH2 is busy waiting, it needs to see the result ASAP
257     if (SekCyclesLeftNoMCD > 32)
258       SekEndRun(32);
259     return;
260   }
261 }
262
263 static void p32x_reg_write16(u32 a, u32 d)
264 {
265   u16 *r = Pico32x.regs;
266   a &= 0x3e;
267
268   // for things like bset on comm port
269   m68k_poll.cnt = 0;
270
271   switch (a) {
272     case 0x00: // adapter ctl
273       if ((d ^ r[0]) & d & P32XS_nRES)
274         p32x_reset_sh2s();
275       r[0] = (r[0] & ~(P32XS_FM|P32XS_nRES)) | (d & (P32XS_FM|P32XS_nRES));
276       return;
277     case 0x10: // DREQ len
278       r[a / 2] = d & ~3;
279       return;
280     case 0x12: // FIFO reg
281       if (!(r[6 / 2] & P32XS_68S)) {
282         elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?");
283         return;
284       }
285       if (Pico32x.dmac_ptr < DMAC_FIFO_LEN) {
286         Pico32x.dmac_fifo[Pico32x.dmac_ptr++] = d;
287         if ((Pico32x.dmac_ptr & 3) == 0 && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1))
288           dma_68k2sh2_do();
289         if (Pico32x.dmac_ptr == DMAC_FIFO_LEN)
290           r[6 / 2] |= P32XS_FULL;
291       }
292       break;
293   }
294
295   // DREQ src, dst
296   if      ((a & 0x38) == 0x08) {
297     r[a / 2] = d;
298     return;
299   }
300   // comm port
301   else if ((a & 0x30) == 0x20 && r[a / 2] != d) {
302     r[a / 2] = d;
303     p32x_poll_undetect(&sh2_poll[0], 0);
304     p32x_poll_undetect(&sh2_poll[1], 0);
305     // same as for w8
306     if (SekCyclesLeftNoMCD > 32)
307       SekEndRun(32);
308     return;
309   }
310   // PWM
311   else if ((a & 0x30) == 0x30) {
312     p32x_pwm_write16(a, d);
313     return;
314   }
315
316   p32x_reg_write8(a + 1, d);
317 }
318
319 // ------------------------------------------------------------------
320 // VDP regs
321 static u32 p32x_vdp_read16(u32 a)
322 {
323   a &= 0x0e;
324
325   return Pico32x.vdp_regs[a / 2];
326 }
327
328 static void p32x_vdp_write8(u32 a, u32 d)
329 {
330   u16 *r = Pico32x.vdp_regs;
331   a &= 0x0f;
332
333   // for FEN checks between writes
334   sh2_poll[0].cnt = 0;
335
336   // TODO: verify what's writeable
337   switch (a) {
338     case 0x01:
339       // priority inversion is handled in palette
340       if ((r[0] ^ d) & P32XV_PRI)
341         Pico32x.dirty_pal = 1;
342       r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
343       break;
344     case 0x05: // fill len
345       r[4 / 2] = d & 0xff;
346       break;
347     case 0x0b:
348       d &= 1;
349       Pico32x.pending_fb = d;
350       // if we are blanking and FS bit is changing
351       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
352         r[0x0a/2] ^= 1;
353         Pico32xSwapDRAM(d ^ 1);
354         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
355       }
356       break;
357   }
358 }
359
360 static void p32x_vdp_write16(u32 a, u32 d)
361 {
362   a &= 0x0e;
363   if (a == 6) { // fill start
364     Pico32x.vdp_regs[6 / 2] = d;
365     return;
366   }
367   if (a == 8) { // fill data
368     u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
369     int len = Pico32x.vdp_regs[4 / 2] + 1;
370     a = Pico32x.vdp_regs[6 / 2];
371     while (len--) {
372       dram[a] = d;
373       a = (a & 0xff00) | ((a + 1) & 0xff);
374     }
375     Pico32x.vdp_regs[6 / 2] = a;
376     Pico32x.vdp_regs[8 / 2] = d;
377     return;
378   }
379
380   p32x_vdp_write8(a | 1, d);
381 }
382
383 // ------------------------------------------------------------------
384 // SH2 regs
385
386 static u32 p32x_sh2reg_read16(u32 a, int cpuid)
387 {
388   u16 *r = Pico32x.regs;
389   a &= 0xfe; // ?
390
391   switch (a) {
392     case 0x00: // adapter/irq ctl
393       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[cpuid];
394     case 0x04: // H count (often as comm too)
395       if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
396         ash2_end_run(8);
397       return Pico32x.sh2_regs[4 / 2];
398     case 0x10: // DREQ len
399       return r[a / 2];
400   }
401
402   // DREQ src, dst
403   if ((a & 0x38) == 0x08)
404     return r[a / 2];
405   // comm port
406   if ((a & 0x30) == 0x20) {
407     if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
408       ash2_end_run(8);
409     return r[a / 2];
410   }
411   if ((a & 0x30) == 0x30) {
412     sh2_poll[cpuid].cnt = 0;
413     return p32x_pwm_read16(a);
414   }
415
416   return 0;
417 }
418
419 static void p32x_sh2reg_write8(u32 a, u32 d, int cpuid)
420 {
421   a &= 0xff;
422   switch (a) {
423     case 0: // FM
424       Pico32x.regs[0] &= ~P32XS_FM;
425       Pico32x.regs[0] |= (d << 8) & P32XS_FM;
426       return;
427     case 1: // 
428       Pico32x.sh2irq_mask[cpuid] = d & 0x8f;
429       Pico32x.sh2_regs[0] &= ~0x80;
430       Pico32x.sh2_regs[0] |= d & 0x80;
431       p32x_update_irls();
432       return;
433     case 5: // H count
434       Pico32x.sh2_regs[4 / 2] = d & 0xff;
435       p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
436       return;
437   }
438
439   if ((a & 0x30) == 0x20) {
440     u8 *r8 = (u8 *)Pico32x.regs;
441     r8[a ^ 1] = d;
442     if (p32x_poll_undetect(&m68k_poll, 0))
443       SekSetStop(0);
444     p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
445     return;
446   }
447 }
448
449 static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid)
450 {
451   a &= 0xfe;
452
453   // comm
454   if ((a & 0x30) == 0x20 && Pico32x.regs[a/2] != d) {
455     Pico32x.regs[a / 2] = d;
456     if (p32x_poll_undetect(&m68k_poll, 0))
457       SekSetStop(0);
458     p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
459     return;
460   }
461   // PWM
462   else if ((a & 0x30) == 0x30) {
463     p32x_pwm_write16(a, d);
464     return;
465   }
466
467   switch (a) {
468     case 0: // FM
469       Pico32x.regs[0] &= ~P32XS_FM;
470       Pico32x.regs[0] |= d & P32XS_FM;
471       break;
472     case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls;
473     case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls;
474     case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls;
475     case 0x1a: Pico32x.sh2irqi[cpuid] &= ~P32XI_CMD; goto irls;
476     case 0x1c:
477       Pico32x.sh2irqs &= ~P32XI_PWM;
478       p32x_timers_do(0);
479       goto irls;
480   }
481
482   p32x_sh2reg_write8(a | 1, d, cpuid);
483   return;
484
485 irls:
486   p32x_update_irls();
487 }
488
489 // ------------------------------------------------------------------
490 // SH2 internal peripherals
491 // we keep them in little endian format
492 static u32 sh2_peripheral_read8(u32 a, int id)
493 {
494   u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
495   u32 d;
496
497   a &= 0x1ff;
498   d = PREG8(r, a);
499
500   elprintf(EL_32X, "%csh2 peri r8  [%08x]       %02x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
501   return d;
502 }
503
504 static u32 sh2_peripheral_read16(u32 a, int id)
505 {
506   u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
507   u32 d;
508
509   a &= 0x1ff;
510   d = r[(a / 2) ^ 1];
511
512   elprintf(EL_32X, "%csh2 peri r16 [%08x]     %04x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
513   return d;
514 }
515
516 static u32 sh2_peripheral_read32(u32 a, int id)
517 {
518   u32 d;
519   a &= 0x1fc;
520   d = Pico32xMem->sh2_peri_regs[id][a / 4];
521
522   elprintf(EL_32X, "%csh2 peri r32 [%08x] %08x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
523   return d;
524 }
525
526 static void sh2_peripheral_write8(u32 a, u32 d, int id)
527 {
528   u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
529   elprintf(EL_32X, "%csh2 peri w8  [%08x]       %02x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
530
531   a &= 0x1ff;
532   PREG8(r, a) = d;
533
534   // X-men SCI hack
535   if ((a == 2 &&  (d & 0x20)) || // transmiter enabled
536       (a == 4 && !(d & 0x80))) { // valid data in TDR
537     void *oregs = Pico32xMem->sh2_peri_regs[id ^ 1];
538     if ((PREG8(oregs, 2) & 0x50) == 0x50) { // receiver + irq enabled
539       int level = PREG8(oregs, 0x60) >> 4;
540       int vector = PREG8(oregs, 0x63) & 0x7f;
541       elprintf(EL_32X, "%csh2 SCI recv irq (%d, %d)", (id ^ 1) ? 's' : 'm', level, vector);
542       sh2_internal_irq(&sh2s[id ^ 1], level, vector);
543     }
544   }
545 }
546
547 static void sh2_peripheral_write16(u32 a, u32 d, int id)
548 {
549   u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
550   elprintf(EL_32X, "%csh2 peri w16 [%08x]     %04x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
551
552   a &= 0x1ff;
553
554   // evil WDT
555   if (a == 0x80) {
556     if ((d & 0xff00) == 0xa500) { // WTCSR
557       PREG8(r, 0x80) = d;
558       p32x_timers_recalc();
559     }
560     if ((d & 0xff00) == 0x5a00) // WTCNT
561       PREG8(r, 0x81) = d;
562     return;
563   }
564
565   r[(a / 2) ^ 1] = d;
566 }
567
568 static void sh2_peripheral_write32(u32 a, u32 d, int id)
569 {
570   u32 *r = Pico32xMem->sh2_peri_regs[id];
571   elprintf(EL_32X, "%csh2 peri w32 [%08x] %08x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
572
573   a &= 0x1fc;
574   r[a / 4] = d;
575
576   switch (a) {
577     // division unit (TODO: verify):
578     case 0x104: // DVDNT: divident L, starts divide
579       elprintf(EL_32X, "%csh2 divide %08x / %08x", id ? 's' : 'm', d, r[0x100 / 4]);
580       if (r[0x100 / 4]) {
581         signed int divisor = r[0x100 / 4];
582                        r[0x118 / 4] = r[0x110 / 4] = (signed int)d % divisor;
583         r[0x104 / 4] = r[0x11c / 4] = r[0x114 / 4] = (signed int)d / divisor;
584       }
585       else
586         r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
587       break;
588     case 0x114:
589       elprintf(EL_32X, "%csh2 divide %08x%08x / %08x @%08x",
590         id ? 's' : 'm', r[0x110 / 4], d, r[0x100 / 4], sh2_pc(id));
591       if (r[0x100 / 4]) {
592         signed long long divident = (signed long long)r[0x110 / 4] << 32 | d;
593         signed int divisor = r[0x100 / 4];
594         // XXX: undocumented mirroring to 0x118,0x11c?
595         r[0x118 / 4] = r[0x110 / 4] = divident % divisor;
596         divident /= divisor;
597         r[0x11c / 4] = r[0x114 / 4] = divident;
598         divident >>= 31;
599         if ((unsigned long long)divident + 1 > 1) {
600           //elprintf(EL_32X, "%csh2 divide overflow! @%08x", id ? 's' : 'm', sh2_pc(id));
601           r[0x11c / 4] = r[0x114 / 4] = divident > 0 ? 0x7fffffff : 0x80000000; // overflow
602         }
603       }
604       else
605         r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
606       break;
607   }
608
609   if ((a == 0x1b0 || a == 0x18c) && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1)) {
610     elprintf(EL_32X, "sh2 DMA %08x -> %08x, cnt %d, chcr %04x @%06x",
611       dmac0->sar0, dmac0->dar0, dmac0->tcr0, dmac0->chcr0, sh2_pc(id));
612     dmac0->tcr0 &= 0xffffff;
613
614     // HACK: assume 68k starts writing soon and end the timeslice
615     ash2_end_run(16);
616
617     // DREQ is only sent after first 4 words are written.
618     // we do multiple of 4 words to avoid messing up alignment
619     if (dmac0->sar0 == 0x20004012 && Pico32x.dmac_ptr && (Pico32x.dmac_ptr & 3) == 0) {
620       elprintf(EL_32X, "68k -> sh2 DMA");
621       dma_68k2sh2_do();
622     }
623   }
624 }
625
626 // ------------------------------------------------------------------
627 // 32x handlers
628
629 // after ADEN
630 static u32 PicoRead8_32x_on(u32 a)
631 {
632   u32 d = 0;
633   if ((a & 0xffc0) == 0x5100) { // a15100
634     d = p32x_reg_read16(a);
635     goto out_16to8;
636   }
637
638   if ((a & 0xfc00) != 0x5000)
639     return PicoRead8_io(a);
640
641   if ((a & 0xfff0) == 0x5180) { // a15180
642     d = p32x_vdp_read16(a);
643     goto out_16to8;
644   }
645
646   if ((a & 0xfe00) == 0x5200) { // a15200
647     d = Pico32xMem->pal[(a & 0x1ff) / 2];
648     goto out_16to8;
649   }
650
651   if ((a & 0xfffc) == 0x30ec) { // a130ec
652     d = str_mars[a & 3];
653     goto out;
654   }
655
656   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
657   return d;
658
659 out_16to8:
660   if (a & 1)
661     d &= 0xff;
662   else
663     d >>= 8;
664
665 out:
666   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
667   return d;
668 }
669
670 static u32 PicoRead16_32x_on(u32 a)
671 {
672   u32 d = 0;
673   if ((a & 0xffc0) == 0x5100) { // a15100
674     d = p32x_reg_read16(a);
675     goto out;
676   }
677
678   if ((a & 0xfc00) != 0x5000)
679     return PicoRead16_io(a);
680
681   if ((a & 0xfff0) == 0x5180) { // a15180
682     d = p32x_vdp_read16(a);
683     goto out;
684   }
685
686   if ((a & 0xfe00) == 0x5200) { // a15200
687     d = Pico32xMem->pal[(a & 0x1ff) / 2];
688     goto out;
689   }
690
691   if ((a & 0xfffc) == 0x30ec) { // a130ec
692     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
693     goto out;
694   }
695
696   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
697   return d;
698
699 out:
700   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
701   return d;
702 }
703
704 static void PicoWrite8_32x_on(u32 a, u32 d)
705 {
706   if ((a & 0xfc00) == 0x5000)
707     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
708
709   if ((a & 0xffc0) == 0x5100) { // a15100
710     p32x_reg_write8(a, d);
711     return;
712   }
713
714   if ((a & 0xfc00) != 0x5000) {
715     PicoWrite8_io(a, d);
716     return;
717   }
718
719   if ((a & 0xfff0) == 0x5180) { // a15180
720     p32x_vdp_write8(a, d);
721     return;
722   }
723
724   // TODO: verify
725   if ((a & 0xfe00) == 0x5200) { // a15200
726     elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
727     ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
728     Pico32x.dirty_pal = 1;
729     return;
730   }
731
732   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
733 }
734
735 static void PicoWrite16_32x_on(u32 a, u32 d)
736 {
737   if ((a & 0xfc00) == 0x5000)
738     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
739
740   if ((a & 0xffc0) == 0x5100) { // a15100
741     p32x_reg_write16(a, d);
742     return;
743   }
744
745   if ((a & 0xfc00) != 0x5000) {
746     PicoWrite16_io(a, d);
747     return;
748   }
749
750   if ((a & 0xfff0) == 0x5180) { // a15180
751     p32x_vdp_write16(a, d);
752     return;
753   }
754
755   if ((a & 0xfe00) == 0x5200) { // a15200
756     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
757     Pico32x.dirty_pal = 1;
758     return;
759   }
760
761   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
762 }
763
764 // before ADEN
765 u32 PicoRead8_32x(u32 a)
766 {
767   u32 d = 0;
768   if ((a & 0xffc0) == 0x5100) { // a15100
769     // regs are always readable
770     d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
771     goto out;
772   }
773
774   if ((a & 0xfffc) == 0x30ec) { // a130ec
775     d = str_mars[a & 3];
776     goto out;
777   }
778
779   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
780   return d;
781
782 out:
783   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
784   return d;
785 }
786
787 u32 PicoRead16_32x(u32 a)
788 {
789   u32 d = 0;
790   if ((a & 0xffc0) == 0x5100) { // a15100
791     d = Pico32x.regs[(a & 0x3f) / 2];
792     goto out;
793   }
794
795   if ((a & 0xfffc) == 0x30ec) { // a130ec
796     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
797     goto out;
798   }
799
800   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
801   return d;
802
803 out:
804   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
805   return d;
806 }
807
808 void PicoWrite8_32x(u32 a, u32 d)
809 {
810   if ((a & 0xffc0) == 0x5100) { // a15100
811     u16 *r = Pico32x.regs;
812
813     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
814     a &= 0x3f;
815     if (a == 1) {
816       if ((d ^ r[0]) & d & P32XS_ADEN) {
817         Pico32xStartup();
818         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
819         r[0] |= P32XS_ADEN;
820         p32x_reg_write8(a, d); // forward for reset processing
821       }
822       return;
823     }
824
825     // allow only COMM for now
826     if ((a & 0x30) == 0x20) {
827       u8 *r8 = (u8 *)r;
828       r8[a ^ 1] = d;
829     }
830     return;
831   }
832
833   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
834 }
835
836 void PicoWrite16_32x(u32 a, u32 d)
837 {
838   if ((a & 0xffc0) == 0x5100) { // a15100
839     u16 *r = Pico32x.regs;
840
841     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
842     a &= 0x3e;
843     if (a == 0) {
844       if ((d ^ r[0]) & d & P32XS_ADEN) {
845         Pico32xStartup();
846         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
847         r[0] |= P32XS_ADEN;
848         p32x_reg_write16(a, d); // forward for reset processing
849       }
850       return;
851     }
852
853     // allow only COMM for now
854     if ((a & 0x30) == 0x20)
855       r[a / 2] = d;
856     return;
857   }
858
859   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
860 }
861
862 // -----------------------------------------------------------------
863
864 // hint vector is writeable
865 static void PicoWrite8_hint(u32 a, u32 d)
866 {
867   if ((a & 0xfffc) == 0x0070) {
868     Pico32xMem->m68k_rom[a ^ 1] = d;
869     return;
870   }
871
872   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
873 }
874
875 static void PicoWrite16_hint(u32 a, u32 d)
876 {
877   if ((a & 0xfffc) == 0x0070) {
878     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
879     return;
880   }
881
882   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
883 }
884
885 static void bank_switch(int b)
886 {
887   unsigned int rs, bank;
888
889   bank = b << 20;
890   if (bank >= Pico.romsize) {
891     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
892     return;
893   }
894
895   // 32X ROM (unbanked, XXX: consider mirroring?)
896   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
897   rs -= bank;
898   if (rs > 0x100000)
899     rs = 0x100000;
900   cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
901   cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
902
903   elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
904
905 #ifdef EMU_F68K
906   // setup FAME fetchmap
907   for (rs = 0x90; rs < 0xa0; rs++)
908     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom + bank - 0x900000;
909 #endif
910 }
911
912 // -----------------------------------------------------------------
913 //                              SH2  
914 // -----------------------------------------------------------------
915
916 // read8
917 static u32 sh2_read8_unmapped(u32 a, int id)
918 {
919   elprintf(EL_UIO, "%csh2 unmapped r8  [%08x]       %02x @%06x",
920     id ? 's' : 'm', a, 0, sh2_pc(id));
921   return 0;
922 }
923
924 static u32 sh2_read8_cs0(u32 a, int id)
925 {
926   u32 d = 0;
927
928   // 0x3ff00 is veridied
929   if ((a & 0x3ff00) == 0x4000) {
930     d = p32x_sh2reg_read16(a, id);
931     goto out_16to8;
932   }
933
934   if ((a & 0x3ff00) == 0x4100) {
935     d = p32x_vdp_read16(a);
936     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
937       ash2_end_run(8);
938     goto out_16to8;
939   }
940
941   // TODO: mirroring?
942   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
943     return Pico32xMem->sh2_rom_m[a ^ 1];
944   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
945     return Pico32xMem->sh2_rom_s[a ^ 1];
946
947   if ((a & 0x3ff00) == 0x4200) {
948     d = Pico32xMem->pal[(a & 0x1ff) / 2];
949     goto out_16to8;
950   }
951
952   return sh2_read8_unmapped(a, id);
953
954 out_16to8:
955   if (a & 1)
956     d &= 0xff;
957   else
958     d >>= 8;
959
960   elprintf(EL_32X, "%csh2 r8  [%08x]       %02x @%06x",
961     id ? 's' : 'm', a, d, sh2_pc(id));
962   return d;
963 }
964
965 static u32 sh2_read8_da(u32 a, int id)
966 {
967   return Pico32xMem->data_array[id][(a & 0xfff) ^ 1];
968 }
969
970 // read16
971 static u32 sh2_read16_unmapped(u32 a, int id)
972 {
973   elprintf(EL_UIO, "%csh2 unmapped r16 [%08x]     %04x @%06x",
974     id ? 's' : 'm', a, 0, sh2_pc(id));
975   return 0;
976 }
977
978 static u32 sh2_read16_cs0(u32 a, int id)
979 {
980   u32 d = 0;
981
982   if ((a & 0x3ff00) == 0x4000) {
983     d = p32x_sh2reg_read16(a, id);
984     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
985       return d;
986     goto out;
987   }
988
989   if ((a & 0x3ff00) == 0x4100) {
990     d = p32x_vdp_read16(a);
991     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
992       ash2_end_run(8);
993     goto out;
994   }
995
996   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
997     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
998   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
999     return *(u16 *)(Pico32xMem->sh2_rom_s + a);
1000
1001   if ((a & 0x3ff00) == 0x4200) {
1002     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1003     goto out;
1004   }
1005
1006   return sh2_read16_unmapped(a, id);
1007
1008 out:
1009   elprintf(EL_32X, "%csh2 r16 [%08x]     %04x @%06x",
1010     id ? 's' : 'm', a, d, sh2_pc(id));
1011   return d;
1012 }
1013
1014 static u32 sh2_read16_da(u32 a, int id)
1015 {
1016   return ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2];
1017 }
1018
1019 static void sh2_write_ignore(u32 a, u32 d, int id)
1020 {
1021 }
1022
1023 // write8
1024 static void sh2_write8_unmapped(u32 a, u32 d, int id)
1025 {
1026   elprintf(EL_UIO, "%csh2 unmapped w8  [%08x]       %02x @%06x",
1027     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1028 }
1029
1030 static void sh2_write8_cs0(u32 a, u32 d, int id)
1031 {
1032   elprintf(EL_32X, "%csh2 w8  [%08x]       %02x @%06x",
1033     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1034
1035   if ((a & 0x3ff00) == 0x4100) {
1036     p32x_vdp_write8(a, d);
1037     return;
1038   }
1039
1040   if ((a & 0x3ff00) == 0x4000) {
1041     p32x_sh2reg_write8(a, d, id);
1042     return;
1043   }
1044
1045   sh2_write8_unmapped(a, d, id);
1046 }
1047
1048 #define sh2_write8_dramN(n) \
1049   if (!(a & 0x20000) || d) { \
1050     u8 *dram = (u8 *)Pico32xMem->dram[n]; \
1051     dram[(a & 0x1ffff) ^ 1] = d; \
1052   }
1053
1054 static void sh2_write8_dram0(u32 a, u32 d, int id)
1055 {
1056   sh2_write8_dramN(0);
1057 }
1058
1059 static void sh2_write8_dram1(u32 a, u32 d, int id)
1060 {
1061   sh2_write8_dramN(1);
1062 }
1063
1064 static void sh2_write8_sdram(u32 a, u32 d, int id)
1065 {
1066   u32 a1 = a & 0x3ffff;
1067 #ifdef DRC_SH2
1068   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1069   if (t)
1070     sh2_drc_wcheck_ram(a, t, id);
1071 #endif
1072   Pico32xMem->sdram[a1 ^ 1] = d;
1073 }
1074
1075 static void sh2_write8_da(u32 a, u32 d, int id)
1076 {
1077   u32 a1 = a & 0xfff;
1078 #ifdef DRC_SH2
1079   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1080   if (t)
1081     sh2_drc_wcheck_da(a, t, id);
1082 #endif
1083   Pico32xMem->data_array[id][a1 ^ 1] = d;
1084 }
1085
1086 // write16
1087 static void sh2_write16_unmapped(u32 a, u32 d, int id)
1088 {
1089   elprintf(EL_UIO, "%csh2 unmapped w16 [%08x]     %04x @%06x",
1090     id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1091 }
1092
1093 static void sh2_write16_cs0(u32 a, u32 d, int id)
1094 {
1095   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1096     elprintf(EL_32X, "%csh2 w16 [%08x]     %04x @%06x",
1097       id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1098
1099   if ((a & 0x3ff00) == 0x4100) {
1100     sh2_poll[id].cnt = 0; // for poll before VDP accesses
1101     p32x_vdp_write16(a, d);
1102     return;
1103   }
1104
1105   if ((a & 0x3fe00) == 0x4200) {
1106     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1107     Pico32x.dirty_pal = 1;
1108     return;
1109   }
1110
1111   if ((a & 0x3ff00) == 0x4000) {
1112     p32x_sh2reg_write16(a, d, id);
1113     return;
1114   }
1115
1116   sh2_write16_unmapped(a, d, id);
1117 }
1118
1119 #define sh2_write16_dramN(n) \
1120   u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
1121   if (!(a & 0x20000)) { \
1122     *pd = d; \
1123     return; \
1124   } \
1125   /* overwrite */ \
1126   if (!(d & 0xff00)) d |= *pd & 0xff00; \
1127   if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
1128   *pd = d
1129
1130 static void sh2_write16_dram0(u32 a, u32 d, int id)
1131 {
1132   sh2_write16_dramN(0);
1133 }
1134
1135 static void sh2_write16_dram1(u32 a, u32 d, int id)
1136 {
1137   sh2_write16_dramN(1);
1138 }
1139
1140 static void sh2_write16_sdram(u32 a, u32 d, int id)
1141 {
1142   u32 a1 = a & 0x3ffff;
1143 #ifdef DRC_SH2
1144   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1145   if (t)
1146     sh2_drc_wcheck_ram(a, t, id);
1147 #endif
1148   ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
1149 }
1150
1151 static void sh2_write16_da(u32 a, u32 d, int id)
1152 {
1153   u32 a1 = a & 0xfff;
1154 #ifdef DRC_SH2
1155   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1156   if (t)
1157     sh2_drc_wcheck_da(a, t, id);
1158 #endif
1159   ((u16 *)Pico32xMem->data_array[id])[a1 / 2] = d;
1160 }
1161
1162
1163 typedef struct {
1164   uptr addr; // stores (membase >> 1) or ((handler >> 1) | (1<<31))
1165   u32 mask;
1166 } sh2_memmap;
1167
1168 typedef u32  (sh2_read_handler)(u32 a, int id);
1169 typedef void (sh2_write_handler)(u32 a, u32 d, int id);
1170
1171 #define SH2MAP_ADDR2OFFS(a) \
1172   (((a >> 25) & 3) | ((a >> 27) & 0x1c))
1173
1174 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1175 {
1176   const sh2_memmap *sh2_map = sh2->read8_map;
1177   uptr p;
1178
1179   sh2_map += SH2MAP_ADDR2OFFS(a);
1180   p = sh2_map->addr;
1181   if (map_flag_set(p))
1182     return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
1183   else
1184     return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
1185 }
1186
1187 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1188 {
1189   const sh2_memmap *sh2_map = sh2->read16_map;
1190   uptr p;
1191
1192   sh2_map += SH2MAP_ADDR2OFFS(a);
1193   p = sh2_map->addr;
1194   if (map_flag_set(p))
1195     return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
1196   else
1197     return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1198 }
1199
1200 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1201 {
1202   const sh2_memmap *sh2_map = sh2->read16_map;
1203   sh2_read_handler *handler;
1204   u32 offs;
1205   uptr p;
1206
1207   offs = SH2MAP_ADDR2OFFS(a);
1208   sh2_map += offs;
1209   p = sh2_map->addr;
1210   if (!map_flag_set(p)) {
1211     // XXX: maybe 32bit access instead with ror?
1212     u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1213     return (pd[0] << 16) | pd[1];
1214   }
1215
1216   if (offs == 0x1f)
1217     return sh2_peripheral_read32(a, sh2->is_slave);
1218
1219   handler = (sh2_read_handler *)(p << 1);
1220   return (handler(a, sh2->is_slave) << 16) | handler(a + 2, sh2->is_slave);
1221 }
1222
1223 void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1224 {
1225   const void **sh2_wmap = sh2->write8_tab;
1226   sh2_write_handler *wh;
1227
1228   wh = sh2_wmap[SH2MAP_ADDR2OFFS(a)];
1229   wh(a, d, sh2->is_slave);
1230 }
1231
1232 void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1233 {
1234   const void **sh2_wmap = sh2->write16_tab;
1235   sh2_write_handler *wh;
1236
1237   wh = sh2_wmap[SH2MAP_ADDR2OFFS(a)];
1238   wh(a, d, sh2->is_slave);
1239 }
1240
1241 void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1242 {
1243   const void **sh2_wmap = sh2->write16_tab;
1244   sh2_write_handler *handler;
1245   u32 offs;
1246
1247   offs = SH2MAP_ADDR2OFFS(a);
1248
1249   if (offs == 0x1f) {
1250     sh2_peripheral_write32(a, d, sh2->is_slave);
1251     return;
1252   }
1253
1254   handler = sh2_wmap[offs];
1255   handler(a, d >> 16, sh2->is_slave);
1256   handler(a + 2, d, sh2->is_slave);
1257 }
1258
1259 // -----------------------------------------------------------------
1260
1261 static const u16 msh2_code[] = {
1262   // trap instructions
1263   0xaffe, // bra <self>
1264   0x0009, // nop
1265   // have to wait a bit until m68k initial program finishes clearing stuff
1266   // to avoid races with game SH2 code, like in Tempo
1267   0xd004, // mov.l   @(_m_ok,pc), r0
1268   0xd105, // mov.l   @(_cnt,pc), r1
1269   0xd205, // mov.l   @(_start,pc), r2
1270   0x71ff, // add     #-1, r1
1271   0x4115, // cmp/pl  r1
1272   0x89fc, // bt      -2
1273   0xc208, // mov.l   r0, @(h'20,gbr)
1274   0x6822, // mov.l   @r2, r8
1275   0x482b, // jmp     @r8
1276   0x0009, // nop
1277   ('M'<<8)|'_', ('O'<<8)|'K',
1278   0x0001, 0x0000,
1279   0x2200, 0x03e0  // master start pointer in ROM
1280 };
1281
1282 static const u16 ssh2_code[] = {
1283   0xaffe, // bra <self>
1284   0x0009, // nop
1285   // code to wait for master, in case authentic master BIOS is used
1286   0xd104, // mov.l   @(_m_ok,pc), r1
1287   0xd206, // mov.l   @(_start,pc), r2
1288   0xc608, // mov.l   @(h'20,gbr), r0
1289   0x3100, // cmp/eq  r0, r1
1290   0x8bfc, // bf      #-2
1291   0xd003, // mov.l   @(_s_ok,pc), r0
1292   0xc209, // mov.l   r0, @(h'24,gbr)
1293   0x6822, // mov.l   @r2, r8
1294   0x482b, // jmp     @r8
1295   0x0009, // nop
1296   ('M'<<8)|'_', ('O'<<8)|'K',
1297   ('S'<<8)|'_', ('O'<<8)|'K',
1298   0x2200, 0x03e4  // slave start pointer in ROM
1299 };
1300
1301 #define HWSWAP(x) (((x) << 16) | ((x) >> 16))
1302 static void get_bios(void)
1303 {
1304   u16 *ps;
1305   u32 *pl;
1306   int i;
1307
1308   // M68K ROM
1309   if (p32x_bios_g != NULL) {
1310     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1311     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, 0x100);
1312   }
1313   else {
1314     // generate 68k ROM
1315     ps = (u16 *)Pico32xMem->m68k_rom;
1316     pl = (u32 *)ps;
1317     for (i = 1; i < 0xc0/4; i++)
1318       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1319
1320     // fill with nops
1321     for (i = 0xc0/2; i < 0x100/2; i++)
1322       ps[i] = 0x4e71;
1323
1324 #if 0
1325     ps[0xc0/2] = 0x46fc;
1326     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1327     ps[0xfe/2] = 0x60fe; // jump to self
1328 #else
1329     ps[0xfe/2] = 0x4e75; // rts
1330 #endif
1331   }
1332   // fill remaining m68k_rom page with game ROM
1333   memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
1334
1335   // MSH2
1336   if (p32x_bios_m != NULL) {
1337     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1338     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1339   }
1340   else {
1341     pl = (u32 *)Pico32xMem->sh2_rom_m;
1342
1343     // fill exception vector table to our trap address
1344     for (i = 0; i < 128; i++)
1345       pl[i] = HWSWAP(0x200);
1346
1347     // startup code
1348     memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
1349
1350     // reset SP
1351     pl[1] = pl[3] = HWSWAP(0x6040000);
1352     // start
1353     pl[0] = pl[2] = HWSWAP(0x204);
1354   }
1355
1356   // SSH2
1357   if (p32x_bios_s != NULL) {
1358     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1359     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1360   }
1361   else {
1362     pl = (u32 *)Pico32xMem->sh2_rom_s;
1363
1364     // fill exception vector table to our trap address
1365     for (i = 0; i < 128; i++)
1366       pl[i] = HWSWAP(0x200);
1367
1368     // startup code
1369     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1370
1371     // reset SP
1372     pl[1] = pl[3] = HWSWAP(0x603f800);
1373     // start
1374     pl[0] = pl[2] = HWSWAP(0x204);
1375   }
1376 }
1377
1378 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
1379 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
1380
1381 static sh2_memmap sh2_read8_map[0x20], sh2_read16_map[0x20];
1382 // for writes we are using handlers only
1383 static void *sh2_write8_map[0x20], *sh2_write16_map[0x20];
1384
1385 void Pico32xSwapDRAM(int b)
1386 {
1387   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1388   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1389   cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1390   cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1391
1392   // SH2
1393   sh2_read8_map[2].addr   = sh2_read8_map[6].addr   =
1394   sh2_read16_map[2].addr  = sh2_read16_map[6].addr  = MAP_MEMORY(Pico32xMem->dram[b]);
1395
1396   sh2_write8_map[2]  = sh2_write8_map[6]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
1397   sh2_write16_map[2] = sh2_write16_map[6] = b ? sh2_write16_dram1 : sh2_write16_dram0;
1398 }
1399
1400 void PicoMemSetup32x(void)
1401 {
1402   unsigned int rs;
1403   int i;
1404
1405   Pico32xMem = calloc(1, sizeof(*Pico32xMem));
1406   if (Pico32xMem == NULL) {
1407     elprintf(EL_STATUS, "OOM");
1408     return;
1409   }
1410
1411   dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
1412
1413   get_bios();
1414
1415   // cartridge area becomes unmapped
1416   // XXX: we take the easy way and don't unmap ROM,
1417   // so that we can avoid handling the RV bit.
1418   // m68k_map_unmap(0x000000, 0x3fffff);
1419
1420   // MD ROM area
1421   rs = sizeof(Pico32xMem->m68k_rom);
1422   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1423   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1424   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1425   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1426
1427   // 32X ROM (unbanked, XXX: consider mirroring?)
1428   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1429   if (rs > 0x80000)
1430     rs = 0x80000;
1431   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1432   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1433 #ifdef EMU_F68K
1434   // setup FAME fetchmap
1435   PicoCpuFM68k.Fetch[0] = (u32)Pico32xMem->m68k_rom;
1436   for (rs = 0x88; rs < 0x90; rs++)
1437     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom - 0x880000;
1438 #endif
1439
1440   // 32X ROM (banked)
1441   bank_switch(0);
1442
1443   // SYS regs
1444   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1445   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1446   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1447   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1448
1449   // SH2 maps: A31,A30,A29,CS1,CS0
1450   // all unmapped by default
1451   for (i = 0; i < 0x20; i++) {
1452     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
1453     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
1454     sh2_write8_map[i]       = sh2_write8_unmapped;
1455     sh2_write16_map[i]      = sh2_write16_unmapped;
1456   }
1457
1458   // "purge area"
1459   for (i = 0x08; i <= 0x0b; i++) {
1460     sh2_write8_map[i]       =
1461     sh2_write16_map[i]      = sh2_write_ignore;
1462   }
1463
1464   // CS0
1465   sh2_read8_map[0].addr   = sh2_read8_map[4].addr   = MAP_HANDLER(sh2_read8_cs0);
1466   sh2_read16_map[0].addr  = sh2_read16_map[4].addr  = MAP_HANDLER(sh2_read16_cs0);
1467   sh2_write8_map[0]       = sh2_write8_map[4]       = sh2_write8_cs0;
1468   sh2_write16_map[0]      = sh2_write16_map[4]      = sh2_write16_cs0;
1469   // CS1 - ROM
1470   sh2_read8_map[1].addr   = sh2_read8_map[5].addr   =
1471   sh2_read16_map[1].addr  = sh2_read16_map[5].addr  = MAP_MEMORY(Pico.rom);
1472   sh2_read8_map[1].mask   = sh2_read8_map[5].mask   =
1473   sh2_read16_map[1].mask  = sh2_read16_map[5].mask  = 0x3fffff; // FIXME
1474   // CS2 - DRAM - done by Pico32xSwapDRAM()
1475   sh2_read8_map[2].mask   = sh2_read8_map[6].mask   =
1476   sh2_read16_map[2].mask  = sh2_read16_map[6].mask  = 0x01ffff;
1477   // CS3 - SDRAM
1478   sh2_read8_map[3].addr   = sh2_read8_map[7].addr   =
1479   sh2_read16_map[3].addr  = sh2_read16_map[7].addr  = MAP_MEMORY(Pico32xMem->sdram);
1480   sh2_write8_map[3]       = sh2_write8_map[7]       = sh2_write8_sdram;
1481   sh2_write16_map[3]      = sh2_write16_map[7]      = sh2_write16_sdram;
1482   sh2_read8_map[3].mask   = sh2_read8_map[7].mask   =
1483   sh2_read16_map[3].mask  = sh2_read16_map[7].mask  = 0x03ffff;
1484   // SH2 data array
1485   sh2_read8_map[0x18].addr   = MAP_HANDLER(sh2_read8_da);
1486   sh2_read16_map[0x18].addr  = MAP_HANDLER(sh2_read16_da);
1487   sh2_write8_map[0x18]       = sh2_write8_da;
1488   sh2_write16_map[0x18]      = sh2_write16_da;
1489   // SH2 IO
1490   sh2_read8_map[0x1f].addr   = MAP_HANDLER(sh2_peripheral_read8);
1491   sh2_read16_map[0x1f].addr  = MAP_HANDLER(sh2_peripheral_read16);
1492   sh2_write8_map[0x1f]       = sh2_peripheral_write8;
1493   sh2_write16_map[0x1f]      = sh2_peripheral_write16;
1494
1495   // map DRAM area, both 68k and SH2
1496   Pico32xSwapDRAM(1);
1497
1498   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
1499   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
1500   msh2.write8_tab  = ssh2.write8_tab  = (const void **)sh2_write8_map;
1501   msh2.write16_tab = ssh2.write16_tab = (const void **)sh2_write16_map;
1502
1503   // setup poll detector
1504   m68k_poll.flag = P32XF_68KPOLL;
1505   m68k_poll.cyc_max = 64;
1506   sh2_poll[0].flag = P32XF_MSH2POLL;
1507   sh2_poll[0].cyc_max = 21;
1508   sh2_poll[1].flag = P32XF_SSH2POLL;
1509   sh2_poll[1].cyc_max = 16;
1510 }
1511
1512 // vim:shiftwidth=2:expandtab