9bb7282925e578bc07563636fdbd656071faac4d
[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   if (level == 2) // clear pending bit
36     Pico_mcd->m.state_flags &= ~PCD_ST_S68K_IFL2;
37   irqs = Pico_mcd->m.s68k_pend_ints;
38   irqs &= Pico_mcd->s68k_regs[0x33];
39   while ((irqs >>= 1)) level_new++;
40
41   return level_new;
42 }
43
44 #ifdef EMU_C68K
45 // interrupt acknowledgement
46 static int SekIntAckS68k(int level)
47 {
48   int level_new = new_irq_level(level);
49
50   elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new);
51   PicoCpuCS68k.irq = level_new;
52   return CYCLONE_INT_ACK_AUTOVECTOR;
53 }
54
55 static void SekResetAckS68k(void)
56 {
57   elprintf(EL_ANOMALY, "s68k: Reset encountered @ %06x", SekPcS68k);
58 }
59
60 static int SekUnrecognizedOpcodeS68k(void)
61 {
62   elprintf(EL_ANOMALY, "Unrecognized Opcode @ %06x", SekPcS68k);
63   //exit(1);
64   return 0;
65 }
66 #endif
67
68 #ifdef EMU_M68K
69 static int SekIntAckMS68k(int level)
70 {
71 #ifndef EMU_CORE_DEBUG
72   int level_new = new_irq_level(level);
73   elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new);
74   CPU_INT_LEVEL = level_new << 8;
75 #else
76   CPU_INT_LEVEL = 0;
77 #endif
78   return M68K_INT_ACK_AUTOVECTOR;
79 }
80 #endif
81
82 #ifdef EMU_F68K
83 static void SekIntAckFS68k(unsigned level)
84 {
85   int level_new = new_irq_level(level);
86   elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new);
87 #ifndef EMU_CORE_DEBUG
88   PicoCpuFS68k.interrupts[0] = level_new;
89 #else
90   {
91     extern int dbg_irq_level_sub;
92     dbg_irq_level_sub = level_new;
93     PicoCpuFS68k.interrupts[0] = 0;
94   }
95 #endif
96 }
97 #endif
98
99
100 PICO_INTERNAL void SekInitS68k(void)
101 {
102 #ifdef EMU_C68K
103 //  CycloneInit();
104   memset(&PicoCpuCS68k,0,sizeof(PicoCpuCS68k));
105   PicoCpuCS68k.IrqCallback=SekIntAckS68k;
106   PicoCpuCS68k.ResetCallback=SekResetAckS68k;
107   PicoCpuCS68k.UnrecognizedCallback=SekUnrecognizedOpcodeS68k;
108 #endif
109 #ifdef EMU_M68K
110   {
111     // Musashi is not very context friendly..
112     void *oldcontext = m68ki_cpu_p;
113     m68k_set_context(&PicoCpuMS68k);
114     m68k_set_cpu_type(M68K_CPU_TYPE_68000);
115     m68k_init();
116     m68k_set_int_ack_callback(SekIntAckMS68k);
117 //  m68k_pulse_reset(); // not yet, memmap is not set up
118     m68k_set_context(oldcontext);
119   }
120 #endif
121 #ifdef EMU_F68K
122   memset(&PicoCpuFS68k, 0, sizeof(PicoCpuFS68k));
123   fm68k_init();
124   PicoCpuFS68k.iack_handler = SekIntAckFS68k;
125   PicoCpuFS68k.sr = 0x2704; // Z flag
126 #endif
127 }
128
129 // Reset the 68000:
130 PICO_INTERNAL int SekResetS68k(void)
131 {
132   if (Pico.rom==NULL) return 1;
133
134 #ifdef EMU_C68K
135   CycloneReset(&PicoCpuCS68k);
136 #endif
137 #ifdef EMU_M68K
138   {
139     void *oldcontext = m68ki_cpu_p;
140
141     m68k_set_context(&PicoCpuMS68k);
142     m68ki_cpu.sp[0]=0;
143     m68k_set_irq(0);
144     m68k_pulse_reset();
145     m68k_set_context(oldcontext);
146   }
147 #endif
148 #ifdef EMU_F68K
149   fm68k_reset(&PicoCpuFS68k);
150 #endif
151
152   return 0;
153 }
154
155 PICO_INTERNAL int SekInterruptS68k(int irq)
156 {
157   int irqs, real_irq = 1;
158   Pico_mcd->m.s68k_pend_ints |= 1 << irq;
159   irqs = Pico_mcd->m.s68k_pend_ints >> 1;
160   while ((irqs >>= 1)) real_irq++;
161
162 #ifdef EMU_CORE_DEBUG
163   {
164     extern int dbg_irq_level_sub;
165     dbg_irq_level_sub=real_irq;
166     return 0;
167   }
168 #endif
169 #ifdef EMU_C68K
170   PicoCpuCS68k.irq=real_irq;
171 #endif
172 #ifdef EMU_M68K
173   // avoid m68k_set_irq() for delaying to work
174   PicoCpuMS68k.int_level = real_irq << 8;
175 #endif
176 #ifdef EMU_F68K
177   PicoCpuFS68k.interrupts[0]=real_irq;
178 #endif
179   return 0;
180 }
181
182 void SekInterruptClearS68k(int irq)
183 {
184   int level_new = new_irq_level(irq);
185
186 #ifdef EMU_C68K
187   PicoCpuCS68k.irq = level_new;
188 #endif
189 #ifdef EMU_M68K
190   CPU_INT_LEVEL = level_new << 8;
191 #endif
192 #ifdef EMU_F68K
193   PicoCpuFS68k.interrupts[0] = level_new;
194 #endif
195 }