32x: drc: some constant propagation
[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 0x03: // shift (for pp mode)
345       r[2 / 2] = d & 1;
346       break;
347     case 0x05: // fill len
348       r[4 / 2] = d & 0xff;
349       break;
350     case 0x0b:
351       d &= 1;
352       Pico32x.pending_fb = d;
353       // if we are blanking and FS bit is changing
354       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
355         r[0x0a/2] ^= 1;
356         Pico32xSwapDRAM(d ^ 1);
357         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
358       }
359       break;
360   }
361 }
362
363 static void p32x_vdp_write16(u32 a, u32 d)
364 {
365   a &= 0x0e;
366   if (a == 6) { // fill start
367     Pico32x.vdp_regs[6 / 2] = d;
368     return;
369   }
370   if (a == 8) { // fill data
371     u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
372     int len = Pico32x.vdp_regs[4 / 2] + 1;
373     a = Pico32x.vdp_regs[6 / 2];
374     while (len--) {
375       dram[a] = d;
376       a = (a & 0xff00) | ((a + 1) & 0xff);
377     }
378     Pico32x.vdp_regs[6 / 2] = a;
379     Pico32x.vdp_regs[8 / 2] = d;
380     return;
381   }
382
383   p32x_vdp_write8(a | 1, d);
384 }
385
386 // ------------------------------------------------------------------
387 // SH2 regs
388
389 static u32 p32x_sh2reg_read16(u32 a, int cpuid)
390 {
391   u16 *r = Pico32x.regs;
392   a &= 0xfe; // ?
393
394   switch (a) {
395     case 0x00: // adapter/irq ctl
396       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[cpuid];
397     case 0x04: // H count (often as comm too)
398       if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
399         ash2_end_run(8);
400       return Pico32x.sh2_regs[4 / 2];
401     case 0x10: // DREQ len
402       return r[a / 2];
403   }
404
405   // DREQ src, dst
406   if ((a & 0x38) == 0x08)
407     return r[a / 2];
408   // comm port
409   if ((a & 0x30) == 0x20) {
410     if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
411       ash2_end_run(8);
412     return r[a / 2];
413   }
414   if ((a & 0x30) == 0x30) {
415     sh2_poll[cpuid].cnt = 0;
416     return p32x_pwm_read16(a);
417   }
418
419   return 0;
420 }
421
422 static void p32x_sh2reg_write8(u32 a, u32 d, int cpuid)
423 {
424   a &= 0xff;
425   switch (a) {
426     case 0: // FM
427       Pico32x.regs[0] &= ~P32XS_FM;
428       Pico32x.regs[0] |= (d << 8) & P32XS_FM;
429       return;
430     case 1: // 
431       Pico32x.sh2irq_mask[cpuid] = d & 0x8f;
432       Pico32x.sh2_regs[0] &= ~0x80;
433       Pico32x.sh2_regs[0] |= d & 0x80;
434       p32x_update_irls();
435       return;
436     case 5: // H count
437       Pico32x.sh2_regs[4 / 2] = d & 0xff;
438       p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
439       return;
440   }
441
442   if ((a & 0x30) == 0x20) {
443     u8 *r8 = (u8 *)Pico32x.regs;
444     r8[a ^ 1] = d;
445     if (p32x_poll_undetect(&m68k_poll, 0))
446       SekSetStop(0);
447     p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
448     return;
449   }
450 }
451
452 static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid)
453 {
454   a &= 0xfe;
455
456   // comm
457   if ((a & 0x30) == 0x20 && Pico32x.regs[a/2] != d) {
458     Pico32x.regs[a / 2] = d;
459     if (p32x_poll_undetect(&m68k_poll, 0))
460       SekSetStop(0);
461     p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
462     return;
463   }
464   // PWM
465   else if ((a & 0x30) == 0x30) {
466     p32x_pwm_write16(a, d);
467     return;
468   }
469
470   switch (a) {
471     case 0: // FM
472       Pico32x.regs[0] &= ~P32XS_FM;
473       Pico32x.regs[0] |= d & P32XS_FM;
474       break;
475     case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls;
476     case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls;
477     case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls;
478     case 0x1a: Pico32x.sh2irqi[cpuid] &= ~P32XI_CMD; goto irls;
479     case 0x1c:
480       Pico32x.sh2irqs &= ~P32XI_PWM;
481       p32x_timers_do(0);
482       goto irls;
483   }
484
485   p32x_sh2reg_write8(a | 1, d, cpuid);
486   return;
487
488 irls:
489   p32x_update_irls();
490 }
491
492 // ------------------------------------------------------------------
493 // SH2 internal peripherals
494 // we keep them in little endian format
495 static u32 sh2_peripheral_read8(u32 a, int id)
496 {
497   u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
498   u32 d;
499
500   a &= 0x1ff;
501   d = PREG8(r, a);
502
503   elprintf(EL_32X, "%csh2 peri r8  [%08x]       %02x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
504   return d;
505 }
506
507 static u32 sh2_peripheral_read16(u32 a, int id)
508 {
509   u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
510   u32 d;
511
512   a &= 0x1ff;
513   d = r[(a / 2) ^ 1];
514
515   elprintf(EL_32X, "%csh2 peri r16 [%08x]     %04x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
516   return d;
517 }
518
519 static u32 sh2_peripheral_read32(u32 a, int id)
520 {
521   u32 d;
522   a &= 0x1fc;
523   d = Pico32xMem->sh2_peri_regs[id][a / 4];
524
525   elprintf(EL_32X, "%csh2 peri r32 [%08x] %08x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
526   return d;
527 }
528
529 static int REGPARM(3) sh2_peripheral_write8(u32 a, u32 d, int id)
530 {
531   u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
532   elprintf(EL_32X, "%csh2 peri w8  [%08x]       %02x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
533
534   a &= 0x1ff;
535   PREG8(r, a) = d;
536
537   // X-men SCI hack
538   if ((a == 2 &&  (d & 0x20)) || // transmiter enabled
539       (a == 4 && !(d & 0x80))) { // valid data in TDR
540     void *oregs = Pico32xMem->sh2_peri_regs[id ^ 1];
541     if ((PREG8(oregs, 2) & 0x50) == 0x50) { // receiver + irq enabled
542       int level = PREG8(oregs, 0x60) >> 4;
543       int vector = PREG8(oregs, 0x63) & 0x7f;
544       elprintf(EL_32X, "%csh2 SCI recv irq (%d, %d)", (id ^ 1) ? 's' : 'm', level, vector);
545       sh2_internal_irq(&sh2s[id ^ 1], level, vector);
546       return 1;
547     }
548   }
549   return 0;
550 }
551
552 static int REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, int id)
553 {
554   u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
555   elprintf(EL_32X, "%csh2 peri w16 [%08x]     %04x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
556
557   a &= 0x1ff;
558
559   // evil WDT
560   if (a == 0x80) {
561     if ((d & 0xff00) == 0xa500) { // WTCSR
562       PREG8(r, 0x80) = d;
563       p32x_timers_recalc();
564     }
565     if ((d & 0xff00) == 0x5a00) // WTCNT
566       PREG8(r, 0x81) = d;
567     return 0;
568   }
569
570   r[(a / 2) ^ 1] = d;
571   return 0;
572 }
573
574 static void sh2_peripheral_write32(u32 a, u32 d, int id)
575 {
576   u32 *r = Pico32xMem->sh2_peri_regs[id];
577   elprintf(EL_32X, "%csh2 peri w32 [%08x] %08x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
578
579   a &= 0x1fc;
580   r[a / 4] = d;
581
582   switch (a) {
583     // division unit (TODO: verify):
584     case 0x104: // DVDNT: divident L, starts divide
585       elprintf(EL_32X, "%csh2 divide %08x / %08x", id ? 's' : 'm', d, r[0x100 / 4]);
586       if (r[0x100 / 4]) {
587         signed int divisor = r[0x100 / 4];
588                        r[0x118 / 4] = r[0x110 / 4] = (signed int)d % divisor;
589         r[0x104 / 4] = r[0x11c / 4] = r[0x114 / 4] = (signed int)d / divisor;
590       }
591       else
592         r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
593       break;
594     case 0x114:
595       elprintf(EL_32X, "%csh2 divide %08x%08x / %08x @%08x",
596         id ? 's' : 'm', r[0x110 / 4], d, r[0x100 / 4], sh2_pc(id));
597       if (r[0x100 / 4]) {
598         signed long long divident = (signed long long)r[0x110 / 4] << 32 | d;
599         signed int divisor = r[0x100 / 4];
600         // XXX: undocumented mirroring to 0x118,0x11c?
601         r[0x118 / 4] = r[0x110 / 4] = divident % divisor;
602         divident /= divisor;
603         r[0x11c / 4] = r[0x114 / 4] = divident;
604         divident >>= 31;
605         if ((unsigned long long)divident + 1 > 1) {
606           //elprintf(EL_32X, "%csh2 divide overflow! @%08x", id ? 's' : 'm', sh2_pc(id));
607           r[0x11c / 4] = r[0x114 / 4] = divident > 0 ? 0x7fffffff : 0x80000000; // overflow
608         }
609       }
610       else
611         r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
612       break;
613   }
614
615   if ((a == 0x1b0 || a == 0x18c) && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1)) {
616     elprintf(EL_32X, "sh2 DMA %08x -> %08x, cnt %d, chcr %04x @%06x",
617       dmac0->sar0, dmac0->dar0, dmac0->tcr0, dmac0->chcr0, sh2_pc(id));
618     dmac0->tcr0 &= 0xffffff;
619
620     // HACK: assume 68k starts writing soon and end the timeslice
621     ash2_end_run(16);
622
623     // DREQ is only sent after first 4 words are written.
624     // we do multiple of 4 words to avoid messing up alignment
625     if (dmac0->sar0 == 0x20004012 && Pico32x.dmac_ptr && (Pico32x.dmac_ptr & 3) == 0) {
626       elprintf(EL_32X, "68k -> sh2 DMA");
627       dma_68k2sh2_do();
628     }
629   }
630 }
631
632 // ------------------------------------------------------------------
633 // 32x handlers
634
635 // after ADEN
636 static u32 PicoRead8_32x_on(u32 a)
637 {
638   u32 d = 0;
639   if ((a & 0xffc0) == 0x5100) { // a15100
640     d = p32x_reg_read16(a);
641     goto out_16to8;
642   }
643
644   if ((a & 0xfc00) != 0x5000)
645     return PicoRead8_io(a);
646
647   if ((a & 0xfff0) == 0x5180) { // a15180
648     d = p32x_vdp_read16(a);
649     goto out_16to8;
650   }
651
652   if ((a & 0xfe00) == 0x5200) { // a15200
653     d = Pico32xMem->pal[(a & 0x1ff) / 2];
654     goto out_16to8;
655   }
656
657   if ((a & 0xfffc) == 0x30ec) { // a130ec
658     d = str_mars[a & 3];
659     goto out;
660   }
661
662   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
663   return d;
664
665 out_16to8:
666   if (a & 1)
667     d &= 0xff;
668   else
669     d >>= 8;
670
671 out:
672   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
673   return d;
674 }
675
676 static u32 PicoRead16_32x_on(u32 a)
677 {
678   u32 d = 0;
679   if ((a & 0xffc0) == 0x5100) { // a15100
680     d = p32x_reg_read16(a);
681     goto out;
682   }
683
684   if ((a & 0xfc00) != 0x5000)
685     return PicoRead16_io(a);
686
687   if ((a & 0xfff0) == 0x5180) { // a15180
688     d = p32x_vdp_read16(a);
689     goto out;
690   }
691
692   if ((a & 0xfe00) == 0x5200) { // a15200
693     d = Pico32xMem->pal[(a & 0x1ff) / 2];
694     goto out;
695   }
696
697   if ((a & 0xfffc) == 0x30ec) { // a130ec
698     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
699     goto out;
700   }
701
702   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
703   return d;
704
705 out:
706   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
707   return d;
708 }
709
710 static void PicoWrite8_32x_on(u32 a, u32 d)
711 {
712   if ((a & 0xfc00) == 0x5000)
713     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
714
715   if ((a & 0xffc0) == 0x5100) { // a15100
716     p32x_reg_write8(a, d);
717     return;
718   }
719
720   if ((a & 0xfc00) != 0x5000) {
721     PicoWrite8_io(a, d);
722     return;
723   }
724
725   if ((a & 0xfff0) == 0x5180) { // a15180
726     p32x_vdp_write8(a, d);
727     return;
728   }
729
730   // TODO: verify
731   if ((a & 0xfe00) == 0x5200) { // a15200
732     elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
733     ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
734     Pico32x.dirty_pal = 1;
735     return;
736   }
737
738   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
739 }
740
741 static void PicoWrite16_32x_on(u32 a, u32 d)
742 {
743   if ((a & 0xfc00) == 0x5000)
744     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
745
746   if ((a & 0xffc0) == 0x5100) { // a15100
747     p32x_reg_write16(a, d);
748     return;
749   }
750
751   if ((a & 0xfc00) != 0x5000) {
752     PicoWrite16_io(a, d);
753     return;
754   }
755
756   if ((a & 0xfff0) == 0x5180) { // a15180
757     p32x_vdp_write16(a, d);
758     return;
759   }
760
761   if ((a & 0xfe00) == 0x5200) { // a15200
762     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
763     Pico32x.dirty_pal = 1;
764     return;
765   }
766
767   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
768 }
769
770 // before ADEN
771 u32 PicoRead8_32x(u32 a)
772 {
773   u32 d = 0;
774   if ((a & 0xffc0) == 0x5100) { // a15100
775     // regs are always readable
776     d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
777     goto out;
778   }
779
780   if ((a & 0xfffc) == 0x30ec) { // a130ec
781     d = str_mars[a & 3];
782     goto out;
783   }
784
785   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
786   return d;
787
788 out:
789   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
790   return d;
791 }
792
793 u32 PicoRead16_32x(u32 a)
794 {
795   u32 d = 0;
796   if ((a & 0xffc0) == 0x5100) { // a15100
797     d = Pico32x.regs[(a & 0x3f) / 2];
798     goto out;
799   }
800
801   if ((a & 0xfffc) == 0x30ec) { // a130ec
802     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
803     goto out;
804   }
805
806   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
807   return d;
808
809 out:
810   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
811   return d;
812 }
813
814 void PicoWrite8_32x(u32 a, u32 d)
815 {
816   if ((a & 0xffc0) == 0x5100) { // a15100
817     u16 *r = Pico32x.regs;
818
819     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
820     a &= 0x3f;
821     if (a == 1) {
822       if ((d ^ r[0]) & d & P32XS_ADEN) {
823         Pico32xStartup();
824         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
825         r[0] |= P32XS_ADEN;
826         p32x_reg_write8(a, d); // forward for reset processing
827       }
828       return;
829     }
830
831     // allow only COMM for now
832     if ((a & 0x30) == 0x20) {
833       u8 *r8 = (u8 *)r;
834       r8[a ^ 1] = d;
835     }
836     return;
837   }
838
839   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
840 }
841
842 void PicoWrite16_32x(u32 a, u32 d)
843 {
844   if ((a & 0xffc0) == 0x5100) { // a15100
845     u16 *r = Pico32x.regs;
846
847     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
848     a &= 0x3e;
849     if (a == 0) {
850       if ((d ^ r[0]) & d & P32XS_ADEN) {
851         Pico32xStartup();
852         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
853         r[0] |= P32XS_ADEN;
854         p32x_reg_write16(a, d); // forward for reset processing
855       }
856       return;
857     }
858
859     // allow only COMM for now
860     if ((a & 0x30) == 0x20)
861       r[a / 2] = d;
862     return;
863   }
864
865   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
866 }
867
868 // -----------------------------------------------------------------
869
870 // hint vector is writeable
871 static void PicoWrite8_hint(u32 a, u32 d)
872 {
873   if ((a & 0xfffc) == 0x0070) {
874     Pico32xMem->m68k_rom[a ^ 1] = d;
875     return;
876   }
877
878   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
879 }
880
881 static void PicoWrite16_hint(u32 a, u32 d)
882 {
883   if ((a & 0xfffc) == 0x0070) {
884     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
885     return;
886   }
887
888   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
889 }
890
891 static void bank_switch(int b)
892 {
893   unsigned int rs, bank;
894
895   bank = b << 20;
896   if (bank >= Pico.romsize) {
897     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
898     return;
899   }
900
901   // 32X ROM (unbanked, XXX: consider mirroring?)
902   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
903   rs -= bank;
904   if (rs > 0x100000)
905     rs = 0x100000;
906   cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
907   cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
908
909   elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
910
911 #ifdef EMU_F68K
912   // setup FAME fetchmap
913   for (rs = 0x90; rs < 0xa0; rs++)
914     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom + bank - 0x900000;
915 #endif
916 }
917
918 // -----------------------------------------------------------------
919 //                              SH2  
920 // -----------------------------------------------------------------
921
922 // read8
923 static u32 sh2_read8_unmapped(u32 a, int id)
924 {
925   elprintf(EL_UIO, "%csh2 unmapped r8  [%08x]       %02x @%06x",
926     id ? 's' : 'm', a, 0, sh2_pc(id));
927   return 0;
928 }
929
930 static u32 sh2_read8_cs0(u32 a, int id)
931 {
932   u32 d = 0;
933
934   // 0x3ff00 is veridied
935   if ((a & 0x3ff00) == 0x4000) {
936     d = p32x_sh2reg_read16(a, id);
937     goto out_16to8;
938   }
939
940   if ((a & 0x3ff00) == 0x4100) {
941     d = p32x_vdp_read16(a);
942     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
943       ash2_end_run(8);
944     goto out_16to8;
945   }
946
947   // TODO: mirroring?
948   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
949     return Pico32xMem->sh2_rom_m[a ^ 1];
950   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
951     return Pico32xMem->sh2_rom_s[a ^ 1];
952
953   if ((a & 0x3ff00) == 0x4200) {
954     d = Pico32xMem->pal[(a & 0x1ff) / 2];
955     goto out_16to8;
956   }
957
958   return sh2_read8_unmapped(a, id);
959
960 out_16to8:
961   if (a & 1)
962     d &= 0xff;
963   else
964     d >>= 8;
965
966   elprintf(EL_32X, "%csh2 r8  [%08x]       %02x @%06x",
967     id ? 's' : 'm', a, d, sh2_pc(id));
968   return d;
969 }
970
971 static u32 sh2_read8_da(u32 a, int id)
972 {
973   return Pico32xMem->data_array[id][(a & 0xfff) ^ 1];
974 }
975
976 // read16
977 static u32 sh2_read16_unmapped(u32 a, int id)
978 {
979   elprintf(EL_UIO, "%csh2 unmapped r16 [%08x]     %04x @%06x",
980     id ? 's' : 'm', a, 0, sh2_pc(id));
981   return 0;
982 }
983
984 static u32 sh2_read16_cs0(u32 a, int id)
985 {
986   u32 d = 0;
987
988   if ((a & 0x3ff00) == 0x4000) {
989     d = p32x_sh2reg_read16(a, id);
990     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
991       return d;
992     goto out;
993   }
994
995   if ((a & 0x3ff00) == 0x4100) {
996     d = p32x_vdp_read16(a);
997     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
998       ash2_end_run(8);
999     goto out;
1000   }
1001
1002   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
1003     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
1004   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
1005     return *(u16 *)(Pico32xMem->sh2_rom_s + a);
1006
1007   if ((a & 0x3ff00) == 0x4200) {
1008     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1009     goto out;
1010   }
1011
1012   return sh2_read16_unmapped(a, id);
1013
1014 out:
1015   elprintf(EL_32X, "%csh2 r16 [%08x]     %04x @%06x",
1016     id ? 's' : 'm', a, d, sh2_pc(id));
1017   return d;
1018 }
1019
1020 static u32 sh2_read16_da(u32 a, int id)
1021 {
1022   return ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2];
1023 }
1024
1025 static int REGPARM(3) sh2_write_ignore(u32 a, u32 d, int id)
1026 {
1027   return 0;
1028 }
1029
1030 // write8
1031 static int REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, int id)
1032 {
1033   elprintf(EL_UIO, "%csh2 unmapped w8  [%08x]       %02x @%06x",
1034     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1035   return 0;
1036 }
1037
1038 static int REGPARM(3) sh2_write8_cs0(u32 a, u32 d, int id)
1039 {
1040   elprintf(EL_32X, "%csh2 w8  [%08x]       %02x @%06x",
1041     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1042
1043   if ((a & 0x3ff00) == 0x4100) {
1044     p32x_vdp_write8(a, d);
1045     return 0;
1046   }
1047
1048   if ((a & 0x3ff00) == 0x4000) {
1049     p32x_sh2reg_write8(a, d, id);
1050     return 1;
1051   }
1052
1053   return sh2_write8_unmapped(a, d, id);
1054 }
1055
1056 /* quirk: in both normal and overwrite areas only nonzero values go through */
1057 #define sh2_write8_dramN(n) \
1058   if ((d & 0xff) != 0) { \
1059     u8 *dram = (u8 *)Pico32xMem->dram[n]; \
1060     dram[(a & 0x1ffff) ^ 1] = d; \
1061   } \
1062   return 0;
1063
1064 static int REGPARM(3) sh2_write8_dram0(u32 a, u32 d, int id)
1065 {
1066   sh2_write8_dramN(0);
1067 }
1068
1069 static int REGPARM(3) sh2_write8_dram1(u32 a, u32 d, int id)
1070 {
1071   sh2_write8_dramN(1);
1072 }
1073
1074 static int REGPARM(3) sh2_write8_sdram(u32 a, u32 d, int id)
1075 {
1076   u32 a1 = a & 0x3ffff;
1077 #ifdef DRC_SH2
1078   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1079   if (t)
1080     sh2_drc_wcheck_ram(a, t, id);
1081 #endif
1082   Pico32xMem->sdram[a1 ^ 1] = d;
1083   return 0;
1084 }
1085
1086 static int REGPARM(3) sh2_write8_da(u32 a, u32 d, int id)
1087 {
1088   u32 a1 = a & 0xfff;
1089 #ifdef DRC_SH2
1090   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1091   if (t)
1092     sh2_drc_wcheck_da(a, t, id);
1093 #endif
1094   Pico32xMem->data_array[id][a1 ^ 1] = d;
1095   return 0;
1096 }
1097
1098 // write16
1099 static int REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, int id)
1100 {
1101   elprintf(EL_UIO, "%csh2 unmapped w16 [%08x]     %04x @%06x",
1102     id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1103   return 0;
1104 }
1105
1106 static int REGPARM(3) sh2_write16_cs0(u32 a, u32 d, int id)
1107 {
1108   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1109     elprintf(EL_32X, "%csh2 w16 [%08x]     %04x @%06x",
1110       id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1111
1112   if ((a & 0x3ff00) == 0x4100) {
1113     sh2_poll[id].cnt = 0; // for poll before VDP accesses
1114     p32x_vdp_write16(a, d);
1115     return 0;
1116   }
1117
1118   if ((a & 0x3fe00) == 0x4200) {
1119     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1120     Pico32x.dirty_pal = 1;
1121     return 0;
1122   }
1123
1124   if ((a & 0x3ff00) == 0x4000) {
1125     p32x_sh2reg_write16(a, d, id);
1126     return 1;
1127   }
1128
1129   return sh2_write16_unmapped(a, d, id);
1130 }
1131
1132 #define sh2_write16_dramN(n) \
1133   u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
1134   if (!(a & 0x20000)) { \
1135     *pd = d; \
1136     return 0; \
1137   } \
1138   /* overwrite */ \
1139   if (!(d & 0xff00)) d |= *pd & 0xff00; \
1140   if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
1141   *pd = d; \
1142   return 0
1143
1144 static int REGPARM(3) sh2_write16_dram0(u32 a, u32 d, int id)
1145 {
1146   sh2_write16_dramN(0);
1147 }
1148
1149 static int REGPARM(3) sh2_write16_dram1(u32 a, u32 d, int id)
1150 {
1151   sh2_write16_dramN(1);
1152 }
1153
1154 static int REGPARM(3) sh2_write16_sdram(u32 a, u32 d, int id)
1155 {
1156   u32 a1 = a & 0x3ffff;
1157 #ifdef DRC_SH2
1158   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1159   if (t)
1160     sh2_drc_wcheck_ram(a, t, id);
1161 #endif
1162   ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
1163   return 0;
1164 }
1165
1166 static int REGPARM(3) sh2_write16_da(u32 a, u32 d, int id)
1167 {
1168   u32 a1 = a & 0xfff;
1169 #ifdef DRC_SH2
1170   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1171   if (t)
1172     sh2_drc_wcheck_da(a, t, id);
1173 #endif
1174   ((u16 *)Pico32xMem->data_array[id])[a1 / 2] = d;
1175   return 0;
1176 }
1177
1178
1179 typedef struct {
1180   uptr addr; // stores (membase >> 1) or ((handler >> 1) | (1<<31))
1181   u32 mask;
1182 } sh2_memmap;
1183
1184 typedef u32 (sh2_read_handler)(u32 a, int id);
1185 typedef int REGPARM(3) (sh2_write_handler)(u32 a, u32 d, int id);
1186
1187 #define SH2MAP_ADDR2OFFS_R(a) \
1188   ((((a) >> 25) & 3) | (((a) >> 27) & 0x1c))
1189
1190 #define SH2MAP_ADDR2OFFS_W(a) \
1191   ((u32)(a) >> SH2_WRITE_SHIFT)
1192
1193 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1194 {
1195   const sh2_memmap *sh2_map = sh2->read8_map;
1196   uptr p;
1197
1198   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1199   p = sh2_map->addr;
1200   if (map_flag_set(p))
1201     return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
1202   else
1203     return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
1204 }
1205
1206 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1207 {
1208   const sh2_memmap *sh2_map = sh2->read16_map;
1209   uptr p;
1210
1211   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1212   p = sh2_map->addr;
1213   if (map_flag_set(p))
1214     return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
1215   else
1216     return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1217 }
1218
1219 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1220 {
1221   const sh2_memmap *sh2_map = sh2->read16_map;
1222   sh2_read_handler *handler;
1223   u32 offs;
1224   uptr p;
1225
1226   offs = SH2MAP_ADDR2OFFS_R(a);
1227   sh2_map += offs;
1228   p = sh2_map->addr;
1229   if (!map_flag_set(p)) {
1230     // XXX: maybe 32bit access instead with ror?
1231     u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1232     return (pd[0] << 16) | pd[1];
1233   }
1234
1235   if (offs == 0x1f)
1236     return sh2_peripheral_read32(a, sh2->is_slave);
1237
1238   handler = (sh2_read_handler *)(p << 1);
1239   return (handler(a, sh2->is_slave) << 16) | handler(a + 2, sh2->is_slave);
1240 }
1241
1242 // return nonzero if write potentially causes an interrupt (used by drc)
1243 int REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1244 {
1245   const void **sh2_wmap = sh2->write8_tab;
1246   sh2_write_handler *wh;
1247
1248   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1249   return wh(a, d, sh2->is_slave);
1250 }
1251
1252 int REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1253 {
1254   const void **sh2_wmap = sh2->write16_tab;
1255   sh2_write_handler *wh;
1256
1257   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1258   return wh(a, d, sh2->is_slave);
1259 }
1260
1261 int REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1262 {
1263   const void **sh2_wmap = sh2->write16_tab;
1264   sh2_write_handler *handler;
1265   u32 offs;
1266
1267   offs = SH2MAP_ADDR2OFFS_W(a);
1268
1269   if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
1270     sh2_peripheral_write32(a, d, sh2->is_slave);
1271     return 0;
1272   }
1273
1274   handler = sh2_wmap[offs];
1275   handler(a, d >> 16, sh2->is_slave);
1276   handler(a + 2, d, sh2->is_slave);
1277   return 0;
1278 }
1279
1280 // -----------------------------------------------------------------
1281
1282 static const u16 msh2_code[] = {
1283   // trap instructions
1284   0xaffe, // bra <self>
1285   0x0009, // nop
1286   // have to wait a bit until m68k initial program finishes clearing stuff
1287   // to avoid races with game SH2 code, like in Tempo
1288   0xd004, // mov.l   @(_m_ok,pc), r0
1289   0xd105, // mov.l   @(_cnt,pc), r1
1290   0xd205, // mov.l   @(_start,pc), r2
1291   0x71ff, // add     #-1, r1
1292   0x4115, // cmp/pl  r1
1293   0x89fc, // bt      -2
1294   0xc208, // mov.l   r0, @(h'20,gbr)
1295   0x6822, // mov.l   @r2, r8
1296   0x482b, // jmp     @r8
1297   0x0009, // nop
1298   ('M'<<8)|'_', ('O'<<8)|'K',
1299   0x0001, 0x0000,
1300   0x2200, 0x03e0  // master start pointer in ROM
1301 };
1302
1303 static const u16 ssh2_code[] = {
1304   0xaffe, // bra <self>
1305   0x0009, // nop
1306   // code to wait for master, in case authentic master BIOS is used
1307   0xd104, // mov.l   @(_m_ok,pc), r1
1308   0xd206, // mov.l   @(_start,pc), r2
1309   0xc608, // mov.l   @(h'20,gbr), r0
1310   0x3100, // cmp/eq  r0, r1
1311   0x8bfc, // bf      #-2
1312   0xd003, // mov.l   @(_s_ok,pc), r0
1313   0xc209, // mov.l   r0, @(h'24,gbr)
1314   0x6822, // mov.l   @r2, r8
1315   0x482b, // jmp     @r8
1316   0x0009, // nop
1317   ('M'<<8)|'_', ('O'<<8)|'K',
1318   ('S'<<8)|'_', ('O'<<8)|'K',
1319   0x2200, 0x03e4  // slave start pointer in ROM
1320 };
1321
1322 #define HWSWAP(x) (((x) << 16) | ((x) >> 16))
1323 static void get_bios(void)
1324 {
1325   u16 *ps;
1326   u32 *pl;
1327   int i;
1328
1329   // M68K ROM
1330   if (p32x_bios_g != NULL) {
1331     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1332     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, 0x100);
1333   }
1334   else {
1335     // generate 68k ROM
1336     ps = (u16 *)Pico32xMem->m68k_rom;
1337     pl = (u32 *)ps;
1338     for (i = 1; i < 0xc0/4; i++)
1339       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1340
1341     // fill with nops
1342     for (i = 0xc0/2; i < 0x100/2; i++)
1343       ps[i] = 0x4e71;
1344
1345 #if 0
1346     ps[0xc0/2] = 0x46fc;
1347     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1348     ps[0xfe/2] = 0x60fe; // jump to self
1349 #else
1350     ps[0xfe/2] = 0x4e75; // rts
1351 #endif
1352   }
1353   // fill remaining m68k_rom page with game ROM
1354   memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
1355
1356   // MSH2
1357   if (p32x_bios_m != NULL) {
1358     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1359     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1360   }
1361   else {
1362     pl = (u32 *)Pico32xMem->sh2_rom_m;
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_m + 0x200, msh2_code, sizeof(msh2_code));
1370
1371     // reset SP
1372     pl[1] = pl[3] = HWSWAP(0x6040000);
1373     // start
1374     pl[0] = pl[2] = HWSWAP(0x204);
1375   }
1376
1377   // SSH2
1378   if (p32x_bios_s != NULL) {
1379     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1380     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1381   }
1382   else {
1383     pl = (u32 *)Pico32xMem->sh2_rom_s;
1384
1385     // fill exception vector table to our trap address
1386     for (i = 0; i < 128; i++)
1387       pl[i] = HWSWAP(0x200);
1388
1389     // startup code
1390     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1391
1392     // reset SP
1393     pl[1] = pl[3] = HWSWAP(0x603f800);
1394     // start
1395     pl[0] = pl[2] = HWSWAP(0x204);
1396   }
1397 }
1398
1399 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
1400 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
1401
1402 static sh2_memmap sh2_read8_map[0x20], sh2_read16_map[0x20];
1403 // for writes we are using handlers only
1404 static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
1405
1406 void Pico32xSwapDRAM(int b)
1407 {
1408   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1409   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1410   cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1411   cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1412
1413   // SH2
1414   sh2_read8_map[2].addr   = sh2_read8_map[6].addr   =
1415   sh2_read16_map[2].addr  = sh2_read16_map[6].addr  = MAP_MEMORY(Pico32xMem->dram[b]);
1416
1417   sh2_write8_map[0x04/2]  = sh2_write8_map[0x24/2]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
1418   sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
1419 }
1420
1421 void PicoMemSetup32x(void)
1422 {
1423   unsigned int rs;
1424   int i;
1425
1426   Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem));
1427   if (Pico32xMem == NULL) {
1428     elprintf(EL_STATUS, "OOM");
1429     return;
1430   }
1431
1432   dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
1433
1434   get_bios();
1435
1436   // cartridge area becomes unmapped
1437   // XXX: we take the easy way and don't unmap ROM,
1438   // so that we can avoid handling the RV bit.
1439   // m68k_map_unmap(0x000000, 0x3fffff);
1440
1441   // MD ROM area
1442   rs = sizeof(Pico32xMem->m68k_rom);
1443   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1444   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1445   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1446   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1447
1448   // 32X ROM (unbanked, XXX: consider mirroring?)
1449   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1450   if (rs > 0x80000)
1451     rs = 0x80000;
1452   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1453   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1454 #ifdef EMU_F68K
1455   // setup FAME fetchmap
1456   PicoCpuFM68k.Fetch[0] = (u32)Pico32xMem->m68k_rom;
1457   for (rs = 0x88; rs < 0x90; rs++)
1458     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom - 0x880000;
1459 #endif
1460
1461   // 32X ROM (banked)
1462   bank_switch(0);
1463
1464   // SYS regs
1465   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1466   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1467   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1468   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1469
1470   // SH2 maps: A31,A30,A29,CS1,CS0
1471   // all unmapped by default
1472   for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
1473     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
1474     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
1475   }
1476
1477   for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
1478     sh2_write8_map[i]       = sh2_write8_unmapped;
1479     sh2_write16_map[i]      = sh2_write16_unmapped;
1480   }
1481
1482   // "purge area"
1483   for (i = 0x40; i <= 0x5f; i++) {
1484     sh2_write8_map[i >> 1]  =
1485     sh2_write16_map[i >> 1] = sh2_write_ignore;
1486   }
1487
1488   // CS0
1489   sh2_read8_map[0].addr   = sh2_read8_map[4].addr   = MAP_HANDLER(sh2_read8_cs0);
1490   sh2_read16_map[0].addr  = sh2_read16_map[4].addr  = MAP_HANDLER(sh2_read16_cs0);
1491   sh2_write8_map[0x00/2]  = sh2_write8_map[0x20/2]  = sh2_write8_cs0;
1492   sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
1493   // CS1 - ROM
1494   sh2_read8_map[1].addr   = sh2_read8_map[5].addr   =
1495   sh2_read16_map[1].addr  = sh2_read16_map[5].addr  = MAP_MEMORY(Pico.rom);
1496   sh2_read8_map[1].mask   = sh2_read8_map[5].mask   =
1497   sh2_read16_map[1].mask  = sh2_read16_map[5].mask  = 0x3fffff; // FIXME
1498   // CS2 - DRAM - done by Pico32xSwapDRAM()
1499   sh2_read8_map[2].mask   = sh2_read8_map[6].mask   =
1500   sh2_read16_map[2].mask  = sh2_read16_map[6].mask  = 0x01ffff;
1501   // CS3 - SDRAM
1502   sh2_read8_map[3].addr   = sh2_read8_map[7].addr   =
1503   sh2_read16_map[3].addr  = sh2_read16_map[7].addr  = MAP_MEMORY(Pico32xMem->sdram);
1504   sh2_write8_map[0x06/2]  = sh2_write8_map[0x26/2]  = sh2_write8_sdram;
1505   sh2_write16_map[0x06/2] = sh2_write16_map[0x26/2] = sh2_write16_sdram;
1506   sh2_read8_map[3].mask   = sh2_read8_map[7].mask   =
1507   sh2_read16_map[3].mask  = sh2_read16_map[7].mask  = 0x03ffff;
1508   // SH2 data array
1509   sh2_read8_map[0x18].addr   = MAP_HANDLER(sh2_read8_da);
1510   sh2_read16_map[0x18].addr  = MAP_HANDLER(sh2_read16_da);
1511   sh2_write8_map[0xc0/2]     = sh2_write8_da;
1512   sh2_write16_map[0xc0/2]    = sh2_write16_da;
1513   // SH2 IO
1514   sh2_read8_map[0x1f].addr   = MAP_HANDLER(sh2_peripheral_read8);
1515   sh2_read16_map[0x1f].addr  = MAP_HANDLER(sh2_peripheral_read16);
1516   sh2_write8_map[0xff/2]     = sh2_peripheral_write8;
1517   sh2_write16_map[0xff/2]    = sh2_peripheral_write16;
1518
1519   // map DRAM area, both 68k and SH2
1520   Pico32xSwapDRAM(1);
1521
1522   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
1523   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
1524   msh2.write8_tab  = ssh2.write8_tab  = (const void **)(void *)sh2_write8_map;
1525   msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
1526
1527   // setup poll detector
1528   m68k_poll.flag = P32XF_68KPOLL;
1529   m68k_poll.cyc_max = 64;
1530   sh2_poll[0].flag = P32XF_MSH2POLL;
1531   sh2_poll[0].cyc_max = 21;
1532   sh2_poll[1].flag = P32XF_SSH2POLL;
1533   sh2_poll[1].cyc_max = 16;
1534
1535 #ifdef DRC_SH2
1536   sh2_drc_mem_setup(&msh2);
1537   sh2_drc_mem_setup(&ssh2);
1538 #endif
1539 }
1540
1541 // vim:shiftwidth=2:expandtab