42fea930d7e50aa8523719f720622814de69798b
[picodrive.git] / pico / cd / sek.c
1 /*
2  * PicoDrive
3  * (C) notaz, 2007
4  *
5  * This work is licensed under the terms of MAME license.
6  * See COPYING file in the top-level directory.
7  */
8
9 #include "../pico_int.h"
10
11
12 unsigned int SekCycleCntS68k;
13 unsigned int SekCycleAimS68k;
14
15
16 /* context */
17 // Cyclone 68000
18 #ifdef EMU_C68K
19 struct Cyclone PicoCpuCS68k;
20 #endif
21 // MUSASHI 68000
22 #ifdef EMU_M68K
23 m68ki_cpu_core PicoCpuMS68k;
24 #endif
25 // FAME 68000
26 #ifdef EMU_F68K
27 M68K_CONTEXT PicoCpuFS68k;
28 #endif
29
30
31 static int new_irq_level(int level)
32 {
33   int level_new = 0, irqs;
34   Pico_mcd->m.s68k_pend_ints &= ~(1 << level);
35   irqs = Pico_mcd->m.s68k_pend_ints;
36   irqs &= Pico_mcd->s68k_regs[0x33];
37   while ((irqs >>= 1)) level_new++;
38
39   return level_new;
40 }
41
42 #ifdef EMU_C68K
43 // interrupt acknowledgement
44 static int SekIntAckS68k(int level)
45 {
46   int level_new = new_irq_level(level);
47
48   elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new);
49   PicoCpuCS68k.irq = level_new;
50   return CYCLONE_INT_ACK_AUTOVECTOR;
51 }
52
53 static void SekResetAckS68k(void)
54 {
55   elprintf(EL_ANOMALY, "s68k: Reset encountered @ %06x", SekPcS68k);
56 }
57
58 static int SekUnrecognizedOpcodeS68k(void)
59 {
60   elprintf(EL_ANOMALY, "Unrecognized Opcode @ %06x", SekPcS68k);
61   //exit(1);
62   return 0;
63 }
64 #endif
65
66 #ifdef EMU_M68K
67 static int SekIntAckMS68k(int level)
68 {
69 #ifndef EMU_CORE_DEBUG
70   int level_new = new_irq_level(level);
71   elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new);
72   CPU_INT_LEVEL = level_new << 8;
73 #else
74   CPU_INT_LEVEL = 0;
75 #endif
76   return M68K_INT_ACK_AUTOVECTOR;
77 }
78 #endif
79
80 #ifdef EMU_F68K
81 static void SekIntAckFS68k(unsigned level)
82 {
83   int level_new = new_irq_level(level);
84   elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new);
85 #ifndef EMU_CORE_DEBUG
86   PicoCpuFS68k.interrupts[0] = level_new;
87 #else
88   {
89     extern int dbg_irq_level_sub;
90     dbg_irq_level_sub = level_new;
91     PicoCpuFS68k.interrupts[0] = 0;
92   }
93 #endif
94 }
95 #endif
96
97
98 PICO_INTERNAL void SekInitS68k(void)
99 {
100 #ifdef EMU_C68K
101 //  CycloneInit();
102   memset(&PicoCpuCS68k,0,sizeof(PicoCpuCS68k));
103   PicoCpuCS68k.IrqCallback=SekIntAckS68k;
104   PicoCpuCS68k.ResetCallback=SekResetAckS68k;
105   PicoCpuCS68k.UnrecognizedCallback=SekUnrecognizedOpcodeS68k;
106 #endif
107 #ifdef EMU_M68K
108   {
109     // Musashi is not very context friendly..
110     void *oldcontext = m68ki_cpu_p;
111     m68k_set_context(&PicoCpuMS68k);
112     m68k_set_cpu_type(M68K_CPU_TYPE_68000);
113     m68k_init();
114     m68k_set_int_ack_callback(SekIntAckMS68k);
115 //  m68k_pulse_reset(); // not yet, memmap is not set up
116     m68k_set_context(oldcontext);
117   }
118 #endif
119 #ifdef EMU_F68K
120   {
121     void *oldcontext = g_m68kcontext;
122     g_m68kcontext = &PicoCpuFS68k;
123     memset(&PicoCpuFS68k, 0, sizeof(PicoCpuFS68k));
124     fm68k_init();
125     PicoCpuFS68k.iack_handler = SekIntAckFS68k;
126     PicoCpuFS68k.sr = 0x2704; // Z flag
127     g_m68kcontext = oldcontext;
128   }
129 #endif
130 }
131
132 // Reset the 68000:
133 PICO_INTERNAL int SekResetS68k(void)
134 {
135   if (Pico.rom==NULL) return 1;
136
137 #ifdef EMU_C68K
138   CycloneReset(&PicoCpuCS68k);
139 #endif
140 #ifdef EMU_M68K
141   {
142     void *oldcontext = m68ki_cpu_p;
143
144     m68k_set_context(&PicoCpuMS68k);
145     m68ki_cpu.sp[0]=0;
146     m68k_set_irq(0);
147     m68k_pulse_reset();
148     m68k_set_context(oldcontext);
149   }
150 #endif
151 #ifdef EMU_F68K
152   {
153     void *oldcontext = g_m68kcontext;
154     g_m68kcontext = &PicoCpuFS68k;
155     fm68k_reset();
156     g_m68kcontext = oldcontext;
157   }
158 #endif
159
160   return 0;
161 }
162
163 PICO_INTERNAL int SekInterruptS68k(int irq)
164 {
165   int irqs, real_irq = 1;
166   Pico_mcd->m.s68k_pend_ints |= 1 << irq;
167   irqs = Pico_mcd->m.s68k_pend_ints >> 1;
168   while ((irqs >>= 1)) real_irq++;
169
170 #ifdef EMU_CORE_DEBUG
171   {
172     extern int dbg_irq_level_sub;
173     dbg_irq_level_sub=real_irq;
174     return 0;
175   }
176 #endif
177 #ifdef EMU_C68K
178   PicoCpuCS68k.irq=real_irq;
179 #endif
180 #ifdef EMU_M68K
181   // avoid m68k_set_irq() for delaying to work
182   PicoCpuMS68k.int_level = real_irq << 8;
183 #endif
184 #ifdef EMU_F68K
185   PicoCpuFS68k.interrupts[0]=real_irq;
186 #endif
187   return 0;
188 }
189
190 void SekInterruptClearS68k(int irq)
191 {
192   int level_new = new_irq_level(irq);
193
194 #ifdef EMU_C68K
195   PicoCpuCS68k.irq = level_new;
196 #endif
197 #ifdef EMU_M68K
198   CPU_INT_LEVEL = level_new << 8;
199 #endif
200 #ifdef EMU_F68K
201   PicoCpuFS68k.interrupts[0] = level_new;
202 #endif
203 }