1 /***************************************************************************
2
3 cpuintrf.c
4
5 Don't you love MS-DOS 8+3 names? That stands for CPU interface.
6 Functions needed to interface the CPU emulator with the other parts of
7 the emulation.
8
9 ***************************************************************************/
10
11 /*#include <signal.h>*/
12 #include "driver.h"
13 #include "timer.h"
14 #include "state.h"
15 #include "hiscore.h"
16
17 #ifdef WANT_LIBCO
18 extern int libco_quit;
19 #endif
20
21 #if (HAS_Z80)
22 #include "cpu/z80/z80.h"
23 #endif
24 #if (HAS_DRZ80)
25 #include "cpu/z80_drz80/drz80_z80.h"
26 #endif
27 #if (HAS_Z80GB)
28 #include "cpu/z80gb/z80gb.h"
29 #endif
30 #if (HAS_8080 || HAS_8085A)
31 #include "cpu/i8085/i8085.h"
32 #endif
33 #if (HAS_M6502 || HAS_M65C02 || HAS_M65SC02 || HAS_M6510 || HAS_M6510T || HAS_M7501 || HAS_M8502 || HAS_N2A03)
34 #include "cpu/m6502/m6502.h"
35 #endif
36 #if (HAS_M4510)
37 #include "cpu/m6502/m4510.h"
38 #endif
39 #if (HAS_M65CE02)
40 #include "cpu/m6502/m65ce02.h"
41 #endif
42 #if (HAS_M6509)
43 #include "cpu/m6502/m6509.h"
44 #endif
45 #if (HAS_H6280)
46 #include "cpu/h6280/h6280.h"
47 #endif
48 #if (HAS_I86)
49 #include "cpu/i86/i86intf.h"
50 #endif
51 #if (HAS_I88)
52 #include "cpu/i86/i88intf.h"
53 #endif
54 #if (HAS_I186)
55 #include "cpu/i86/i186intf.h"
56 #endif
57 #if (HAS_I188)
58 #include "cpu/i86/i188intf.h"
59 #endif
60 #if (HAS_I286)
61 #include "cpu/i86/i286intf.h"
62 #endif
63 #if (HAS_V20 || HAS_V30 || HAS_V33)
64 #include "cpu/nec/necintrf.h"
65 #endif
66 #if (HAS_ARMNEC)
67 #include "cpu/nec_armnec/armnecintrf.h"
68 #endif
69 #if (HAS_I8035 || HAS_I8039 || HAS_I8048 || HAS_N7751)
70 #include "cpu/i8039/i8039.h"
71 #endif
72 #if (HAS_M6800 || HAS_M6801 || HAS_M6802 || HAS_M6803 || HAS_M6808 || HAS_HD63701)
73 #include "cpu/m6800/m6800.h"
74 #endif
75 #if (HAS_M6805 || HAS_M68705 || HAS_HD63705)
76 #include "cpu/m6805/m6805.h"
77 #endif
78 #if (HAS_HD6309 || HAS_M6809)
79 #include "cpu/m6809/m6809.h"
80 #endif
81 #if (HAS_KONAMI)
82 #include "cpu/konami/konami.h"
83 #endif
84 #if (HAS_M68000 || defined HAS_M68010 || HAS_M68020 || HAS_M68EC020)
85 #include "cpu/m68000/m68000.h"
86 #endif
87 #if (HAS_CYCLONE)
88 #include "cpu/m68000_cyclone/c68000.h"
89 #endif
90 #if (HAS_T11)
91 #include "cpu/t11/t11.h"
92 #endif
93 #if (HAS_S2650)
94 #include "cpu/s2650/s2650.h"
95 #endif
96 #if (HAS_TMS34010)
97 #include "cpu/tms34010/tms34010.h"
98 #endif
99 #if (HAS_TMS9900) || (HAS_TMS9940) || (HAS_TMS9980) || (HAS_TMS9985) \
100 || (HAS_TMS9989) || (HAS_TMS9995) || (HAS_TMS99105A) || (HAS_TMS99110A)
101 #include "cpu/tms9900/tms9900.h"
102 #endif
103 #if (HAS_Z8000)
104 #include "cpu/z8000/z8000.h"
105 #endif
106 #if (HAS_TMS320C10)
107 #include "cpu/tms32010/tms32010.h"
108 #endif
109 #if (HAS_CCPU)
110 #include "cpu/ccpu/ccpu.h"
111 #endif
112 #if (HAS_PDP1)
113 #include "cpu/pdp1/pdp1.h"
114 #endif
115 #if (HAS_ADSP2100) || (HAS_ADSP2105)
116 #include "cpu/adsp2100/adsp2100.h"
117 #endif
118 #if (HAS_MIPS)
119 #include "cpu/mips/mips.h"
120 #endif
121 #if (HAS_SC61860)
122 #include "cpu/sc61860/sc61860.h"
123 #endif
124 #if (HAS_ARM)
125 #include "cpu/arm/arm.h"
126 #endif
127
128
129 /* these are triggers sent to the timer system for various interrupt events */
130 #define TRIGGER_TIMESLICE -1000
131 #define TRIGGER_INT -2000
132 #define TRIGGER_YIELDTIME -3000
133 #define TRIGGER_SUSPENDTIME -4000
134
135 #define VERBOSE 0
136
137 #define SAVE_STATE_TEST 0
138 #if VERBOSE
139 #define LOG(x) logerror x
140 #else
141 #define LOG(x)
142 #endif
143
144 #ifdef _MSC_VER
145 __declspec(align(32))
146 #endif
147 struct cpuinfo
148 {
149 struct cpu_interface *intf; /* pointer to the interface functions */
150 int iloops; /* number of interrupts remaining this frame */
151 int totalcycles; /* total CPU cycles executed */
152 int vblankint_countdown; /* number of vblank callbacks left until we interrupt */
153 int vblankint_multiplier; /* number of vblank callbacks per interrupt */
154 void *vblankint_timer; /* reference to elapsed time counter */
155 timer_tm vblankint_period; /* timing period of the VBLANK interrupt */
156 void *timedint_timer; /* reference to this CPU's timer */
157 timer_tm timedint_period; /* timing period of the timed interrupt */
158 void *context; /* dynamically allocated context buffer */
159 int save_context; /* need to context switch this CPU? yes or no */
160 }
161 #ifndef _MSC_VER
162 __attribute__ ((__aligned__ (32)))
163 #endif
164 ;
165
166 static struct cpuinfo cpu[MAX_CPU];
167
168 static int activecpu,totalcpu;
169 static int cycles_running; /* number of cycles that the CPU emulation was requested to run */
170 /* (needed by cpu_getfcount) */
171 static int have_to_reset;
172
173 static int interrupt_enable[MAX_CPU];
174 static int interrupt_vector[MAX_CPU];
175
176 static int irq_line_state[MAX_CPU * MAX_IRQ_LINES];
177 static int irq_line_vector[MAX_CPU * MAX_IRQ_LINES];
178
179 static int watchdog_counter;
180
181 static void *vblank_timer;
182 static int vblank_countdown;
183 static int vblank_multiplier;
184 static timer_tm vblank_period;
185
186 static void *refresh_timer;
187 static timer_tm refresh_period;
188
189 static void *timeslice_timer;
190 static timer_tm timeslice_period;
191
192 static timer_tm scanline_period;
193
194 static int usres; /* removed from cpu_run and made global */
195 static int vblank;
196 static int current_frame;
197
198 static void cpu_generate_interrupt(int cpunum, int (*func)(void), int num);
199 static void cpu_vblankintcallback(int param);
200 static void cpu_timedintcallback(int param);
201 static void cpu_internal_interrupt(int cpunum, int type);
202 static void cpu_manualnmicallback(int param);
203 static void cpu_manualirqcallback(int param);
204 static void cpu_internalintcallback(int param);
205 static void cpu_manualintcallback(int param);
206 static void cpu_clearintcallback(int param);
207 static void cpu_resetcallback(int param);
208 static void cpu_haltcallback(int param);
209 static void cpu_timeslicecallback(int param);
210 static void cpu_vblankreset(void);
211 static void cpu_vblankcallback(int param);
212 static void cpu_updatecallback(int param);
213 static timer_tm cpu_computerate(int value);
214 static void cpu_inittimers(void);
215
216
217 /* default irq callback handlers */
218 static int cpu_0_irq_callback(int irqline);
219 static int cpu_1_irq_callback(int irqline);
220 static int cpu_2_irq_callback(int irqline);
221 static int cpu_3_irq_callback(int irqline);
222 static int cpu_4_irq_callback(int irqline);
223 static int cpu_5_irq_callback(int irqline);
224 static int cpu_6_irq_callback(int irqline);
225 static int cpu_7_irq_callback(int irqline);
226
227 /* and a list of them for indexed access */
228 static int (*cpu_irq_callbacks[MAX_CPU])(int) = {
229 cpu_0_irq_callback, cpu_1_irq_callback, cpu_2_irq_callback, cpu_3_irq_callback,
230 cpu_4_irq_callback, cpu_5_irq_callback, cpu_6_irq_callback, cpu_7_irq_callback
231 };
232
233 /* and a list of driver interception hooks */
234 static int (*drv_irq_callbacks[MAX_CPU])(int) = { NULL, };
235
236 /* Dummy interfaces for non-CPUs */
237 static void Dummy_reset(void *param);
238 static void Dummy_exit(void);
239 static int Dummy_execute(int cycles);
240 //static void Dummy_burn(int cycles);
241 static unsigned Dummy_get_context(void *regs);
242 static void Dummy_set_context(void *regs);
243 static unsigned Dummy_get_pc(void);
244 static void Dummy_set_pc(unsigned val);
245 static unsigned Dummy_get_sp(void);
246 static void Dummy_set_sp(unsigned val);
247 static unsigned Dummy_get_reg(int regnum);
248 static void Dummy_set_reg(int regnum, unsigned val);
249 static void Dummy_set_nmi_line(int state);
250 static void Dummy_set_irq_line(int irqline, int state);
251 static void Dummy_set_irq_callback(int (*callback)(int irqline));
252 static int Dummy_ICount;
253 static const char *Dummy_info(void *context, int regnum);
254 static unsigned Dummy_dasm(char *buffer, unsigned pc);
255
256 /* Convenience macros - not in cpuintrf.h because they shouldn't be used by everyone */
257 #define RESET(index) ((*cpu[index].intf->reset)(Machine->drv->cpu[index].reset_param))
258 #define EXECUTE(index,cycles) ((*cpu[index].intf->execute)(cycles))
259 #define GETCONTEXT(index,context) ((*cpu[index].intf->get_context)(context))
260 #define SETCONTEXT(index,context) ((*cpu[index].intf->set_context)(context))
261 #define GETCYCLETBL(index,which) ((*cpu[index].intf->get_cycle_table)(which))
262 #define SETCYCLETBL(index,which,cnts) ((*cpu[index].intf->set_cycle_table)(which,cnts))
263 #define GETPC(index) ((*cpu[index].intf->get_pc)())
264 #define SETPC(index,val) ((*cpu[index].intf->set_pc)(val))
265 #define GETSP(index) ((*cpu[index].intf->get_sp)())
266 #define SETSP(index,val) ((*cpu[index].intf->set_sp)(val))
267 #define GETREG(index,regnum) ((*cpu[index].intf->get_reg)(regnum))
268 #define SETREG(index,regnum,value) ((*cpu[index].intf->set_reg)(regnum,value))
269 #define SETNMILINE(index,state) ((*cpu[index].intf->set_nmi_line)(state))
270 #define SETIRQLINE(index,line,state) ((*cpu[index].intf->set_irq_line)(line,state))
271 #define SETIRQCALLBACK(index,callback) ((*cpu[index].intf->set_irq_callback)(callback))
272 #define INTERNAL_INTERRUPT(index,type) if( cpu[index].intf->internal_interrupt ) ((*cpu[index].intf->internal_interrupt)(type))
273 #define CPUINFO(index,context,regnum) ((*cpu[index].intf->cpu_info)(context,regnum))
274 #define CPUDASM(index,buffer,pc) ((*cpu[index].intf->cpu_dasm)(buffer,pc))
275 #define ICOUNT(index) (*cpu[index].intf->icount)
276 #define INT_TYPE_NONE(index) (cpu[index].intf->no_int)
277 #define INT_TYPE_IRQ(index) (cpu[index].intf->irq_int)
278 #define INT_TYPE_NMI(index) (cpu[index].intf->nmi_int)
279 #define READMEM(index,offset) ((*cpu[index].intf->memory_read)(offset))
280 #define WRITEMEM(index,offset,data) ((*cpu[index].intf->memory_write)(offset,data))
281 #define SET_OP_BASE(index,pc) ((*cpu[index].intf->set_op_base)(pc))
282
283 #define CPU_TYPE(index) (Machine->drv->cpu[index].cpu_type & ~CPU_FLAGS_MASK)
284 #define CPU_AUDIO(index) (Machine->drv->cpu[index].cpu_type & CPU_AUDIO_CPU)
285
286 #define IFC_INFO(cpu,context,regnum) ((cpuintf[cpu].cpu_info)(context,regnum))
287
288 /* most CPUs use this macro */
289 #define CPU0(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM) \
290 { \
291 CPU_##cpu, \
292 name##_reset, name##_exit, name##_execute, NULL, \
293 name##_get_context, name##_set_context, NULL, NULL, \
294 name##_get_pc, name##_set_pc, \
295 name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg, \
296 name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback, \
297 NULL,NULL,NULL, name##_info, name##_dasm, \
298 nirq, dirq, &name##_ICount, oc, i0, i1, i2, \
299 cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem, \
300 shift, bits, CPU_IS_##endian, align, maxinst, \
301 ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM \
302 }
303
304 /* CPUs which have _burn, _state_save and _state_load functions */
305 #define CPU1(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM) \
306 { \
307 CPU_##cpu, \
308 name##_reset, name##_exit, name##_execute, \
309 name##_burn, \
310 name##_get_context, name##_set_context, \
311 name##_get_cycle_table, name##_set_cycle_table, \
312 name##_get_pc, name##_set_pc, \
313 name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg, \
314 name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback, \
315 NULL,name##_state_save,name##_state_load, name##_info, name##_dasm, \
316 nirq, dirq, &name##_ICount, oc, i0, i1, i2, \
317 cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem, \
318 shift, bits, CPU_IS_##endian, align, maxinst, \
319 ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM \
320 }
321
322 /* CPUs which have the _internal_interrupt function */
323 #define CPU2(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM) \
324 { \
325 CPU_##cpu, \
326 name##_reset, name##_exit, name##_execute, \
327 NULL, \
328 name##_get_context, name##_set_context, NULL, NULL, \
329 name##_get_pc, name##_set_pc, \
330 name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg, \
331 name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback, \
332 name##_internal_interrupt,NULL,NULL, name##_info, name##_dasm, \
333 nirq, dirq, &name##_ICount, oc, i0, i1, i2, \
334 cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem, \
335 shift, bits, CPU_IS_##endian, align, maxinst, \
336 ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM \
337 } \
338
339 /* alternative CPU0 for ICount refs */
340 #define CPU3(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM) \
341 { \
342 CPU_##cpu, \
343 name##_reset, name##_exit, name##_execute, NULL, \
344 name##_get_context, name##_set_context, NULL, NULL, \
345 name##_get_pc, name##_set_pc, \
346 name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg, \
347 name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback, \
348 NULL,NULL,NULL, name##_info, name##_dasm, \
349 nirq, dirq, NULL, oc, i0, i1, i2, \
350 cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem, \
351 shift, bits, CPU_IS_##endian, align, maxinst, \
352 ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM \
353 }
354
355 /* alternative CPU1 for ICount refs */
356 #define CPU4(cpu,name,nirq,dirq,oc,i0,i1,i2,mem,shift,bits,endian,align,maxinst,MEM) \
357 { \
358 CPU_##cpu, \
359 name##_reset, name##_exit, name##_execute, \
360 name##_burn, \
361 name##_get_context, name##_set_context, \
362 name##_get_cycle_table, name##_set_cycle_table, \
363 name##_get_pc, name##_set_pc, \
364 name##_get_sp, name##_set_sp, name##_get_reg, name##_set_reg, \
365 name##_set_nmi_line, name##_set_irq_line, name##_set_irq_callback, \
366 NULL,name##_state_save,name##_state_load, name##_info, name##_dasm, \
367 nirq, dirq, NULL, oc, i0, i1, i2, \
368 cpu_readmem##mem, cpu_writemem##mem, cpu_setOPbase##mem, \
369 shift, bits, CPU_IS_##endian, align, maxinst, \
370 ABITS1_##MEM, ABITS2_##MEM, ABITS_MIN_##MEM \
371 }
372
373
374
375 /* warning the ordering must match the one of the enum in driver.h! */
376 struct cpu_interface cpuintf[] =
377 {
378 CPU0(DUMMY, Dummy, 1, 0,1.00,0, -1, -1, 16, 0,16,LE,1, 1,16 ),
379 #if (HAS_Z80)
380 CPU1(Z80, z80, 1,255,1.00,Z80_IGNORE_INT, Z80_IRQ_INT, Z80_NMI_INT, 16, 0,16,LE,1, 4,16 ),
381 #endif
382 #if (HAS_DRZ80)
383 CPU4(DRZ80, drz80, 1,255,1.00,DRZ80_IGNORE_INT, DRZ80_IRQ_INT, DRZ80_NMI_INT, 16, 0,16,LE,1, 4,16 ),
384 #endif
385 #if (HAS_Z80GB)
386 CPU0(Z80GB, z80gb, 5,255,1.00,Z80GB_IGNORE_INT, 0, 1, 16, 0,16,LE,1, 4,16 ),
387 #endif
388 #if (HAS_8080)
389 CPU0(8080, i8080, 4,255,1.00,I8080_NONE, I8080_INTR, I8080_TRAP, 16, 0,16,LE,1, 3,16 ),
390 #endif
391 #if (HAS_8085A)
392 CPU0(8085A, i8085, 4,255,1.00,I8085_NONE, I8085_INTR, I8085_TRAP, 16, 0,16,LE,1, 3,16 ),
393 #endif
394 #if (HAS_M6502)
395 CPU0(M6502, m6502, 1, 0,1.00,M6502_INT_NONE, M6502_INT_IRQ, M6502_INT_NMI, 16, 0,16,LE,1, 3,16 ),
396 #endif
397 #if (HAS_M65C02)
398 CPU0(M65C02, m65c02, 1, 0,1.00,M65C02_INT_NONE, M65C02_INT_IRQ, M65C02_INT_NMI, 16, 0,16,LE,1, 3,16 ),
399 #endif
400 #if (HAS_M65SC02)
401 CPU0(M65SC02, m65sc02, 1, 0,1.00,M65SC02_INT_NONE, M65SC02_INT_IRQ,M65SC02_INT_NMI,16, 0,16,LE,1, 3,16 ),
402 #endif
403 #if (HAS_M65CE02)
404 CPU0(M65CE02, m65ce02, 1, 0,1.00,M65CE02_INT_NONE, M65CE02_INT_IRQ,M65CE02_INT_NMI,16, 0,16,LE,1, 3,16 ),
405 #endif
406 #if (HAS_M6509)
407 CPU0(M6509, m6509, 1, 0,1.00,M6509_INT_NONE, M6509_INT_IRQ, M6509_INT_NMI, 20, 0,20,LE,1, 3,20 ),
408 #endif
409 #if (HAS_M6510)
410 CPU0(M6510, m6510, 1, 0,1.00,M6510_INT_NONE, M6510_INT_IRQ, M6510_INT_NMI, 16, 0,16,LE,1, 3,16 ),
411 #endif
412 #if (HAS_M6510T)
413 CPU0(M6510T, m6510t, 1, 0,1.00,M6510T_INT_NONE, M6510T_INT_IRQ, M6510T_INT_NMI, 16, 0,16,LE,1, 3,16 ),
414 #endif
415 #if (HAS_M7501)
416 CPU0(M7501, m7501, 1, 0,1.00,M7501_INT_NONE, M7501_INT_IRQ, M7501_INT_NMI, 16, 0,16,LE,1, 3,16 ),
417 #endif
418 #if (HAS_M8502)
419 CPU0(M8502, m8502, 1, 0,1.00,M8502_INT_NONE, M8502_INT_IRQ, M8502_INT_NMI, 16, 0,16,LE,1, 3,16 ),
420 #endif
421 #if (HAS_N2A03)
422 CPU0(N2A03, n2a03, 1, 0,1.00,N2A03_INT_NONE, N2A03_INT_IRQ, N2A03_INT_NMI, 16, 0,16,LE,1, 3,16 ),
423 #endif
424 #if (HAS_M4510)
425 CPU0(M4510, m4510, 1, 0,1.00,M4510_INT_NONE, M4510_INT_IRQ, M4510_INT_NMI, 20, 0,20,LE,1, 3,20 ),
426 #endif
427 #if (HAS_H6280)
428 CPU0(H6280, h6280, 3, 0,1.00,H6280_INT_NONE, -1, H6280_INT_NMI, 21, 0,21,LE,1, 3,21 ),
429 #endif
430 #if (HAS_I86)
431 CPU0(I86, i86, 1, 0,1.00,I86_INT_NONE, -1000, I86_NMI_INT, 20, 0,20,LE,1, 5,20 ),
432 #endif
433 #if (HAS_I88)
434 CPU0(I88, i88, 1, 0,1.00,I88_INT_NONE, -1000, I88_NMI_INT, 20, 0,20,LE,1, 5,20 ),
435 #endif
436 #if (HAS_I186)
437 CPU0(I186, i186, 1, 0,1.00,I186_INT_NONE, -1000, I186_NMI_INT, 20, 0,20,LE,1, 5,20 ),
438 #endif
439 #if (HAS_I188)
440 CPU0(I188, i188, 1, 0,1.00,I188_INT_NONE, -1000, I188_NMI_INT, 20, 0,20,LE,1, 5,20 ),
441 #endif
442 #if (HAS_I286)
443 CPU0(I286, i286, 1, 0,1.00,I286_INT_NONE, -1000, I286_NMI_INT, 24, 0,24,LE,1, 5,24 ),
444 #endif
445 #if (HAS_V20)
446 CPU0(V20, v20, 1, 0,1.00,NEC_INT_NONE, -1000, NEC_NMI_INT, 20, 0,20,LE,1, 5,20 ),
447 #endif
448 #if (HAS_V30)
449 CPU0(V30, v30, 1, 0,1.00,NEC_INT_NONE, -1000, NEC_NMI_INT, 20, 0,20,LE,1, 5,20 ),
450 #endif
451 #if (HAS_V33)
452 CPU0(V33, v33, 1, 0,1.20,NEC_INT_NONE, -1000, NEC_NMI_INT, 20, 0,20,LE,1, 5,20 ),
453 #endif
454 #if (HAS_ARMNEC)
455 CPU0(ARMV30, armv30, 1, 0,1.00,NEC_INT_NONE, -1000, NEC_NMI_INT, 20, 0,20,LE,1, 5,20 ),
456 CPU0(ARMV33, armv33, 1, 0,1.20,NEC_INT_NONE, -1000, NEC_NMI_INT, 20, 0,20,LE,1, 5,20 ),
457 #endif
458 #if (HAS_I8035)
459 CPU0(I8035, i8035, 1, 0,1.00,I8035_IGNORE_INT, I8035_EXT_INT, -1, 16, 0,16,LE,1, 2,16 ),
460 #endif
461 #if (HAS_I8039)
462 CPU0(I8039, i8039, 1, 0,1.00,I8039_IGNORE_INT, I8039_EXT_INT, -1, 16, 0,16,LE,1, 2,16 ),
463 #endif
464 #if (HAS_I8048)
465 CPU0(I8048, i8048, 1, 0,1.00,I8048_IGNORE_INT, I8048_EXT_INT, -1, 16, 0,16,LE,1, 2,16 ),
466 #endif
467 #if (HAS_N7751)
468 CPU0(N7751, n7751, 1, 0,1.00,N7751_IGNORE_INT, N7751_EXT_INT, -1, 16, 0,16,LE,1, 2,16 ),
469 #endif
470 #if (HAS_M6800)
471 CPU0(M6800, m6800, 1, 0,1.00,M6800_INT_NONE, M6800_INT_IRQ, M6800_INT_NMI, 16, 0,16,BE,1, 4,16 ),
472 #endif
473 #if (HAS_M6801)
474 CPU0(M6801, m6801, 1, 0,1.00,M6801_INT_NONE, M6801_INT_IRQ, M6801_INT_NMI, 16, 0,16,BE,1, 4,16 ),
475 #endif
476 #if (HAS_M6802)
477 CPU0(M6802, m6802, 1, 0,1.00,M6802_INT_NONE, M6802_INT_IRQ, M6802_INT_NMI, 16, 0,16,BE,1, 4,16 ),
478 #endif
479 #if (HAS_M6803)
480 CPU0(M6803, m6803, 1, 0,1.00,M6803_INT_NONE, M6803_INT_IRQ, M6803_INT_NMI, 16, 0,16,BE,1, 4,16 ),
481 #endif
482 #if (HAS_M6808)
483 CPU0(M6808, m6808, 1, 0,1.00,M6808_INT_NONE, M6808_INT_IRQ, M6808_INT_NMI, 16, 0,16,BE,1, 4,16 ),
484 #endif
485 #if (HAS_HD63701)
486 CPU0(HD63701, hd63701, 1, 0,1.00,HD63701_INT_NONE, HD63701_INT_IRQ,HD63701_INT_NMI,16, 0,16,BE,1, 4,16 ),
487 #endif
488 #if (HAS_NSC8105)
489 CPU0(NSC8105, nsc8105, 1, 0,1.00,NSC8105_INT_NONE, NSC8105_INT_IRQ,NSC8105_INT_NMI,16, 0,16,BE,1, 4,16 ),
490 #endif
491 #if (HAS_M6805)
492 CPU0(M6805, m6805, 1, 0,1.00,M6805_INT_NONE, M6805_INT_IRQ, -1, 16, 0,11,BE,1, 3,16 ),
493 #endif
494 #if (HAS_M68705)
495 CPU0(M68705, m68705, 1, 0,1.00,M68705_INT_NONE, M68705_INT_IRQ, -1, 16, 0,11,BE,1, 3,16 ),
496 #endif
497 #if (HAS_HD63705)
498 CPU0(HD63705, hd63705, 8, 0,1.00,HD63705_INT_NONE, HD63705_INT_IRQ,-1, 16, 0,16,BE,1, 3,16 ),
499 #endif
500 #if (HAS_HD6309)
501 CPU0(HD6309, hd6309, 2, 0,1.00,HD6309_INT_NONE, HD6309_INT_IRQ, HD6309_INT_NMI, 16, 0,16,BE,1, 4,16 ),
502 #endif
503 #if (HAS_M6809)
504 CPU0(M6809, m6809, 2, 0,1.00,M6809_INT_NONE, M6809_INT_IRQ, M6809_INT_NMI, 16, 0,16,BE,1, 4,16 ),
505 #endif
506 #if (HAS_KONAMI)
507 CPU0(KONAMI, konami, 2, 0,1.00,KONAMI_INT_NONE, KONAMI_INT_IRQ, KONAMI_INT_NMI, 16, 0,16,BE,1, 4,16 ),
508 #endif
509 #if (HAS_M68000)
510 CPU0(M68000, m68000, 8, -1,1.00,MC68000_INT_NONE, -1, -1, 24bew, 0,24,BE,2,10,24BEW),
511 #endif
512 #if (HAS_CYCLONE)
513 CPU3(CYCLONE, cyclone, 8, -1,1.00,cyclone_INT_NONE, -1, -1, 24bew, 0,24,BE,2,10,24BEW),
514 #endif
515 #if (HAS_M68010)
516 CPU0(M68010, m68010, 8, -1,1.00,MC68010_INT_NONE, -1, -1, 24bew, 0,24,BE,2,10,24BEW),
517 #endif
518 #if (HAS_M68EC020)
519 CPU0(M68EC020, m68ec020, 8, -1,1.00,MC68EC020_INT_NONE,-1, -1, 24bew, 0,24,BE,2,10,24BEW),
520 #endif
521 #if (HAS_M68020)
522 CPU0(M68020, m68020, 8, -1,1.00,MC68020_INT_NONE, -1, -1, 24bew, 0,24,BE,2,10,24BEW),
523 #endif
524 #if (HAS_T11)
525 CPU0(T11, t11, 4, 0,1.00,T11_INT_NONE, -1, -1, 16lew, 0,16,LE,2, 6,16LEW),
526 #endif
527 #if (HAS_S2650)
528 CPU0(S2650, s2650, 2, 0,1.00,S2650_INT_NONE, -1, -1, 16, 0,15,LE,1, 3,16 ),
529 #endif
530 #if (HAS_TMS34010)
531 CPU2(TMS34010, tms34010, 2, 0,1.00,TMS34010_INT_NONE, TMS34010_INT1, -1, 29, 3,29,LE,2,10,29 ),
532 #endif
533 #if (HAS_TMS9900)
534 CPU0(TMS9900, tms9900, 1, 0,1.00,TMS9900_NONE, -1, -1, 16bew, 0,16,BE,2, 6,16BEW),
535 #endif
536 #if (HAS_TMS9940)
537 CPU0(TMS9940, tms9940, 1, 0,1.00,TMS9940_NONE, -1, -1, 16bew, 0,16,BE,2, 6,16BEW),
538 #endif
539 #if (HAS_TMS9980)
540 CPU0(TMS9980, tms9980a, 1, 0,1.00,TMS9980A_NONE, -1, -1, 16, 0,16,BE,1, 6,16 ),
541 #endif
542 #if (HAS_TMS9985)
543 CPU0(TMS9985, tms9985, 1, 0,1.00,TMS9985_NONE, -1, -1, 16, 0,16,BE,1, 6,16 ),
544 #endif
545 #if (HAS_TMS9989)
546 CPU0(TMS9989, tms9989, 1, 0,1.00,TMS9989_NONE, -1, -1, 16, 0,16,BE,1, 6,16 ),
547 #endif
548 #if (HAS_TMS9995)
549 CPU0(TMS9995, tms9995, 1, 0,1.00,TMS9995_NONE, -1, -1, 16, 0,16,BE,1, 6,16 ),
550 #endif
551 #if (HAS_TMS99105A)
552 CPU0(TMS99105A,tms99105a,1, 0,1.00,TMS99105A_NONE, -1, -1, 16bew, 0,16,BE,2, 6,16BEW),
553 #endif
554 #if (HAS_TMS99110A)
555 CPU0(TMS99110A,tms99110a,1, 0,1.00,TMS99110A_NONE, -1, -1, 16bew, 0,16,BE,2, 6,16BEW),
556 #endif
557 #if (HAS_Z8000)
558 CPU0(Z8000, z8000, 2, 0,1.00,Z8000_INT_NONE, Z8000_NVI, Z8000_NMI, 16bew, 0,16,BE,2, 6,16BEW),
559 #endif
560 #if (HAS_TMS320C10)
561 CPU0(TMS320C10,tms320c10,2, 0,1.00,TMS320C10_INT_NONE,-1, -1, 16, -1,16,BE,2, 4,16 ),
562 #endif
563 #if (HAS_CCPU)
564 CPU0(CCPU, ccpu, 2, 0,1.00,0, -1, -1, 16, 0,15,LE,1, 3,16 ),
565 #endif
566 #if (HAS_PDP1)
567 CPU0(PDP1, pdp1, 0, 0,1.00,0, -1, -1, 16, 0,18,LE,1, 3,16 ),
568 #endif
569 #if (HAS_ADSP2100)
570 /* IMO we should rename all *_ICount to *_icount - ie. no mixed case */
571 #define adsp2100_ICount adsp2100_icount
572 CPU0(ADSP2100, adsp2100, 4, 0,1.00,ADSP2100_INT_NONE, -1, -1, 16lew,-1,14,LE,2, 4,16LEW),
573 #endif
574 #if (HAS_ADSP2105)
575 /* IMO we should rename all *_ICount to *_icount - ie. no mixed case */
576 #define adsp2105_ICount adsp2105_icount
577 CPU0(ADSP2105, adsp2105, 4, 0,1.00,ADSP2105_INT_NONE, -1, -1, 16lew,-1,14,LE,2, 4,16LEW),
578 #endif
579 #if (HAS_MIPS)
580 CPU0(MIPS, mips, 8, -1,1.00,MIPS_INT_NONE, MIPS_INT_NONE, MIPS_INT_NONE, 32lew, 0,32,LE,4, 4,32LEW),
581 #endif
582 #if (HAS_SC61860)
583 #define sc61860_ICount sc61860_icount
584 CPU0(SC61860, sc61860, 1, 0,1.00,-1, -1, -1, 16, 0,16,BE,1, 4,16 ),
585 #endif
586 #if (HAS_ARM)
587 CPU0(ARM, arm, 2, 0,1.00,ARM_INT_NONE, ARM_FIRQ, ARM_IRQ, 26lew, 0,26,LE,4, 4,26LEW),
588 #endif
589 };
590
cpu_init(void)591 void cpu_init(void)
592 {
593 int i;
594
595 /* Verify the order of entries in the cpuintf[] array */
596 for( i = 0; i < CPU_COUNT; i++ )
597 {
598 if( cpuintf[i].cpu_num != i )
599 {
600 logerror("CPU #%d [%s] wrong ID %d: check enum CPU_... in src/driver.h!\n", i, cputype_name(i), cpuintf[i].cpu_num);
601 exit(1);
602 }
603 }
604
605 /* hacks for our two custom CPUs */
606 #ifdef HAS_DRZ80
607 cpuintf[CPU_DRZ80].icount = &drz80_ICount;
608 #endif
609
610 #ifdef HAS_CYCLONE
611 cpuintf[CPU_CYCLONE].icount = &cyclone_ICount;
612 #endif
613
614 /* count how many CPUs we have to emulate */
615 totalcpu = 0;
616
617 while (totalcpu < MAX_CPU)
618 {
619 if( CPU_TYPE(totalcpu) == CPU_DUMMY ) break;
620 totalcpu++;
621 }
622
623 /* zap the CPU data structure */
624 memset(cpu, 0, sizeof(cpu));
625
626 /* Set up the interface functions */
627 for (i = 0; i < MAX_CPU; i++)
628 cpu[i].intf = &cpuintf[CPU_TYPE(i)];
629
630 /* reset the timer system */
631 timer_init();
632 timeslice_timer = refresh_timer = vblank_timer = NULL;
633 }
634
cpu_run(void)635 void cpu_run(void)
636 {
637 int i;
638
639 /* determine which CPUs need a context switch */
640 for (i = 0; i < totalcpu; i++)
641 {
642 int j, size;
643
644 /* allocate a context buffer for the CPU */
645 size = GETCONTEXT(i,NULL);
646 if( size == 0 )
647 {
648 /* That can't really be true */
649 logerror("CPU #%d claims to need no context buffer!\n", i);
650 /*raise( SIGABRT );*/
651 }
652
653 cpu[i].context = malloc( size );
654 if( cpu[i].context == NULL )
655 {
656 /* That's really bad :( */
657 logerror("CPU #%d failed to allocate context buffer (%d bytes)!\n", i, size);
658 /*raise( SIGABRT );*/
659 }
660
661 /* Zap the context buffer */
662 memset(cpu[i].context, 0, size );
663
664
665 /* Save if there is another CPU of the same type */
666 cpu[i].save_context = 0;
667
668 for (j = 0; j < totalcpu; j++)
669 if ( i != j && !strcmp(cpunum_core_file(i),cpunum_core_file(j)) )
670 cpu[i].save_context = 1;
671
672 for( j = 0; j < MAX_IRQ_LINES; j++ )
673 {
674 irq_line_state[i * MAX_IRQ_LINES + j] = CLEAR_LINE;
675 irq_line_vector[i * MAX_IRQ_LINES + j] = cpuintf[CPU_TYPE(i)].default_vector;
676 }
677 }
678
679 reset:
680 /* read hi scores information from hiscore.dat */
681 hs_open(Machine->gamedrv->name);
682 hs_init();
683
684 /* initialize the various timers (suspends all CPUs at startup) */
685 cpu_inittimers();
686 watchdog_counter = -1;
687
688 /* reset sound chips */
689 sound_reset();
690
691 /* enable all CPUs (except for audio CPUs if the sound is off) */
692 for (i = 0; i < totalcpu; i++)
693 {
694 if (!CPU_AUDIO(i) || Machine->sample_rate != 0)
695 {
696 timer_suspendcpu(i, 0, SUSPEND_REASON_RESET);
697 }
698 else
699 {
700 timer_suspendcpu(i, 1, SUSPEND_REASON_DISABLE);
701 }
702 }
703
704 have_to_reset = 0;
705 vblank = 0;
706
707 logerror("Machine reset\n");
708
709 /* start with interrupts enabled, so the generic routine will work even if */
710 /* the machine doesn't have an interrupt enable port */
711 for (i = 0;i < MAX_CPU;i++)
712 {
713 interrupt_enable[i] = 1;
714 interrupt_vector[i] = 0xff;
715 /* Reset any driver hooks into the IRQ acknowledge callbacks */
716 drv_irq_callbacks[i] = NULL;
717 }
718
719 /* do this AFTER the above so init_machine() can use cpu_halt() to hold the */
720 /* execution of some CPUs, or disable interrupts */
721 if (Machine->drv->init_machine) (*Machine->drv->init_machine)();
722
723 /* reset each CPU */
724 for (i = 0; i < totalcpu; i++)
725 {
726 /* swap memory contexts and reset */
727 memorycontextswap(i);
728 if (cpu[i].save_context) SETCONTEXT(i, cpu[i].context);
729 activecpu = i;
730 RESET(i);
731
732 /* Set the irq callback for the cpu */
733 SETIRQCALLBACK(i,cpu_irq_callbacks[i]);
734
735
736 /* save the CPU context if necessary */
737 if (cpu[i].save_context) GETCONTEXT (i, cpu[i].context);
738
739 /* reset the total number of cycles */
740 cpu[i].totalcycles = 0;
741 }
742
743 /* reset the globals */
744 cpu_vblankreset();
745 current_frame = 0;
746
747 /* loop until the user quits */
748 usres = 0;
749 while (usres == 0)
750 {
751 int cpunum;
752 #ifdef WANT_LIBCO
753 if(libco_quit==1)usres=1;
754 #endif
755 /* was machine_reset() called? */
756 if (have_to_reset)
757 {
758 #ifdef MESS
759 if (Machine->drv->stop_machine) (*Machine->drv->stop_machine)();
760 #endif
761 goto reset;
762 }
763 profiler_mark(PROFILER_EXTRA);
764
765 #if SAVE_STATE_TEST
766 {
767 if( keyboard_pressed_memory(KEYCODE_S) )
768 {
769 void *s = state_create(Machine->gamedrv->name);
770 if( s )
771 {
772 for( cpunum = 0; cpunum < totalcpu; cpunum++ )
773 {
774 activecpu = cpunum;
775 memorycontextswap(activecpu);
776 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
777 /* make sure any bank switching is reset */
778 SET_OP_BASE(activecpu, GETPC(activecpu));
779 if( cpu[activecpu].intf->cpu_state_save )
780 (*cpu[activecpu].intf->cpu_state_save)(s);
781 }
782 state_close(s);
783 }
784 }
785
786 if( keyboard_pressed_memory(KEYCODE_L) )
787 {
788 void *s = state_open(Machine->gamedrv->name);
789 if( s )
790 {
791 for( cpunum = 0; cpunum < totalcpu; cpunum++ )
792 {
793 activecpu = cpunum;
794 memorycontextswap(activecpu);
795 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
796 /* make sure any bank switching is reset */
797 SET_OP_BASE(activecpu, GETPC(activecpu));
798 if( cpu[activecpu].intf->cpu_state_load )
799 (*cpu[activecpu].intf->cpu_state_load)(s);
800 /* update the contexts */
801 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
802 }
803 state_close(s);
804 }
805 }
806 }
807 #endif
808 /* ask the timer system to schedule */
809 if (timer_schedule_cpu(&cpunum, &cycles_running))
810 {
811 int ran;
812
813
814 /* switch memory and CPU contexts */
815 activecpu = cpunum;
816 memorycontextswap(activecpu);
817 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
818
819 /* make sure any bank switching is reset */
820 SET_OP_BASE(activecpu, GETPC(activecpu));
821
822 /* run for the requested number of cycles */
823 profiler_mark(PROFILER_CPU1 + cpunum);
824 ran = EXECUTE(activecpu, cycles_running);
825 profiler_mark(PROFILER_END);
826
827 /* update based on how many cycles we really ran */
828 cpu[activecpu].totalcycles += ran;
829
830 /* update the contexts */
831 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
832 activecpu = -1;
833
834 /* update the timer with how long we actually ran */
835 timer_update_cpu(cpunum, ran);
836 }
837
838 profiler_mark(PROFILER_END);
839 }
840
841 /* write hi scores to disk - No scores saving if cheat */
842 hs_close();
843
844 #ifdef MESS
845 if (Machine->drv->stop_machine) (*Machine->drv->stop_machine)();
846 #endif
847
848 /* shut down the CPU cores */
849 for (i = 0; i < totalcpu; i++)
850 {
851 /* if the CPU core defines an exit function, call it now */
852 if( cpu[i].intf->exit )
853 (*cpu[i].intf->exit)();
854
855 /* free the context buffer for that CPU */
856 if( cpu[i].context )
857 {
858 free( cpu[i].context );
859 cpu[i].context = NULL;
860 }
861 }
862 totalcpu = 0;
863 #ifdef WANT_LIBCO
864 libco_quit=1;
865 #endif
866 }
867
868
869
870
871 /***************************************************************************
872
873 Use this function to initialize, and later maintain, the watchdog. For
874 convenience, when the machine is reset, the watchdog is disabled. If you
875 call this function, the watchdog is initialized, and from that point
876 onwards, if you don't call it at least once every 2 seconds, the machine
877 will be reset.
878
879 The 2 seconds delay is targeted at dondokod, which during boot stays more
880 than 1 second without resetting the watchdog.
881
882 ***************************************************************************/
WRITE_HANDLER(watchdog_reset_w)883 WRITE_HANDLER( watchdog_reset_w )
884 {
885 if (watchdog_counter == -1) logerror("watchdog armed\n");
886 watchdog_counter = 2*Machine->drv->frames_per_second;
887 }
888
READ_HANDLER(watchdog_reset_r)889 READ_HANDLER( watchdog_reset_r )
890 {
891 if (watchdog_counter == -1) logerror("watchdog armed\n");
892 watchdog_counter = 2*Machine->drv->frames_per_second;
893 return 0;
894 }
895
896
897
898 /***************************************************************************
899
900 This function resets the machine (the reset will not take place
901 immediately, it will be performed at the end of the active CPU's time
902 slice)
903
904 ***************************************************************************/
machine_reset(void)905 void machine_reset(void)
906 {
907 /* write hi scores to disk - No scores saving if cheat */
908 hs_close();
909
910 have_to_reset = 1;
911 }
912
913
914
915 /***************************************************************************
916
917 Use this function to reset a specified CPU immediately
918
919 ***************************************************************************/
cpu_set_reset_line(int cpunum,int state)920 void cpu_set_reset_line(int cpunum,int state)
921 {
922 timer_set(TIME_NOW, (cpunum & 7) | (state << 3), cpu_resetcallback);
923 }
924
925
926 /***************************************************************************
927
928 Use this function to control the HALT line on a CPU
929
930 ***************************************************************************/
cpu_set_halt_line(int cpunum,int state)931 void cpu_set_halt_line(int cpunum,int state)
932 {
933 timer_set(TIME_NOW, (cpunum & 7) | (state << 3), cpu_haltcallback);
934 }
935
936
937 /***************************************************************************
938
939 Use this function to install a callback for IRQ acknowledge
940
941 ***************************************************************************/
cpu_set_irq_callback(int cpunum,int (* callback)(int))942 void cpu_set_irq_callback(int cpunum, int (*callback)(int))
943 {
944 drv_irq_callbacks[cpunum] = callback;
945 }
946
947
948 /***************************************************************************
949
950 This function returns CPUNUM current status (running or halted)
951
952 ***************************************************************************/
cpu_getstatus(int cpunum)953 int cpu_getstatus(int cpunum)
954 {
955 if (cpunum >= MAX_CPU) return 0;
956
957 return !timer_iscpususpended(cpunum,
958 SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE);
959 }
960
961
962
cpu_getactivecpu(void)963 int cpu_getactivecpu(void)
964 {
965 return (activecpu < 0) ? 0 : activecpu;
966 }
967
cpu_setactivecpu(int cpunum)968 void cpu_setactivecpu(int cpunum)
969 {
970 activecpu = cpunum;
971 }
972
cpu_gettotalcpu(void)973 int cpu_gettotalcpu(void)
974 {
975 return totalcpu;
976 }
977
978
979
cpu_get_pc(void)980 unsigned cpu_get_pc(void)
981 {
982 int cpunum = (activecpu < 0) ? 0 : activecpu;
983 return GETPC(cpunum);
984 }
985
cpu_set_pc(unsigned val)986 void cpu_set_pc(unsigned val)
987 {
988 int cpunum = (activecpu < 0) ? 0 : activecpu;
989 SETPC(cpunum,val);
990 }
991
cpu_get_sp(void)992 unsigned cpu_get_sp(void)
993 {
994 int cpunum = (activecpu < 0) ? 0 : activecpu;
995 return GETSP(cpunum);
996 }
997
cpu_set_sp(unsigned val)998 void cpu_set_sp(unsigned val)
999 {
1000 int cpunum = (activecpu < 0) ? 0 : activecpu;
1001 SETSP(cpunum,val);
1002 }
1003
1004 /* these are available externally, for the timer system */
cycles_currently_ran(void)1005 int cycles_currently_ran(void)
1006 {
1007 int cpunum = (activecpu < 0) ? 0 : activecpu;
1008 return cycles_running - ICOUNT(cpunum);
1009 }
1010
cycles_left_to_run(void)1011 int cycles_left_to_run(void)
1012 {
1013 int cpunum = (activecpu < 0) ? 0 : activecpu;
1014 return ICOUNT(cpunum);
1015 }
1016
1017
1018
1019 /***************************************************************************
1020
1021 Returns the number of CPU cycles since the last reset of the CPU
1022
1023 IMPORTANT: this value wraps around in a relatively short time.
1024 For example, for a 6Mhz CPU, it will wrap around in
1025 2^32/6000000 = 716 seconds = 12 minutes.
1026 Make sure you don't do comparisons between values returned by this
1027 function, but only use the difference (which will be correct regardless
1028 of wraparound).
1029
1030 ***************************************************************************/
cpu_gettotalcycles(void)1031 int cpu_gettotalcycles(void)
1032 {
1033 int cpunum = (activecpu < 0) ? 0 : activecpu;
1034 return cpu[cpunum].totalcycles + cycles_currently_ran();
1035 }
1036
1037
1038
1039 /***************************************************************************
1040
1041 Returns the number of CPU cycles before the next interrupt handler call
1042
1043 ***************************************************************************/
cpu_geticount(void)1044 int cpu_geticount(void)
1045 {
1046 int cpunum = (activecpu < 0) ? 0 : activecpu;
1047 int result = TIME_TO_CYCLES(cpunum, cpu[cpunum].vblankint_period - timer_timeelapsed(cpu[cpunum].vblankint_timer));
1048 return (result < 0) ? 0 : result;
1049 }
1050
1051
1052
1053 /***************************************************************************
1054
1055 Returns the number of CPU cycles before the end of the current video frame
1056
1057 ***************************************************************************/
cpu_getfcount(void)1058 int cpu_getfcount(void)
1059 {
1060 int cpunum = (activecpu < 0) ? 0 : activecpu;
1061 int result = TIME_TO_CYCLES(cpunum, refresh_period - timer_timeelapsed(refresh_timer));
1062 return (result < 0) ? 0 : result;
1063 }
1064
1065
1066
1067 /***************************************************************************
1068
1069 Returns the number of CPU cycles in one video frame
1070
1071 ***************************************************************************/
cpu_getfperiod(void)1072 int cpu_getfperiod(void)
1073 {
1074 int cpunum = (activecpu < 0) ? 0 : activecpu;
1075 return TIME_TO_CYCLES(cpunum, refresh_period);
1076 }
1077
1078
1079
1080 /***************************************************************************
1081
1082 Scales a given value by the ratio of fcount / fperiod
1083
1084 ***************************************************************************/
cpu_scalebyfcount(int value)1085 int cpu_scalebyfcount(int value)
1086 {
1087 int result = ( ((INT64)value) * ((INT64)timer_timeelapsed(refresh_timer)) ) / ((INT64)refresh_period);
1088 if (value >= 0) return (result < value) ? result : value;
1089 else return (result > value) ? result : value;
1090 }
1091
1092
1093
1094 /***************************************************************************
1095
1096 Returns the current scanline, or the time until a specific scanline
1097
1098 Note: cpu_getscanline() counts from 0, 0 being the first visible line. You
1099 might have to adjust this value to match the hardware, since in many cases
1100 the first visible line is >0.
1101
1102 ***************************************************************************/
cpu_getscanline(void)1103 int cpu_getscanline(void)
1104 {
1105 return (int)(timer_timeelapsed(refresh_timer)/scanline_period);
1106 }
1107
1108
cpu_getscanlinetime(int scanline)1109 timer_tm cpu_getscanlinetime(int scanline)
1110 {
1111 timer_tm ret;
1112 timer_tm scantime = ((timer_entry *)refresh_timer)->start + scanline*scanline_period;
1113 timer_tm abstime = getabsolutetime();
1114 if (abstime >= scantime) scantime += TIME_IN_HZ(Machine->drv->frames_per_second);
1115 ret = scantime - abstime;
1116 if (ret < 1)
1117 {
1118 ret = TIME_IN_HZ(Machine->drv->frames_per_second);
1119 }
1120
1121 return ret;
1122 }
1123
1124
cpu_getscanlineperiod(void)1125 timer_tm cpu_getscanlineperiod(void)
1126 {
1127 return scanline_period;
1128 }
1129
1130
1131 /***************************************************************************
1132
1133 Returns the number of cycles in a scanline
1134
1135 ***************************************************************************/
cpu_getscanlinecycles(void)1136 int cpu_getscanlinecycles(void)
1137 {
1138 int cpunum = (activecpu < 0) ? 0 : activecpu;
1139 return TIME_TO_CYCLES(cpunum, scanline_period);
1140 }
1141
1142
1143 /***************************************************************************
1144
1145 Returns the number of cycles since the beginning of this frame
1146
1147 ***************************************************************************/
cpu_getcurrentcycles(void)1148 int cpu_getcurrentcycles(void)
1149 {
1150 int cpunum = (activecpu < 0) ? 0 : activecpu;
1151 return TIME_TO_CYCLES(cpunum, timer_timeelapsed(refresh_timer));
1152 }
1153
1154
1155 /***************************************************************************
1156
1157 Returns the current horizontal beam position in pixels
1158
1159 ***************************************************************************/
cpu_gethorzbeampos(void)1160 int cpu_gethorzbeampos(void)
1161 {
1162 /*
1163 timer_tm elapsed_time = timer_timeelapsed(refresh_timer);
1164 int scanline = elapsed_time / scanline_period;
1165 timer_tm time_since_scanline = elapsed_time - scanline * scanline_period;
1166 */
1167 timer_tm time_since_scanline = timer_timeelapsed(refresh_timer) % scanline_period;
1168 return ( ((INT64)time_since_scanline) * ((INT64)Machine->drv->screen_width) ) / ((INT64)scanline_period);
1169 }
1170
1171
1172 /***************************************************************************
1173
1174 Returns the number of times the interrupt handler will be called before
1175 the end of the current video frame. This can be useful to interrupt
1176 handlers to synchronize their operation. If you call this from outside
1177 an interrupt handler, add 1 to the result, i.e. if it returns 0, it means
1178 that the interrupt handler will be called once.
1179
1180 ***************************************************************************/
cpu_getiloops(void)1181 int cpu_getiloops(void)
1182 {
1183 int cpunum = (activecpu < 0) ? 0 : activecpu;
1184 return cpu[cpunum].iloops;
1185 }
1186
1187
1188
1189 /***************************************************************************
1190
1191 Interrupt handling
1192
1193 ***************************************************************************/
1194
1195 /***************************************************************************
1196
1197 These functions are called when a cpu calls the callback sent to it's
1198 set_irq_callback function. It clears the irq line if the current state
1199 is HOLD_LINE and returns the interrupt vector for that line.
1200
1201 ***************************************************************************/
1202 #define MAKE_IRQ_CALLBACK(num) \
1203 static int cpu_##num##_irq_callback(int irqline) \
1204 { \
1205 int vector = irq_line_vector[num * MAX_IRQ_LINES + irqline]; \
1206 if( irq_line_state[num * MAX_IRQ_LINES + irqline] == HOLD_LINE ) \
1207 { \
1208 SETIRQLINE(num, irqline, CLEAR_LINE); \
1209 irq_line_state[num * MAX_IRQ_LINES + irqline] = CLEAR_LINE; \
1210 } \
1211 LOG(("cpu_##num##_irq_callback(%d) $%04x\n", irqline, vector)); \
1212 if( drv_irq_callbacks[num] ) \
1213 return (*drv_irq_callbacks[num])(vector); \
1214 return vector; \
1215 }
1216
1217 MAKE_IRQ_CALLBACK(0)
1218 MAKE_IRQ_CALLBACK(1)
1219 MAKE_IRQ_CALLBACK(2)
1220 MAKE_IRQ_CALLBACK(3)
1221 MAKE_IRQ_CALLBACK(4)
1222 MAKE_IRQ_CALLBACK(5)
1223 MAKE_IRQ_CALLBACK(6)
1224 MAKE_IRQ_CALLBACK(7)
1225
1226 /***************************************************************************
1227
1228 This function is used to generate internal interrupts (TMS34010)
1229
1230 ***************************************************************************/
cpu_generate_internal_interrupt(int cpunum,int type)1231 void cpu_generate_internal_interrupt(int cpunum, int type)
1232 {
1233 timer_set(TIME_NOW, (cpunum & 7) | (type << 3), cpu_internalintcallback);
1234 }
1235
1236
1237 /***************************************************************************
1238
1239 Use this functions to set the vector for a irq line of a CPU
1240
1241 ***************************************************************************/
cpu_irq_line_vector_w(int cpunum,int irqline,int vector)1242 void cpu_irq_line_vector_w(int cpunum, int irqline, int vector)
1243 {
1244 cpunum &= (MAX_CPU - 1);
1245 irqline &= (MAX_IRQ_LINES - 1);
1246 if( irqline < cpu[cpunum].intf->num_irqs )
1247 {
1248 LOG(("cpu_irq_line_vector_w(%d,%d,$%04x)\n",cpunum,irqline,vector));
1249 irq_line_vector[cpunum * MAX_IRQ_LINES + irqline] = vector;
1250 return;
1251 }
1252 LOG(("cpu_irq_line_vector_w CPU#%d irqline %d > max irq lines\n", cpunum, irqline));
1253 }
1254
1255 /***************************************************************************
1256
1257 Use these functions to set the vector (data) for a irq line (offset)
1258 of CPU #0 to #3
1259
1260 ***************************************************************************/
WRITE_HANDLER(cpu_0_irq_line_vector_w)1261 WRITE_HANDLER( cpu_0_irq_line_vector_w ) { cpu_irq_line_vector_w(0, offset, data); }
WRITE_HANDLER(cpu_1_irq_line_vector_w)1262 WRITE_HANDLER( cpu_1_irq_line_vector_w ) { cpu_irq_line_vector_w(1, offset, data); }
WRITE_HANDLER(cpu_2_irq_line_vector_w)1263 WRITE_HANDLER( cpu_2_irq_line_vector_w ) { cpu_irq_line_vector_w(2, offset, data); }
WRITE_HANDLER(cpu_3_irq_line_vector_w)1264 WRITE_HANDLER( cpu_3_irq_line_vector_w ) { cpu_irq_line_vector_w(3, offset, data); }
WRITE_HANDLER(cpu_4_irq_line_vector_w)1265 WRITE_HANDLER( cpu_4_irq_line_vector_w ) { cpu_irq_line_vector_w(4, offset, data); }
WRITE_HANDLER(cpu_5_irq_line_vector_w)1266 WRITE_HANDLER( cpu_5_irq_line_vector_w ) { cpu_irq_line_vector_w(5, offset, data); }
WRITE_HANDLER(cpu_6_irq_line_vector_w)1267 WRITE_HANDLER( cpu_6_irq_line_vector_w ) { cpu_irq_line_vector_w(6, offset, data); }
WRITE_HANDLER(cpu_7_irq_line_vector_w)1268 WRITE_HANDLER( cpu_7_irq_line_vector_w ) { cpu_irq_line_vector_w(7, offset, data); }
1269
1270 /***************************************************************************
1271
1272 Use this function to set the state the NMI line of a CPU
1273
1274 ***************************************************************************/
cpu_set_nmi_line(int cpunum,int state)1275 void cpu_set_nmi_line(int cpunum, int state)
1276 {
1277 /* don't trigger interrupts on suspended CPUs */
1278 if (cpu_getstatus(cpunum) == 0) return;
1279
1280 LOG(("cpu_set_nmi_line(%d,%d)\n",cpunum,state));
1281 timer_set(TIME_NOW, (cpunum & 7) | (state << 3), cpu_manualnmicallback);
1282 }
1283
1284 /***************************************************************************
1285
1286 Use this function to set the state of an IRQ line of a CPU
1287 The meaning of irqline varies between the different CPU types
1288
1289 ***************************************************************************/
cpu_set_irq_line(int cpunum,int irqline,int state)1290 void cpu_set_irq_line(int cpunum, int irqline, int state)
1291 {
1292 /* don't trigger interrupts on suspended CPUs */
1293 if (cpu_getstatus(cpunum) == 0) return;
1294
1295 LOG(("cpu_set_irq_line(%d,%d,%d)\n",cpunum,irqline,state));
1296 timer_set(TIME_NOW, (irqline & 7) | ((cpunum & 7) << 3) | (state << 6), cpu_manualirqcallback);
1297 }
1298
1299 /***************************************************************************
1300
1301 Use this function to cause an interrupt immediately (don't have to wait
1302 until the next call to the interrupt handler)
1303
1304 ***************************************************************************/
cpu_cause_interrupt(int cpunum,int type)1305 void cpu_cause_interrupt(int cpunum,int type)
1306 {
1307 /* don't trigger interrupts on suspended CPUs */
1308 if (cpu_getstatus(cpunum) == 0) return;
1309
1310 timer_set(TIME_NOW, (cpunum & 7) | (type << 3), cpu_manualintcallback);
1311 }
1312
1313
1314
cpu_clear_pending_interrupts(int cpunum)1315 void cpu_clear_pending_interrupts(int cpunum)
1316 {
1317 timer_set(TIME_NOW, cpunum, cpu_clearintcallback);
1318 }
1319
1320
1321
WRITE_HANDLER(interrupt_enable_w)1322 WRITE_HANDLER( interrupt_enable_w )
1323 {
1324 int cpunum = (activecpu < 0) ? 0 : activecpu;
1325 interrupt_enable[cpunum] = data;
1326
1327 /* make sure there are no queued interrupts */
1328 if (data == 0) cpu_clear_pending_interrupts(cpunum);
1329 }
1330
1331
1332
WRITE_HANDLER(interrupt_vector_w)1333 WRITE_HANDLER( interrupt_vector_w )
1334 {
1335 int cpunum = (activecpu < 0) ? 0 : activecpu;
1336 if (interrupt_vector[cpunum] != data)
1337 {
1338 LOG(("CPU#%d interrupt_vector_w $%02x\n", cpunum, data));
1339 interrupt_vector[cpunum] = data;
1340
1341 /* make sure there are no queued interrupts */
1342 cpu_clear_pending_interrupts(cpunum);
1343 }
1344 }
1345
1346
1347
interrupt(void)1348 int interrupt(void)
1349 {
1350 int cpunum = (activecpu < 0) ? 0 : activecpu;
1351 int val;
1352
1353 if (interrupt_enable[cpunum] == 0)
1354 return INT_TYPE_NONE(cpunum);
1355
1356 val = INT_TYPE_IRQ(cpunum);
1357 if (val == -1000)
1358 val = interrupt_vector[cpunum];
1359
1360 return val;
1361 }
1362
1363
1364
nmi_interrupt(void)1365 int nmi_interrupt(void)
1366 {
1367 int cpunum = (activecpu < 0) ? 0 : activecpu;
1368
1369 if (interrupt_enable[cpunum] == 0)
1370 return INT_TYPE_NONE(cpunum);
1371
1372 return INT_TYPE_NMI(cpunum);
1373 }
1374
1375
1376
m68_level1_irq(void)1377 int m68_level1_irq(void)
1378 {
1379 int cpunum = (activecpu < 0) ? 0 : activecpu;
1380 if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1381 return MC68000_IRQ_1;
1382 }
m68_level2_irq(void)1383 int m68_level2_irq(void)
1384 {
1385 int cpunum = (activecpu < 0) ? 0 : activecpu;
1386 if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1387 return MC68000_IRQ_2;
1388 }
m68_level3_irq(void)1389 int m68_level3_irq(void)
1390 {
1391 int cpunum = (activecpu < 0) ? 0 : activecpu;
1392 if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1393 return MC68000_IRQ_3;
1394 }
m68_level4_irq(void)1395 int m68_level4_irq(void)
1396 {
1397 int cpunum = (activecpu < 0) ? 0 : activecpu;
1398 if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1399 return MC68000_IRQ_4;
1400 }
m68_level5_irq(void)1401 int m68_level5_irq(void)
1402 {
1403 int cpunum = (activecpu < 0) ? 0 : activecpu;
1404 if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1405 return MC68000_IRQ_5;
1406 }
m68_level6_irq(void)1407 int m68_level6_irq(void)
1408 {
1409 int cpunum = (activecpu < 0) ? 0 : activecpu;
1410 if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1411 return MC68000_IRQ_6;
1412 }
m68_level7_irq(void)1413 int m68_level7_irq(void)
1414 {
1415 int cpunum = (activecpu < 0) ? 0 : activecpu;
1416 if (interrupt_enable[cpunum] == 0) return MC68000_INT_NONE;
1417 return MC68000_IRQ_7;
1418 }
1419
1420
1421
ignore_interrupt(void)1422 int ignore_interrupt(void)
1423 {
1424 int cpunum = (activecpu < 0) ? 0 : activecpu;
1425 return INT_TYPE_NONE(cpunum);
1426 }
1427
1428
1429
1430 /***************************************************************************
1431
1432 CPU timing and synchronization functions.
1433
1434 ***************************************************************************/
1435
1436 /* generate a trigger */
cpu_trigger(int trigger)1437 void cpu_trigger(int trigger)
1438 {
1439 timer_trigger(trigger);
1440 }
1441
1442 /* generate a trigger after a specific period of time */
cpu_triggertime(timer_tm duration,int trigger)1443 void cpu_triggertime(timer_tm duration, int trigger)
1444 {
1445 timer_set(duration, trigger, cpu_trigger);
1446 }
1447
1448
1449
1450 /* burn CPU cycles until a timer trigger */
cpu_spinuntil_trigger(int trigger)1451 void cpu_spinuntil_trigger(int trigger)
1452 {
1453 int cpunum = (activecpu < 0) ? 0 : activecpu;
1454 timer_suspendcpu_trigger(cpunum, trigger);
1455 }
1456
1457 /* burn CPU cycles until the next interrupt */
cpu_spinuntil_int(void)1458 void cpu_spinuntil_int(void)
1459 {
1460 int cpunum = (activecpu < 0) ? 0 : activecpu;
1461 cpu_spinuntil_trigger(TRIGGER_INT + cpunum);
1462 }
1463
1464 /* burn CPU cycles until our timeslice is up */
cpu_spin(void)1465 void cpu_spin(void)
1466 {
1467 cpu_spinuntil_trigger(TRIGGER_TIMESLICE);
1468 }
1469
1470 /* burn CPU cycles for a specific period of time */
cpu_spinuntil_time(timer_tm duration)1471 void cpu_spinuntil_time(timer_tm duration)
1472 {
1473 static int timetrig = 0;
1474
1475 cpu_spinuntil_trigger(TRIGGER_SUSPENDTIME + timetrig);
1476 cpu_triggertime(duration, TRIGGER_SUSPENDTIME + timetrig);
1477 timetrig = (timetrig + 1) & 255;
1478 }
1479
1480
1481
1482 /* yield our timeslice for a specific period of time */
cpu_yielduntil_trigger(int trigger)1483 void cpu_yielduntil_trigger(int trigger)
1484 {
1485 int cpunum = (activecpu < 0) ? 0 : activecpu;
1486 timer_holdcpu_trigger(cpunum, trigger);
1487 }
1488
1489 /* yield our timeslice until the next interrupt */
cpu_yielduntil_int(void)1490 void cpu_yielduntil_int(void)
1491 {
1492 int cpunum = (activecpu < 0) ? 0 : activecpu;
1493 cpu_yielduntil_trigger(TRIGGER_INT + cpunum);
1494 }
1495
1496 /* yield our current timeslice */
cpu_yield(void)1497 void cpu_yield(void)
1498 {
1499 cpu_yielduntil_trigger(TRIGGER_TIMESLICE);
1500 }
1501
1502 /* yield our timeslice for a specific period of time */
cpu_yielduntil_time(timer_tm duration)1503 void cpu_yielduntil_time(timer_tm duration)
1504 {
1505 static int timetrig = 0;
1506
1507 cpu_yielduntil_trigger(TRIGGER_YIELDTIME + timetrig);
1508 cpu_triggertime(duration, TRIGGER_YIELDTIME + timetrig);
1509 timetrig = (timetrig + 1) & 255;
1510 }
1511
1512
1513
cpu_getvblank(void)1514 int cpu_getvblank(void)
1515 {
1516 return vblank;
1517 }
1518
1519
cpu_getcurrentframe(void)1520 int cpu_getcurrentframe(void)
1521 {
1522 return current_frame;
1523 }
1524
1525
1526 /***************************************************************************
1527
1528 Internal CPU event processors.
1529
1530 ***************************************************************************/
1531
cpu_manualnmicallback(int param)1532 static void cpu_manualnmicallback(int param)
1533 {
1534 int cpunum, state, oldactive;
1535 cpunum = param & 7;
1536 state = param >> 3;
1537
1538 /* swap to the CPU's context */
1539 oldactive = activecpu;
1540 activecpu = cpunum;
1541 memorycontextswap(activecpu);
1542 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1543
1544 LOG(("cpu_manualnmicallback %d,%d\n",cpunum,state));
1545
1546 switch (state)
1547 {
1548 case PULSE_LINE:
1549 SETNMILINE(cpunum,ASSERT_LINE);
1550 SETNMILINE(cpunum,CLEAR_LINE);
1551 break;
1552 case HOLD_LINE:
1553 case ASSERT_LINE:
1554 SETNMILINE(cpunum,ASSERT_LINE);
1555 break;
1556 case CLEAR_LINE:
1557 SETNMILINE(cpunum,CLEAR_LINE);
1558 break;
1559 default:
1560 logerror("cpu_manualnmicallback cpu #%d unknown state %d\n", cpunum, state);
1561 }
1562 /* update the CPU's context */
1563 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1564 activecpu = oldactive;
1565 if (activecpu >= 0) memorycontextswap(activecpu);
1566
1567 /* generate a trigger to unsuspend any CPUs waiting on the interrupt */
1568 if (state != CLEAR_LINE)
1569 timer_trigger(TRIGGER_INT + cpunum);
1570 }
1571
cpu_manualirqcallback(int param)1572 static void cpu_manualirqcallback(int param)
1573 {
1574 int cpunum, irqline, state, oldactive;
1575
1576 irqline = param & 7;
1577 cpunum = (param >> 3) & 7;
1578 state = param >> 6;
1579
1580 /* swap to the CPU's context */
1581 oldactive = activecpu;
1582 activecpu = cpunum;
1583 memorycontextswap(activecpu);
1584 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1585
1586 LOG(("cpu_manualirqcallback %d,%d,%d\n",cpunum,irqline,state));
1587
1588 irq_line_state[cpunum * MAX_IRQ_LINES + irqline] = state;
1589 switch (state)
1590 {
1591 case PULSE_LINE:
1592 SETIRQLINE(cpunum,irqline,ASSERT_LINE);
1593 SETIRQLINE(cpunum,irqline,CLEAR_LINE);
1594 break;
1595 case HOLD_LINE:
1596 case ASSERT_LINE:
1597 SETIRQLINE(cpunum,irqline,ASSERT_LINE);
1598 break;
1599 case CLEAR_LINE:
1600 SETIRQLINE(cpunum,irqline,CLEAR_LINE);
1601 break;
1602 default:
1603 logerror("cpu_manualirqcallback cpu #%d, line %d, unknown state %d\n", cpunum, irqline, state);
1604 }
1605
1606 /* update the CPU's context */
1607 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1608 activecpu = oldactive;
1609 if (activecpu >= 0) memorycontextswap(activecpu);
1610
1611 /* generate a trigger to unsuspend any CPUs waiting on the interrupt */
1612 if (state != CLEAR_LINE)
1613 timer_trigger(TRIGGER_INT + cpunum);
1614 }
1615
cpu_internal_interrupt(int cpunum,int type)1616 static void cpu_internal_interrupt(int cpunum, int type)
1617 {
1618 int oldactive = activecpu;
1619
1620 /* swap to the CPU's context */
1621 activecpu = cpunum;
1622 memorycontextswap(activecpu);
1623 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1624
1625 INTERNAL_INTERRUPT(cpunum, type);
1626
1627 /* update the CPU's context */
1628 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1629 activecpu = oldactive;
1630 if (activecpu >= 0) memorycontextswap(activecpu);
1631
1632 /* generate a trigger to unsuspend any CPUs waiting on the interrupt */
1633 timer_trigger(TRIGGER_INT + cpunum);
1634 }
1635
cpu_internalintcallback(int param)1636 static void cpu_internalintcallback(int param)
1637 {
1638 int type = param >> 3;
1639 int cpunum = param & 7;
1640
1641 LOG(("CPU#%d internal interrupt type $%04x\n", cpunum, type));
1642 /* generate the interrupt */
1643 cpu_internal_interrupt(cpunum, type);
1644 }
1645
cpu_generate_interrupt(int cpunum,int (* func)(void),int num)1646 static void cpu_generate_interrupt(int cpunum, int (*func)(void), int num)
1647 {
1648 int oldactive = activecpu;
1649
1650 /* don't trigger interrupts on suspended CPUs */
1651 if (cpu_getstatus(cpunum) == 0) return;
1652
1653 /* swap to the CPU's context */
1654 activecpu = cpunum;
1655 memorycontextswap(activecpu);
1656 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1657
1658 /* cause the interrupt, calling the function if it exists */
1659 if (func) num = (*func)();
1660
1661 /* wrapper for the new interrupt system */
1662 if (num != INT_TYPE_NONE(cpunum))
1663 {
1664 LOG(("CPU#%d interrupt type $%04x: ", cpunum, num));
1665 /* is it the NMI type interrupt of that CPU? */
1666 if (num == INT_TYPE_NMI(cpunum))
1667 {
1668
1669 LOG(("NMI\n"));
1670 cpu_manualnmicallback(cpunum | (PULSE_LINE << 3) );
1671
1672 }
1673 else
1674 {
1675 int irq_line=0;
1676
1677 switch (CPU_TYPE(cpunum))
1678 {
1679 #if (HAS_8085A)
1680 case CPU_8085A:
1681 switch (num)
1682 {
1683 case I8085_RST55: irq_line = 1; break;
1684 case I8085_RST65: irq_line = 2; break;
1685 case I8085_RST75: irq_line = 3; break;
1686 }
1687 break;
1688 #endif
1689 #if (HAS_H6280)
1690 case CPU_H6280:
1691 switch (num)
1692 {
1693 case H6280_INT_IRQ2: irq_line = 1; break;
1694 case H6280_INT_TIMER: irq_line = 2; break;
1695 }
1696 break;
1697 #endif
1698 #if (HAS_HD6309)
1699 case CPU_HD6309:
1700 if (num==HD6309_INT_FIRQ) irq_line = 1;
1701 break;
1702 #endif
1703 #if (HAS_M6809)
1704 case CPU_M6809:
1705 if (num==M6809_INT_FIRQ) irq_line = 1;
1706 break;
1707 #endif
1708 #if (HAS_KONAMI)
1709 case CPU_KONAMI:
1710 if (num==KONAMI_INT_FIRQ) irq_line = 1;
1711 break;
1712 #endif
1713 #if (HAS_M68000)
1714 case CPU_M68000:
1715 switch (num)
1716 {
1717 case MC68000_IRQ_1: irq_line = 1; break;
1718 case MC68000_IRQ_2: irq_line = 2; break;
1719 case MC68000_IRQ_3: irq_line = 3; break;
1720 case MC68000_IRQ_4: irq_line = 4; break;
1721 case MC68000_IRQ_5: irq_line = 5; break;
1722 case MC68000_IRQ_6: irq_line = 6; break;
1723 case MC68000_IRQ_7: irq_line = 7; break;
1724 }
1725 /* until now only auto vector interrupts supported */
1726 num = MC68000_INT_ACK_AUTOVECTOR;
1727 break;
1728 #endif
1729 #if (HAS_CYCLONE)
1730 case CPU_CYCLONE:
1731 switch (num)
1732 {
1733 case cyclone_IRQ_1: irq_line = 1; break;
1734 case cyclone_IRQ_2: irq_line = 2; break;
1735 case cyclone_IRQ_3: irq_line = 3; break;
1736 case cyclone_IRQ_4: irq_line = 4; break;
1737 case cyclone_IRQ_5: irq_line = 5; break;
1738 case cyclone_IRQ_6: irq_line = 6; break;
1739 case cyclone_IRQ_7: irq_line = 7; break;
1740 }
1741 /* until now only auto vector interrupts supported */
1742 num = cyclone_INT_ACK_AUTOVECTOR;
1743 break;
1744 #endif
1745 #if (HAS_M68010)
1746 case CPU_M68010:
1747 switch (num)
1748 {
1749 case MC68010_IRQ_1: irq_line = 1; break;
1750 case MC68010_IRQ_2: irq_line = 2; break;
1751 case MC68010_IRQ_3: irq_line = 3; break;
1752 case MC68010_IRQ_4: irq_line = 4; break;
1753 case MC68010_IRQ_5: irq_line = 5; break;
1754 case MC68010_IRQ_6: irq_line = 6; break;
1755 case MC68010_IRQ_7: irq_line = 7; break;
1756 }
1757 /* until now only auto vector interrupts supported */
1758 num = MC68000_INT_ACK_AUTOVECTOR;
1759 break;
1760 #endif
1761 #if (HAS_M68020)
1762 case CPU_M68020:
1763 switch (num)
1764 {
1765 case MC68020_IRQ_1: irq_line = 1; break;
1766 case MC68020_IRQ_2: irq_line = 2; break;
1767 case MC68020_IRQ_3: irq_line = 3; break;
1768 case MC68020_IRQ_4: irq_line = 4; break;
1769 case MC68020_IRQ_5: irq_line = 5; break;
1770 case MC68020_IRQ_6: irq_line = 6; break;
1771 case MC68020_IRQ_7: irq_line = 7; break;
1772 }
1773 /* until now only auto vector interrupts supported */
1774 num = MC68000_INT_ACK_AUTOVECTOR;
1775 break;
1776 #endif
1777 #if (HAS_M68EC020)
1778 case CPU_M68EC020:
1779 switch (num)
1780 {
1781 case MC68EC020_IRQ_1: irq_line = 1; break;
1782 case MC68EC020_IRQ_2: irq_line = 2; break;
1783 case MC68EC020_IRQ_3: irq_line = 3; break;
1784 case MC68EC020_IRQ_4: irq_line = 4; break;
1785 case MC68EC020_IRQ_5: irq_line = 5; break;
1786 case MC68EC020_IRQ_6: irq_line = 6; break;
1787 case MC68EC020_IRQ_7: irq_line = 7; break;
1788 }
1789 /* until now only auto vector interrupts supported */
1790 num = MC68000_INT_ACK_AUTOVECTOR;
1791 break;
1792 #endif
1793 #if (HAS_T11)
1794 case CPU_T11:
1795 switch (num)
1796 {
1797 case T11_IRQ0: irq_line = 0; break;
1798 case T11_IRQ1: irq_line = 1; break;
1799 case T11_IRQ2: irq_line = 2; break;
1800 case T11_IRQ3: irq_line = 3; break;
1801 }
1802 break;
1803 #endif
1804 #if (HAS_TMS34010)
1805 case CPU_TMS34010:
1806 if (num==TMS34010_INT2) irq_line = 1;
1807 break;
1808 #endif
1809 #if (HAS_Z8000)
1810 if (num==Z8000_VI) irq_line = 1;
1811 break;
1812 #endif
1813 #if (HAS_TMS320C10)
1814 case CPU_TMS320C10:
1815 if (num==TMS320C10_ACTIVE_BIO) irq_line = 1;
1816 break;
1817 #endif
1818 #if (HAS_ADSP2100)
1819 case CPU_ADSP2100:
1820 switch (num)
1821 {
1822 case ADSP2100_IRQ1: irq_line = 1; break;
1823 case ADSP2100_IRQ2: irq_line = 2; break;
1824 case ADSP2100_IRQ3: irq_line = 3; break;
1825 }
1826 break;
1827 #endif
1828 }
1829 LOG(("IRQ %d\n",irq_line));
1830 cpu_irq_line_vector_w(cpunum, irq_line, num);
1831 cpu_manualirqcallback(irq_line | (cpunum << 3) | (HOLD_LINE << 6) );
1832 }
1833 }
1834
1835 /* update the CPU's context */
1836 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1837 activecpu = oldactive;
1838 if (activecpu >= 0) memorycontextswap(activecpu);
1839
1840 /* trigger already generated by cpu_manualirqcallback or cpu_manualnmicallback */
1841 }
1842
cpu_clear_interrupts(int cpunum)1843 static void cpu_clear_interrupts(int cpunum)
1844 {
1845 int oldactive = activecpu;
1846 int i;
1847
1848 /* swap to the CPU's context */
1849 activecpu = cpunum;
1850 memorycontextswap(activecpu);
1851 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1852
1853 /* clear NMI line */
1854 SETNMILINE(activecpu,CLEAR_LINE);
1855
1856 /* clear all IRQ lines */
1857 for (i = 0; i < cpu[activecpu].intf->num_irqs; i++)
1858 SETIRQLINE(activecpu,i,CLEAR_LINE);
1859
1860 /* update the CPU's context */
1861 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1862 activecpu = oldactive;
1863 if (activecpu >= 0) memorycontextswap(activecpu);
1864 }
1865
1866
cpu_reset_cpu(int cpunum)1867 static void cpu_reset_cpu(int cpunum)
1868 {
1869 int oldactive = activecpu;
1870
1871 /* swap to the CPU's context */
1872 activecpu = cpunum;
1873 memorycontextswap(activecpu);
1874 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
1875
1876 /* reset the CPU */
1877 RESET(cpunum);
1878
1879 /* Set the irq callback for the cpu */
1880 SETIRQCALLBACK(cpunum,cpu_irq_callbacks[cpunum]);
1881
1882 /* update the CPU's context */
1883 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
1884 activecpu = oldactive;
1885 if (activecpu >= 0) memorycontextswap(activecpu);
1886 }
1887
1888 /***************************************************************************
1889
1890 Interrupt callback. This is called once per CPU interrupt by either the
1891 VBLANK handler or by the CPU's own timer directly, depending on whether
1892 or not the CPU's interrupts are synced to VBLANK.
1893
1894 ***************************************************************************/
cpu_vblankintcallback(int param)1895 static void cpu_vblankintcallback(int param)
1896 {
1897 if (Machine->drv->cpu[param].vblank_interrupt)
1898 cpu_generate_interrupt(param, Machine->drv->cpu[param].vblank_interrupt, 0);
1899
1900 /* update the counters */
1901 cpu[param].iloops--;
1902 }
1903
1904
cpu_timedintcallback(int param)1905 static void cpu_timedintcallback(int param)
1906 {
1907 /* bail if there is no routine */
1908 if (!Machine->drv->cpu[param].timed_interrupt)
1909 return;
1910
1911 /* generate the interrupt */
1912 cpu_generate_interrupt(param, Machine->drv->cpu[param].timed_interrupt, 0);
1913 }
1914
1915
cpu_manualintcallback(int param)1916 static void cpu_manualintcallback(int param)
1917 {
1918 int intnum = param >> 3;
1919 int cpunum = param & 7;
1920
1921 /* generate the interrupt */
1922 cpu_generate_interrupt(cpunum, 0, intnum);
1923 }
1924
1925
cpu_clearintcallback(int param)1926 static void cpu_clearintcallback(int param)
1927 {
1928 /* clear the interrupts */
1929 cpu_clear_interrupts(param);
1930 }
1931
1932
cpu_resetcallback(int param)1933 static void cpu_resetcallback(int param)
1934 {
1935 int state = param >> 3;
1936 int cpunum = param & 7;
1937
1938 /* reset the CPU */
1939 if (state == PULSE_LINE)
1940 cpu_reset_cpu(cpunum);
1941 else if (state == ASSERT_LINE)
1942 {
1943 /* ASG - do we need this? cpu_reset_cpu(cpunum);*/
1944 timer_suspendcpu(cpunum, 1, SUSPEND_REASON_RESET); /* halt cpu */
1945 }
1946 else if (state == CLEAR_LINE)
1947 {
1948 if (timer_iscpususpended(cpunum, SUSPEND_REASON_RESET))
1949 cpu_reset_cpu(cpunum);
1950 timer_suspendcpu(cpunum, 0, SUSPEND_REASON_RESET); /* restart cpu */
1951 }
1952 }
1953
1954
cpu_haltcallback(int param)1955 static void cpu_haltcallback(int param)
1956 {
1957 int state = param >> 3;
1958 int cpunum = param & 7;
1959
1960 /* reset the CPU */
1961 if (state == ASSERT_LINE)
1962 timer_suspendcpu(cpunum, 1, SUSPEND_REASON_HALT); /* halt cpu */
1963 else if (state == CLEAR_LINE)
1964 timer_suspendcpu(cpunum, 0, SUSPEND_REASON_HALT); /* restart cpu */
1965 }
1966
1967
1968
1969 /***************************************************************************
1970
1971 VBLANK reset. Called at the start of emulation and once per VBLANK in
1972 order to update the input ports and reset the interrupt counter.
1973
1974 ***************************************************************************/
cpu_vblankreset(void)1975 static void cpu_vblankreset(void)
1976 {
1977 int i;
1978
1979 /* read hi scores from disk */
1980 hs_update();
1981
1982 /* read keyboard & update the status of the input ports */
1983 update_input_ports();
1984
1985 /* reset the cycle counters */
1986 for (i = 0; i < totalcpu; i++)
1987 {
1988 if (!timer_iscpususpended(i, SUSPEND_ANY_REASON))
1989 cpu[i].iloops = Machine->drv->cpu[i].vblank_interrupts_per_frame - 1;
1990 else
1991 cpu[i].iloops = -1;
1992 }
1993 }
1994
1995
1996 /***************************************************************************
1997
1998 VBLANK callback. This is called 'vblank_multipler' times per frame to
1999 service VBLANK-synced interrupts and to begin the screen update process.
2000
2001 ***************************************************************************/
cpu_firstvblankcallback(int param)2002 static void cpu_firstvblankcallback(int param)
2003 {
2004 /* now that we're synced up, pulse from here on out */
2005 vblank_timer = timer_pulse(vblank_period, param, cpu_vblankcallback);
2006
2007 /* but we need to call the standard routine as well */
2008 cpu_vblankcallback(param);
2009 }
2010
2011 /* note that calling this with param == -1 means count everything, but call no subroutines */
cpu_vblankcallback(int param)2012 static void cpu_vblankcallback(int param)
2013 {
2014 int i;
2015
2016 /* loop over CPUs */
2017 for (i = 0; i < totalcpu; i++)
2018 {
2019 /* if the interrupt multiplier is valid */
2020 if (cpu[i].vblankint_multiplier != -1)
2021 {
2022 /* decrement; if we hit zero, generate the interrupt and reset the countdown */
2023 if (!--cpu[i].vblankint_countdown)
2024 {
2025 if (param != -1)
2026 cpu_vblankintcallback(i);
2027 cpu[i].vblankint_countdown = cpu[i].vblankint_multiplier;
2028 timer_reset(cpu[i].vblankint_timer, TIME_NEVER);
2029 }
2030 }
2031
2032 /* else reset the VBLANK timer if this is going to be a real VBLANK */
2033 else if (vblank_countdown == 1)
2034 timer_reset(cpu[i].vblankint_timer, TIME_NEVER);
2035 }
2036
2037 /* is it a real VBLANK? */
2038 if (!--vblank_countdown)
2039 {
2040 /* do we update the screen now? */
2041 if (!(Machine->drv->video_attributes & VIDEO_UPDATE_AFTER_VBLANK))
2042 usres = updatescreen();
2043
2044 /* Set the timer to update the screen */
2045 timer_set(TIME_IN_USEC(Machine->drv->vblank_duration), 0, cpu_updatecallback);
2046 vblank = 1;
2047
2048 /* reset the globals */
2049 cpu_vblankreset();
2050
2051 /* reset the counter */
2052 vblank_countdown = vblank_multiplier;
2053 }
2054 }
2055
2056
2057 /***************************************************************************
2058
2059 Video update callback. This is called a game-dependent amount of time
2060 after the VBLANK in order to trigger a video update.
2061
2062 ***************************************************************************/
cpu_updatecallback(int param)2063 static void cpu_updatecallback(int param)
2064 {
2065 /* update the screen if we didn't before */
2066 if (Machine->drv->video_attributes & VIDEO_UPDATE_AFTER_VBLANK)
2067 usres = updatescreen();
2068 vblank = 0;
2069
2070 /* update IPT_VBLANK input ports */
2071 inputport_vblank_end();
2072
2073 /* check the watchdog */
2074 if (watchdog_counter > 0)
2075 {
2076 if (--watchdog_counter == 0)
2077 {
2078 logerror("reset caused by the watchdog\n");
2079 machine_reset();
2080 }
2081 }
2082
2083 current_frame++;
2084
2085 /* reset the refresh timer */
2086 timer_reset(refresh_timer, TIME_NEVER);
2087 }
2088
2089
2090 /***************************************************************************
2091
2092 Converts an integral timing rate into a period. Rates can be specified
2093 as follows:
2094
2095 rate > 0 -> 'rate' cycles per frame
2096 rate == 0 -> 0
2097 rate >= -10000 -> 'rate' cycles per second
2098 rate < -10000 -> 'rate' nanoseconds
2099
2100 ***************************************************************************/
cpu_computerate(int value)2101 static timer_tm cpu_computerate(int value)
2102 {
2103 /* values equal to zero are zero */
2104 if (value <= 0)
2105 return 0;
2106
2107 /* values above between 0 and 50000 are in Hz */
2108 if (value < 50000)
2109 return TIME_IN_HZ(value);
2110
2111 /* values greater than 50000 are in nanoseconds */
2112 else
2113 return TIME_IN_NSEC(value);
2114 }
2115
2116
cpu_timeslicecallback(int param)2117 static void cpu_timeslicecallback(int param)
2118 {
2119 timer_trigger(TRIGGER_TIMESLICE);
2120 }
2121
2122
2123 /***************************************************************************
2124
2125 Initializes all the timers used by the CPU system.
2126
2127 ***************************************************************************/
cpu_inittimers(void)2128 static void cpu_inittimers(void)
2129 {
2130 timer_tm first_time;
2131 int i, max, ipf;
2132
2133 /*
2134 #ifdef MAME_FASTSOUND
2135 {
2136 extern int fast_sound;
2137 if (fast_sound)
2138 {
2139 // M72 sound hack
2140 if ((strcmp(Machine->gamedrv->name,"bchopper")==0) || (strcmp(Machine->gamedrv->name,"mrheli")==0) || (strcmp(Machine->gamedrv->name,"nspirit")==0) ||
2141 (strcmp(Machine->gamedrv->name,"nspiritj")==0) || (strcmp(Machine->gamedrv->name,"imgfight")==0) || (strcmp(Machine->gamedrv->name,"loht")==0) ||
2142 (strcmp(Machine->gamedrv->name,"xmultipl")==0) || (strcmp(Machine->gamedrv->name,"dbreed")==0) || (strcmp(Machine->gamedrv->name,"rtype2")==0) ||
2143 (strcmp(Machine->gamedrv->name,"rtype2j")==0) || (strcmp(Machine->gamedrv->name,"majtitle")==0) || (strcmp(Machine->gamedrv->name,"hharry")==0) ||
2144 (strcmp(Machine->gamedrv->name,"hharryu")==0) || (strcmp(Machine->gamedrv->name,"dkgensan")==0) || (strcmp(Machine->gamedrv->name,"kengo")==0) ||
2145 (strcmp(Machine->gamedrv->name,"poundfor")==0) || (strcmp(Machine->gamedrv->name,"poundfou")==0) || (strcmp(Machine->gamedrv->name,"airduel")==0) ||
2146 (strcmp(Machine->gamedrv->name,"gallop")==0))
2147 {
2148 int *ptr=(int *)&Machine->drv->cpu[1].vblank_interrupts_per_frame;
2149 *ptr=1;
2150 }
2151 }
2152 }
2153 #endif
2154 */
2155
2156 /* remove old timers */
2157 if (timeslice_timer)
2158 timer_remove(timeslice_timer);
2159 if (refresh_timer)
2160 timer_remove(refresh_timer);
2161 if (vblank_timer)
2162 timer_remove(vblank_timer);
2163
2164 /* allocate a dummy timer at the minimum frequency to break things up */
2165 ipf = Machine->drv->cpu_slices_per_frame;
2166 if (ipf <= 0)
2167 ipf = 1;
2168 timeslice_period = TIME_IN_HZ(Machine->drv->frames_per_second * ipf);
2169 timeslice_timer = timer_pulse(timeslice_period, 0, cpu_timeslicecallback);
2170
2171 /* allocate an infinite timer to track elapsed time since the last refresh */
2172 refresh_period = TIME_IN_HZ(Machine->drv->frames_per_second);
2173 refresh_timer = timer_set(TIME_NEVER, 0, NULL);
2174
2175 /* while we're at it, compute the scanline times */
2176 if (Machine->drv->vblank_duration)
2177 scanline_period = (refresh_period - TIME_IN_USEC(Machine->drv->vblank_duration)) /
2178 (timer_tm)(Machine->visible_area.max_y - Machine->visible_area.min_y + 1);
2179 else
2180 scanline_period = refresh_period / (timer_tm)Machine->drv->screen_height;
2181
2182 /*
2183 * The following code finds all the CPUs that are interrupting in sync with the VBLANK
2184 * and sets up the VBLANK timer to run at the minimum number of cycles per frame in
2185 * order to service all the synced interrupts
2186 */
2187
2188 /* find the CPU with the maximum interrupts per frame */
2189 max = 1;
2190 for (i = 0; i < totalcpu; i++)
2191 {
2192 ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2193 if (ipf > max)
2194 max = ipf;
2195 }
2196
2197 /* now find the LCD with the rest of the CPUs (brute force - these numbers aren't huge) */
2198 vblank_multiplier = max;
2199 while (1)
2200 {
2201 for (i = 0; i < totalcpu; i++)
2202 {
2203 ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2204 if (ipf > 0 && (vblank_multiplier % ipf) != 0)
2205 break;
2206 }
2207 if (i == totalcpu)
2208 break;
2209 vblank_multiplier += max;
2210 }
2211
2212 /* initialize the countdown timers and intervals */
2213 for (i = 0; i < totalcpu; i++)
2214 {
2215 ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2216 if (ipf > 0)
2217 cpu[i].vblankint_countdown = cpu[i].vblankint_multiplier = vblank_multiplier / ipf;
2218 else
2219 cpu[i].vblankint_countdown = cpu[i].vblankint_multiplier = -1;
2220 }
2221
2222 /* allocate a vblank timer at the frame rate * the LCD number of interrupts per frame */
2223 vblank_period = TIME_IN_HZ(Machine->drv->frames_per_second * vblank_multiplier);
2224 vblank_timer = timer_pulse(vblank_period, 0, cpu_vblankcallback);
2225 vblank_countdown = vblank_multiplier;
2226
2227 /*
2228 * The following code creates individual timers for each CPU whose interrupts are not
2229 * synced to the VBLANK, and computes the typical number of cycles per interrupt
2230 */
2231
2232 /* start the CPU interrupt timers */
2233 for (i = 0; i < totalcpu; i++)
2234 {
2235 ipf = Machine->drv->cpu[i].vblank_interrupts_per_frame;
2236
2237 /* remove old timers */
2238 if (cpu[i].vblankint_timer)
2239 timer_remove(cpu[i].vblankint_timer);
2240 if (cpu[i].timedint_timer)
2241 timer_remove(cpu[i].timedint_timer);
2242
2243 /* compute the average number of cycles per interrupt */
2244 if (ipf <= 0)
2245 ipf = 1;
2246 cpu[i].vblankint_period = TIME_IN_HZ(Machine->drv->frames_per_second * ipf);
2247 cpu[i].vblankint_timer = timer_set(TIME_NEVER, 0, NULL);
2248
2249 /* see if we need to allocate a CPU timer */
2250 ipf = Machine->drv->cpu[i].timed_interrupts_per_second;
2251 if (ipf)
2252 {
2253 cpu[i].timedint_period = cpu_computerate(ipf);
2254 cpu[i].timedint_timer = timer_pulse(cpu[i].timedint_period, i, cpu_timedintcallback);
2255 }
2256 }
2257
2258 /* note that since we start the first frame on the refresh, we can't pulse starting
2259 immediately; instead, we back up one VBLANK period, and inch forward until we hit
2260 positive time. That time will be the time of the first VBLANK timer callback */
2261 timer_remove(vblank_timer);
2262
2263 first_time = -TIME_IN_USEC(Machine->drv->vblank_duration) + vblank_period;
2264 while (first_time < 0)
2265 {
2266 cpu_vblankcallback(-1);
2267 first_time += vblank_period;
2268 }
2269 vblank_timer = timer_set(first_time, 0, cpu_firstvblankcallback);
2270 }
2271
2272
2273 /* AJP 981016 */
cpu_is_saving_context(int _activecpu)2274 int cpu_is_saving_context(int _activecpu)
2275 {
2276 return (cpu[_activecpu].save_context);
2277 }
2278
2279
2280 /* JB 971019 */
cpu_getcontext(int _activecpu)2281 void* cpu_getcontext(int _activecpu)
2282 {
2283 return cpu[_activecpu].context;
2284 }
2285
2286
2287 /***************************************************************************
2288 Retrieve or set the entire context of the active CPU
2289 ***************************************************************************/
2290
cpu_get_context(void * context)2291 unsigned cpu_get_context(void *context)
2292 {
2293 int cpunum = (activecpu < 0) ? 0 : activecpu;
2294 return GETCONTEXT(cpunum,context);
2295 }
2296
cpu_set_context(void * context)2297 void cpu_set_context(void *context)
2298 {
2299 int cpunum = (activecpu < 0) ? 0 : activecpu;
2300 SETCONTEXT(cpunum,context);
2301 }
2302
2303 /***************************************************************************
2304 Retrieve or set a cycle counts lookup table for the active CPU
2305 ***************************************************************************/
2306
cpu_get_cycle_table(int which)2307 void *cpu_get_cycle_table(int which)
2308 {
2309 int cpunum = (activecpu < 0) ? 0 : activecpu;
2310 return GETCYCLETBL(cpunum,which);
2311 }
2312
cpu_set_cycle_tbl(int which,void * new_table)2313 void cpu_set_cycle_tbl(int which, void *new_table)
2314 {
2315 int cpunum = (activecpu < 0) ? 0 : activecpu;
2316 SETCYCLETBL(cpunum,which,new_table);
2317 }
2318
2319 /***************************************************************************
2320 Retrieve or set the value of a specific register of the active CPU
2321 ***************************************************************************/
2322
cpu_get_reg(int regnum)2323 unsigned cpu_get_reg(int regnum)
2324 {
2325 int cpunum = (activecpu < 0) ? 0 : activecpu;
2326 return GETREG(cpunum,regnum);
2327 }
2328
cpu_set_reg(int regnum,unsigned val)2329 void cpu_set_reg(int regnum, unsigned val)
2330 {
2331 int cpunum = (activecpu < 0) ? 0 : activecpu;
2332 SETREG(cpunum,regnum,val);
2333 }
2334
2335 /***************************************************************************
2336
2337 Get various CPU information
2338
2339 ***************************************************************************/
2340
2341 /***************************************************************************
2342 Returns the number of address bits for the active CPU
2343 ***************************************************************************/
cpu_address_bits(void)2344 unsigned cpu_address_bits(void)
2345 {
2346 int cpunum = (activecpu < 0) ? 0 : activecpu;
2347 return cpuintf[CPU_TYPE(cpunum)].address_bits;
2348 }
2349
2350 /***************************************************************************
2351 Returns the address bit mask for the active CPU
2352 ***************************************************************************/
cpu_address_mask(void)2353 unsigned cpu_address_mask(void)
2354 {
2355 int cpunum = (activecpu < 0) ? 0 : activecpu;
2356 return (1 << cpuintf[CPU_TYPE(cpunum)].address_bits) - 1;
2357 }
2358
2359 /***************************************************************************
2360 Returns the address shift factor for the active CPU
2361 ***************************************************************************/
cpu_address_shift(void)2362 int cpu_address_shift(void)
2363 {
2364 int cpunum = (activecpu < 0) ? 0 : activecpu;
2365 return cpuintf[CPU_TYPE(cpunum)].address_shift;
2366 }
2367
2368 /***************************************************************************
2369 Returns the endianess for the active CPU
2370 ***************************************************************************/
cpu_endianess(void)2371 unsigned cpu_endianess(void)
2372 {
2373 int cpunum = (activecpu < 0) ? 0 : activecpu;
2374 return cpuintf[CPU_TYPE(cpunum)].endianess;
2375 }
2376
2377 /***************************************************************************
2378 Returns the code align unit for the active CPU (1 byte, 2 word, ...)
2379 ***************************************************************************/
cpu_align_unit(void)2380 unsigned cpu_align_unit(void)
2381 {
2382 int cpunum = (activecpu < 0) ? 0 : activecpu;
2383 return cpuintf[CPU_TYPE(cpunum)].align_unit;
2384 }
2385
2386 /***************************************************************************
2387 Returns the max. instruction length for the active CPU
2388 ***************************************************************************/
cpu_max_inst_len(void)2389 unsigned cpu_max_inst_len(void)
2390 {
2391 int cpunum = (activecpu < 0) ? 0 : activecpu;
2392 return cpuintf[CPU_TYPE(cpunum)].max_inst_len;
2393 }
2394
2395 /***************************************************************************
2396 Returns the name for the active CPU
2397 ***************************************************************************/
cpu_name(void)2398 const char *cpu_name(void)
2399 {
2400 if( activecpu >= 0 )
2401 return CPUINFO(activecpu,NULL,CPU_INFO_NAME);
2402 return "";
2403 }
2404
2405 /***************************************************************************
2406 Returns the family name for the active CPU
2407 ***************************************************************************/
cpu_core_family(void)2408 const char *cpu_core_family(void)
2409 {
2410 if( activecpu >= 0 )
2411 return CPUINFO(activecpu,NULL,CPU_INFO_FAMILY);
2412 return "";
2413 }
2414
2415 /***************************************************************************
2416 Returns the version number for the active CPU
2417 ***************************************************************************/
cpu_core_version(void)2418 const char *cpu_core_version(void)
2419 {
2420 if( activecpu >= 0 )
2421 return CPUINFO(activecpu,NULL,CPU_INFO_VERSION);
2422 return "";
2423 }
2424
2425 /***************************************************************************
2426 Returns the core filename for the active CPU
2427 ***************************************************************************/
cpu_core_file(void)2428 const char *cpu_core_file(void)
2429 {
2430 if( activecpu >= 0 )
2431 return CPUINFO(activecpu,NULL,CPU_INFO_FILE);
2432 return "";
2433 }
2434
2435 /***************************************************************************
2436 Returns the credits for the active CPU
2437 ***************************************************************************/
cpu_core_credits(void)2438 const char *cpu_core_credits(void)
2439 {
2440 if( activecpu >= 0 )
2441 return CPUINFO(activecpu,NULL,CPU_INFO_CREDITS);
2442 return "";
2443 }
2444
2445 /***************************************************************************
2446 Returns a dissassembled instruction for the active CPU
2447 ***************************************************************************/
cpu_dasm(char * buffer,unsigned pc)2448 unsigned cpu_dasm(char *buffer, unsigned pc)
2449 {
2450 if( activecpu >= 0 )
2451 return CPUDASM(activecpu,buffer,pc);
2452 return 0;
2453 }
2454
2455 /***************************************************************************
2456 Returns a flags (state, condition codes) string for the active CPU
2457 ***************************************************************************/
cpu_flags(void)2458 const char *cpu_flags(void)
2459 {
2460 if( activecpu >= 0 )
2461 return CPUINFO(activecpu,NULL,CPU_INFO_FLAGS);
2462 return "";
2463 }
2464
2465 /***************************************************************************
2466 Returns the number of address bits for a specific CPU type
2467 ***************************************************************************/
cputype_address_bits(int cpu_type)2468 unsigned cputype_address_bits(int cpu_type)
2469 {
2470 cpu_type &= ~CPU_FLAGS_MASK;
2471 if( cpu_type < CPU_COUNT )
2472 return cpuintf[cpu_type].address_bits;
2473 return 0;
2474 }
2475
2476 /***************************************************************************
2477 Returns the address bit mask for a specific CPU type
2478 ***************************************************************************/
cputype_address_mask(int cpu_type)2479 unsigned cputype_address_mask(int cpu_type)
2480 {
2481 cpu_type &= ~CPU_FLAGS_MASK;
2482 if( cpu_type < CPU_COUNT )
2483 return (1 << cpuintf[cpu_type].address_bits) - 1;
2484 return 0;
2485 }
2486
2487 /***************************************************************************
2488 Returns the address shift factor for a specific CPU type
2489 ***************************************************************************/
cputype_address_shift(int cpu_type)2490 int cputype_address_shift(int cpu_type)
2491 {
2492 cpu_type &= ~CPU_FLAGS_MASK;
2493 if( cpu_type < CPU_COUNT )
2494 return cpuintf[cpu_type].address_shift;
2495 return 0;
2496 }
2497
2498 /***************************************************************************
2499 Returns the endianess for a specific CPU type
2500 ***************************************************************************/
cputype_endianess(int cpu_type)2501 unsigned cputype_endianess(int cpu_type)
2502 {
2503 cpu_type &= ~CPU_FLAGS_MASK;
2504 if( cpu_type < CPU_COUNT )
2505 return cpuintf[cpu_type].endianess;
2506 return 0;
2507 }
2508
2509 /***************************************************************************
2510 Returns the code align unit for a speciific CPU type (1 byte, 2 word, ...)
2511 ***************************************************************************/
cputype_align_unit(int cpu_type)2512 unsigned cputype_align_unit(int cpu_type)
2513 {
2514 cpu_type &= ~CPU_FLAGS_MASK;
2515 if( cpu_type < CPU_COUNT )
2516 return cpuintf[cpu_type].align_unit;
2517 return 0;
2518 }
2519
2520 /***************************************************************************
2521 Returns the max. instruction length for a specific CPU type
2522 ***************************************************************************/
cputype_max_inst_len(int cpu_type)2523 unsigned cputype_max_inst_len(int cpu_type)
2524 {
2525 cpu_type &= ~CPU_FLAGS_MASK;
2526 if( cpu_type < CPU_COUNT )
2527 return cpuintf[cpu_type].max_inst_len;
2528 return 0;
2529 }
2530
2531 /***************************************************************************
2532 Returns the name for a specific CPU type
2533 ***************************************************************************/
cputype_name(int cpu_type)2534 const char *cputype_name(int cpu_type)
2535 {
2536 cpu_type &= ~CPU_FLAGS_MASK;
2537 if( cpu_type < CPU_COUNT )
2538 return IFC_INFO(cpu_type,NULL,CPU_INFO_NAME);
2539 return "";
2540 }
2541
2542 /***************************************************************************
2543 Returns the family name for a specific CPU type
2544 ***************************************************************************/
cputype_core_family(int cpu_type)2545 const char *cputype_core_family(int cpu_type)
2546 {
2547 cpu_type &= ~CPU_FLAGS_MASK;
2548 if( cpu_type < CPU_COUNT )
2549 return IFC_INFO(cpu_type,NULL,CPU_INFO_FAMILY);
2550 return "";
2551 }
2552
2553 /***************************************************************************
2554 Returns the version number for a specific CPU type
2555 ***************************************************************************/
cputype_core_version(int cpu_type)2556 const char *cputype_core_version(int cpu_type)
2557 {
2558 cpu_type &= ~CPU_FLAGS_MASK;
2559 if( cpu_type < CPU_COUNT )
2560 return IFC_INFO(cpu_type,NULL,CPU_INFO_VERSION);
2561 return "";
2562 }
2563
2564 /***************************************************************************
2565 Returns the core filename for a specific CPU type
2566 ***************************************************************************/
cputype_core_file(int cpu_type)2567 const char *cputype_core_file(int cpu_type)
2568 {
2569 cpu_type &= ~CPU_FLAGS_MASK;
2570 if( cpu_type < CPU_COUNT )
2571 return IFC_INFO(cpu_type,NULL,CPU_INFO_FILE);
2572 return "";
2573 }
2574
2575 /***************************************************************************
2576 Returns the credits for a specific CPU type
2577 ***************************************************************************/
cputype_core_credits(int cpu_type)2578 const char *cputype_core_credits(int cpu_type)
2579 {
2580 cpu_type &= ~CPU_FLAGS_MASK;
2581 if( cpu_type < CPU_COUNT )
2582 return IFC_INFO(cpu_type,NULL,CPU_INFO_CREDITS);
2583 return "";
2584 }
2585
2586 /***************************************************************************
2587 Returns the number of address bits for a specific CPU number
2588 ***************************************************************************/
cpunum_address_bits(int cpunum)2589 unsigned cpunum_address_bits(int cpunum)
2590 {
2591 if( cpunum < totalcpu )
2592 return cputype_address_bits(CPU_TYPE(cpunum));
2593 return 0;
2594 }
2595
2596 /***************************************************************************
2597 Returns the address bit mask for a specific CPU number
2598 ***************************************************************************/
cpunum_address_mask(int cpunum)2599 unsigned cpunum_address_mask(int cpunum)
2600 {
2601 if( cpunum < totalcpu )
2602 return cputype_address_mask(CPU_TYPE(cpunum));
2603 return 0;
2604 }
2605
2606 /***************************************************************************
2607 Returns the endianess for a specific CPU number
2608 ***************************************************************************/
cpunum_endianess(int cpunum)2609 unsigned cpunum_endianess(int cpunum)
2610 {
2611 if( cpunum < totalcpu )
2612 return cputype_endianess(CPU_TYPE(cpunum));
2613 return 0;
2614 }
2615
2616 /***************************************************************************
2617 Returns the code align unit for the active CPU (1 byte, 2 word, ...)
2618 ***************************************************************************/
cpunum_align_unit(int cpunum)2619 unsigned cpunum_align_unit(int cpunum)
2620 {
2621 if( cpunum < totalcpu )
2622 return cputype_align_unit(CPU_TYPE(cpunum));
2623 return 0;
2624 }
2625
2626 /***************************************************************************
2627 Returns the max. instruction length for a specific CPU number
2628 ***************************************************************************/
cpunum_max_inst_len(int cpunum)2629 unsigned cpunum_max_inst_len(int cpunum)
2630 {
2631 if( cpunum < totalcpu )
2632 return cputype_max_inst_len(CPU_TYPE(cpunum));
2633 return 0;
2634 }
2635
2636 /***************************************************************************
2637 Returns the name for a specific CPU number
2638 ***************************************************************************/
cpunum_name(int cpunum)2639 const char *cpunum_name(int cpunum)
2640 {
2641 if( cpunum < totalcpu )
2642 return cputype_name(CPU_TYPE(cpunum));
2643 return "";
2644 }
2645
2646 /***************************************************************************
2647 Returns the family name for a specific CPU number
2648 ***************************************************************************/
cpunum_core_family(int cpunum)2649 const char *cpunum_core_family(int cpunum)
2650 {
2651 if( cpunum < totalcpu )
2652 return cputype_core_family(CPU_TYPE(cpunum));
2653 return "";
2654 }
2655
2656 /***************************************************************************
2657 Returns the core version for a specific CPU number
2658 ***************************************************************************/
cpunum_core_version(int cpunum)2659 const char *cpunum_core_version(int cpunum)
2660 {
2661 if( cpunum < totalcpu )
2662 return cputype_core_version(CPU_TYPE(cpunum));
2663 return "";
2664 }
2665
2666 /***************************************************************************
2667 Returns the core filename for a specific CPU number
2668 ***************************************************************************/
cpunum_core_file(int cpunum)2669 const char *cpunum_core_file(int cpunum)
2670 {
2671 if( cpunum < totalcpu )
2672 return cputype_core_file(CPU_TYPE(cpunum));
2673 return "";
2674 }
2675
2676 /***************************************************************************
2677 Returns the credits for a specific CPU number
2678 ***************************************************************************/
cpunum_core_credits(int cpunum)2679 const char *cpunum_core_credits(int cpunum)
2680 {
2681 if( cpunum < totalcpu )
2682 return cputype_core_credits(CPU_TYPE(cpunum));
2683 return "";
2684 }
2685
2686 /***************************************************************************
2687 Return a register value for a specific CPU number of the running machine
2688 ***************************************************************************/
cpunum_get_reg(int cpunum,int regnum)2689 unsigned cpunum_get_reg(int cpunum, int regnum)
2690 {
2691 int oldactive;
2692 unsigned val = 0;
2693
2694 if( cpunum == activecpu )
2695 return cpu_get_reg( regnum );
2696
2697 /* swap to the CPU's context */
2698 if (activecpu >= 0)
2699 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2700 oldactive = activecpu;
2701 activecpu = cpunum;
2702 memorycontextswap(activecpu);
2703 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2704
2705 val = GETREG(activecpu,regnum);
2706
2707 /* update the CPU's context */
2708 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2709 activecpu = oldactive;
2710 if (activecpu >= 0)
2711 {
2712 memorycontextswap(activecpu);
2713 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2714 }
2715
2716 return val;
2717 }
2718
2719 /***************************************************************************
2720 Set a register value for a specific CPU number of the running machine
2721 ***************************************************************************/
cpunum_set_reg(int cpunum,int regnum,unsigned val)2722 void cpunum_set_reg(int cpunum, int regnum, unsigned val)
2723 {
2724 int oldactive;
2725
2726 if( cpunum == activecpu )
2727 {
2728 cpu_set_reg( regnum, val );
2729 return;
2730 }
2731
2732 /* swap to the CPU's context */
2733 if (activecpu >= 0)
2734 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2735 oldactive = activecpu;
2736 activecpu = cpunum;
2737 memorycontextswap(activecpu);
2738 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2739
2740 SETREG(activecpu,regnum,val);
2741
2742 /* update the CPU's context */
2743 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2744 activecpu = oldactive;
2745 if (activecpu >= 0)
2746 {
2747 memorycontextswap(activecpu);
2748 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2749 }
2750 }
2751
2752 /***************************************************************************
2753 Return a dissassembled instruction for a specific CPU
2754 ***************************************************************************/
cpunum_dasm(int cpunum,char * buffer,unsigned pc)2755 unsigned cpunum_dasm(int cpunum,char *buffer,unsigned pc)
2756 {
2757 unsigned result;
2758 int oldactive;
2759
2760 if( cpunum == activecpu )
2761 return cpu_dasm(buffer,pc);
2762
2763 /* swap to the CPU's context */
2764 if (activecpu >= 0)
2765 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2766 oldactive = activecpu;
2767 activecpu = cpunum;
2768 memorycontextswap(activecpu);
2769 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2770
2771 result = CPUDASM(activecpu,buffer,pc);
2772
2773 /* update the CPU's context */
2774 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2775 activecpu = oldactive;
2776 if (activecpu >= 0)
2777 {
2778 memorycontextswap(activecpu);
2779 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2780 }
2781
2782 return result;
2783 }
2784
2785 /***************************************************************************
2786 Return a flags (state, condition codes) string for a specific CPU
2787 ***************************************************************************/
cpunum_flags(int cpunum)2788 const char *cpunum_flags(int cpunum)
2789 {
2790 const char *result;
2791 int oldactive;
2792
2793 if( cpunum == activecpu )
2794 return cpu_flags();
2795
2796 /* swap to the CPU's context */
2797 if (activecpu >= 0)
2798 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2799 oldactive = activecpu;
2800 activecpu = cpunum;
2801 memorycontextswap(activecpu);
2802 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2803
2804 result = CPUINFO(activecpu,NULL,CPU_INFO_FLAGS);
2805
2806 /* update the CPU's context */
2807 if (cpu[activecpu].save_context) GETCONTEXT(activecpu, cpu[activecpu].context);
2808 activecpu = oldactive;
2809 if (activecpu >= 0)
2810 {
2811 memorycontextswap(activecpu);
2812 if (cpu[activecpu].save_context) SETCONTEXT(activecpu, cpu[activecpu].context);
2813 }
2814
2815 return result;
2816 }
2817
2818 /***************************************************************************
2819
2820 Dummy interfaces for non-CPUs
2821
2822 ***************************************************************************/
Dummy_reset(void * param)2823 static void Dummy_reset(void *param) { }
Dummy_exit(void)2824 static void Dummy_exit(void) { }
Dummy_execute(int cycles)2825 static int Dummy_execute(int cycles) { return cycles; }
2826 //static void Dummy_burn(int cycles) { }
Dummy_get_context(void * regs)2827 static unsigned Dummy_get_context(void *regs) { return 0; }
Dummy_set_context(void * regs)2828 static void Dummy_set_context(void *regs) { }
Dummy_get_pc(void)2829 static unsigned Dummy_get_pc(void) { return 0; }
Dummy_set_pc(unsigned val)2830 static void Dummy_set_pc(unsigned val) { }
Dummy_get_sp(void)2831 static unsigned Dummy_get_sp(void) { return 0; }
Dummy_set_sp(unsigned val)2832 static void Dummy_set_sp(unsigned val) { }
Dummy_get_reg(int regnum)2833 static unsigned Dummy_get_reg(int regnum) { return 0; }
Dummy_set_reg(int regnum,unsigned val)2834 static void Dummy_set_reg(int regnum, unsigned val) { }
Dummy_set_nmi_line(int state)2835 static void Dummy_set_nmi_line(int state) { }
Dummy_set_irq_line(int irqline,int state)2836 static void Dummy_set_irq_line(int irqline, int state) { }
Dummy_set_irq_callback(int (* callback)(int irqline))2837 static void Dummy_set_irq_callback(int (*callback)(int irqline)) { }
2838
2839 /****************************************************************************
2840 * Return a formatted string for a register
2841 ****************************************************************************/
Dummy_info(void * context,int regnum)2842 static const char *Dummy_info(void *context, int regnum)
2843 {
2844 if( !context && regnum )
2845 return "";
2846
2847 switch (regnum)
2848 {
2849 case CPU_INFO_NAME: return "Dummy";
2850 case CPU_INFO_FAMILY: return "no CPU";
2851 case CPU_INFO_VERSION: return "0.0";
2852 case CPU_INFO_FILE: return __FILE__;
2853 case CPU_INFO_CREDITS: return "The MAME team.";
2854 }
2855 return "";
2856 }
2857
Dummy_dasm(char * buffer,unsigned pc)2858 static unsigned Dummy_dasm(char *buffer, unsigned pc)
2859 {
2860 strcpy(buffer, "???");
2861 return 1;
2862 }
2863
2864