famec: split fm68k_emulate
[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     fm68k_reset(&PicoCpuFS68k);
155     g_m68kcontext = oldcontext;
156   }
157 #endif
158
159   return 0;
160 }
161
162 PICO_INTERNAL int SekInterruptS68k(int irq)
163 {
164   int irqs, real_irq = 1;
165   Pico_mcd->m.s68k_pend_ints |= 1 << irq;
166   irqs = Pico_mcd->m.s68k_pend_ints >> 1;
167   while ((irqs >>= 1)) real_irq++;
168
169 #ifdef EMU_CORE_DEBUG
170   {
171     extern int dbg_irq_level_sub;
172     dbg_irq_level_sub=real_irq;
173     return 0;
174   }
175 #endif
176 #ifdef EMU_C68K
177   PicoCpuCS68k.irq=real_irq;
178 #endif
179 #ifdef EMU_M68K
180   // avoid m68k_set_irq() for delaying to work
181   PicoCpuMS68k.int_level = real_irq << 8;
182 #endif
183 #ifdef EMU_F68K
184   PicoCpuFS68k.interrupts[0]=real_irq;
185 #endif
186   return 0;
187 }
188
189 void SekInterruptClearS68k(int irq)
190 {
191   int level_new = new_irq_level(irq);
192
193 #ifdef EMU_C68K
194   PicoCpuCS68k.irq = level_new;
195 #endif
196 #ifdef EMU_M68K
197   CPU_INT_LEVEL = level_new << 8;
198 #endif
199 #ifdef EMU_F68K
200   PicoCpuFS68k.interrupts[0] = level_new;
201 #endif
202 }