1 /*
2 Mitsubishi M37702/37710 CPU Emulator
3
4 The 7700 series is based on the WDC 65C816 core, with the following
5 notable changes:
6
7 - Second accumulator called "B" (on the 65816, "A" and "B" were the
8 two 8-bit halves of the 16-bit "C" accumulator).
9 - 6502 emulation mode and XCE instruction are not present.
10 - No NMI line. BRK and the watchdog interrupt are non-maskable, but there
11 is no provision for the traditional 6502/65816 NMI line.
12 - 3-bit interrupt priority levels like the 68000. Interrupts in general
13 are very different from the 65816.
14 - New single-instruction immediate-to-memory move instructions (LDM)
15 replaces STZ.
16 - CLM and SEM (clear and set "M" status bit) replace CLD/SED. Decimal
17 mode is still available via REP/SEP instructions.
18 - INC and DEC (0x1A and 0x3A) switch places for no particular reason.
19 - The microcode bug that caused MVN/NVP to take 2 extra cycles per byte
20 on the 65816 seems to have been fixed.
21 - The WDM (0x42) and BIT immediate (0x89) instructions are now prefixes.
22 0x42 when used before an instruction involving the A accumulator makes
23 it use the B accumulator instead. 0x89 adds multiply and divide
24 opcodes, which the real 65816 doesn't have.
25 - The 65C816 preserves the upper 8 bits of A when in 8-bit M mode, but
26 not the upper 8 bits of X or Y when in 8-bit X. The 7700 preserves
27 the top bits of all registers in all modes (code in the C74 BIOS
28 starting at d881 requires this!).
29
30 The various 7700 series models differ primarily by their on board
31 peripherals. The 7750 and later models do include some additional
32 instructions, vs. the 770x/1x/2x, notably signed multiply/divide and
33 sign extension opcodes.
34
35 Peripherals common across the 7700 series include: programmable timers,
36 digital I/O ports, and analog to digital converters.
37
38 Reference: 7700 Family Software User's Manual (instruction set)
39 7702/7703 Family User's Manual (on-board peripherals)
40 7720 Family User's Manual
41
42 Emulator by R. Belmont.
43 Based on G65816 Emulator by Karl Stenrud.
44
45 History:
46 - v1.0 RB First version, basic operation OK, timers not complete
47 - v1.1 RB Data bus is 16-bit, dozens of bugfixes to IRQs, opcodes,
48 and opcode mapping. New opcodes added, internal timers added.
49 - v1.2 RB Fixed execution outside of bank 0, fixed LDM outside of bank 0,
50 fixed so top 8 bits of X & Y are preserved while in 8-bit mode,
51 added save state support.
52 */
53
54 #include "burnint.h"
55 #include "driver.h"
56 #include "m37710.h"
57 #include "m377_intf.h"
58
59 #define M37710_DEBUG (0) // enables verbose logging for peripherals, etc.
60
61 // forwards
62 static void m37710_clock_timers(INT32 clkcnt);
63 static void m37710i_interrupt_software(UINT32 vector);
64 static void m37710i_set_execution_mode(UINT32 mode);
65 static void m37710_set_irq_line(int line, int state);
66 static void m37710i_update_irqs();
67 static void m37710_internal_w(int offset, UINT8 data);
68 static UINT8 m37710_internal_r(int offset);
69 void m37710i_set_reg_p(UINT32 value);
70
71 // FBNeo notes:
72 // Regs & Internal RAM are auto-mapped by this core @ init.
73 //
74 // M37710
75 // Internal regs mapped @ 0x000000 - 0x00007f
76 // Internal RAM mapped @ 0x000080 - 0x00087f
77 //
78 // M37702
79 // Internal regs mapped @ 0x000000 - 0x00007f
80 // Internal RAM mapped @ 0x000080 - 0x00027f
81 //
82 // Can be mapped externally using M377MapMemory():
83 // Internal ROM resides @ 0x00c000 - 0x00ffff
84
85 #define page_size 0x80
86 #define page_mask 0x7f
87 #define address_mask 0xffffff
88
89 static UINT8 **mem[3];
90 static UINT8 *mem_flags;
91 static UINT8 *internal_ram = NULL;
92
93 #define MEM_ENDISWAP 1 // mem_flags
94
95 static UINT8 (*M377_read8)(UINT32) = NULL;
96 static UINT16 (*M377_read16)(UINT32) = NULL;
97 static void (*M377_write8)(UINT32,UINT8) = NULL;
98 static void (*M377_write16)(UINT32,UINT16) = NULL;
99
100 static UINT8 (*M377_ioread8)(UINT32) = NULL;
101 static void (*M377_iowrite8)(UINT32,UINT8) = NULL;
102
M377SetWritePortHandler(void (* write)(UINT32,UINT8))103 void M377SetWritePortHandler(void (*write)(UINT32,UINT8))
104 {
105 M377_iowrite8 = write;
106 }
107
M377SetReadPortHandler(UINT8 (* read)(UINT32))108 void M377SetReadPortHandler(UINT8 (*read)(UINT32))
109 {
110 M377_ioread8 = read;
111 }
112
M377SetWriteByteHandler(void (* write)(UINT32,UINT8))113 void M377SetWriteByteHandler(void (*write)(UINT32,UINT8))
114 {
115 M377_write8 = write;
116 }
117
M377SetWriteWordHandler(void (* write)(UINT32,UINT16))118 void M377SetWriteWordHandler(void (*write)(UINT32,UINT16))
119 {
120 M377_write16 = write;
121 }
122
M377SetReadByteHandler(UINT8 (* read)(UINT32))123 void M377SetReadByteHandler(UINT8 (*read)(UINT32))
124 {
125 M377_read8 = read;
126 }
127
M377SetReadWordHandler(UINT16 (* read)(UINT32))128 void M377SetReadWordHandler(UINT16 (*read)(UINT32))
129 {
130 M377_read16 = read;
131 }
132
M377MapMemory(UINT8 * ptr,UINT32 start,UINT32 end,UINT32 flags)133 void M377MapMemory(UINT8 *ptr, UINT32 start, UINT32 end, UINT32 flags)
134 {
135 for (UINT32 i = start; i < end; i+= page_size)
136 {
137 if (flags & 1) mem[0][i/page_size] = (ptr == NULL) ? NULL : (ptr + (i - start));
138 if (flags & 2) mem[1][i/page_size] = (ptr == NULL) ? NULL : (ptr + (i - start));
139 if (flags & 4) mem[2][i/page_size] = (ptr == NULL) ? NULL : (ptr + (i - start));
140 mem_flags[i/page_size] = (flags & 0x8000) ? MEM_ENDISWAP : 0;
141 }
142 }
143
io_read_byte(UINT32 a)144 static UINT8 io_read_byte(UINT32 a)
145 {
146 if (M377_ioread8) {
147 return M377_ioread8(a);
148 }
149
150 return 0;
151 }
152
io_write_byte(UINT32 a,UINT8 d)153 static void io_write_byte(UINT32 a, UINT8 d)
154 {
155 if (M377_iowrite8) {
156 return M377_iowrite8(a,d);
157 }
158 }
159
160 #define ENDISWAP16(x) (((x >> 8) & 0xff) | ((x << 8) & 0xff00))
161
program_read_word_16le(UINT32 a)162 static UINT16 program_read_word_16le(UINT32 a)
163 {
164 a &= address_mask;
165
166 // Internal Registers
167 if (a < 0x80) {
168 UINT16 ret;
169 ret = (m37710_internal_r(a + 0) << 0) & 0x00ff;
170 ret |= (m37710_internal_r(a + 1) << 8) & 0xff00;
171 return ret;
172 }
173
174 UINT8 *p = mem[0][a / page_size];
175
176 if (p) {
177 if (a & 1) { // not word-aligned, let M377ReadByte() handle the ENDI swapping
178 UINT16 rv;
179 rv = (M377ReadByte(a + 0) << 0) & 0x00ff;
180 rv |= (M377ReadByte(a + 1) << 8) & 0xff00;
181 return rv;
182 }
183
184 UINT8 flag = mem_flags[a / page_size];
185
186 UINT16 *z = (UINT16*)(p + (a & page_mask));
187 #ifdef LOG_MEM
188 bprintf (0, _T("PRW: %6.6x %4.4x\n"), a, *z);
189 #endif
190
191 #ifdef LSB_FIRST
192 return (flag & MEM_ENDISWAP) ? ENDISWAP16(*z) : *z;
193 #else
194 //printf("C 0x%x - flag: %d\n", (flag & MEM_ENDISWAP) ? *z : BURN_ENDIAN_SWAP_INT16(*z), flag);
195 return (flag & MEM_ENDISWAP) ? *z : BURN_ENDIAN_SWAP_INT16(*z);
196 #endif
197 }
198
199 if (M377_read16) {
200 #ifdef LOG_MEM
201 bprintf (0, _T("PRW: %6.6x %4.4x\n"), a, M377_read16(a));
202 #endif
203 return M377_read16(a);
204 }
205
206 return 0xffff;
207 }
208
program_read_byte_16le(UINT32 a)209 static UINT8 program_read_byte_16le(UINT32 a)
210 {
211 a &= address_mask;
212
213 // Internal Registers
214 if (a < 0x80) {
215 return m37710_internal_r(a);
216 }
217
218 #ifdef LOG_MEM
219 bprintf (0, _T("PRB: %6.6x\n"), a);
220 #endif
221
222 if (mem[0][a / page_size]) {
223 UINT8 flag = mem_flags[a / page_size] & MEM_ENDISWAP;
224
225 return mem[0][a / page_size][(a ^ flag) & page_mask];
226 }
227
228 if (M377_read8) {
229 return M377_read8(a);
230 }
231
232 return 0xff;
233 }
234
program_write_word_16le(UINT32 a,UINT16 d)235 static void program_write_word_16le(UINT32 a, UINT16 d)
236 {
237 a &= address_mask;
238
239 // Internal Registers
240 if (a < 0x80) {
241 m37710_internal_w(a + 0, (d >> 0) & 0xff);
242 m37710_internal_w(a + 1, (d >> 8) & 0xff);
243 return;
244 }
245
246 #ifdef LOG_MEM
247 bprintf (0, _T("PWW: %6.6x %4.4x\n"), a,d);
248 #endif
249
250 UINT8 *p = mem[1][a / page_size];
251
252 if (p) {
253 if (a & 1) {
254 M377WriteByte(a + 0, (d >> 0) & 0xff);
255 M377WriteByte(a + 1, (d >> 8) & 0xff);
256 return;
257 }
258 UINT8 flag = mem_flags[a / page_size];
259 UINT16 *z = (UINT16*)(p + (a & page_mask));
260 #ifdef LSB_FIRST
261 *z = (flag & MEM_ENDISWAP) ? ENDISWAP16(d) : d;
262 #else
263 * z = (flag & MEM_ENDISWAP) ? d : BURN_ENDIAN_SWAP_INT16(d);
264 #endif
265 return;
266 }
267
268 if (M377_write16) {
269 M377_write16(a,d);
270 return;
271 }
272 }
273
program_write_byte_16le(UINT32 a,UINT8 d)274 static void program_write_byte_16le(UINT32 a, UINT8 d)
275 {
276 a &= address_mask;
277
278 // Internal Registers
279 if (a < 0x80) {
280 m37710_internal_w(a, d);
281 return;
282 }
283
284 #ifdef LOG_MEM
285 bprintf (0, _T("PWB: %6.6x %2.2x\n"), a,d);
286 #endif
287
288 if (mem[1][a / page_size]) {
289 UINT8 flag = mem_flags[a / page_size] & MEM_ENDISWAP;
290 mem[1][a / page_size][(a ^ flag) & page_mask] = d;
291 return;
292 }
293
294 if (M377_write8) {
295 return M377_write8(a,d);
296 }
297 }
298
M377WriteWord(UINT32 address,UINT16 data)299 void M377WriteWord(UINT32 address, UINT16 data)
300 {
301 program_write_word_16le(address, data);
302 }
303
M377WriteByte(UINT32 address,UINT8 data)304 void M377WriteByte(UINT32 address, UINT8 data)
305 {
306 program_write_byte_16le(address, data);
307 }
308
M377ReadWord(UINT32 address)309 UINT16 M377ReadWord(UINT32 address)
310 {
311 return program_read_word_16le(address);
312 }
313
M377ReadByte(UINT32 address)314 UINT8 M377ReadByte(UINT32 address)
315 {
316 return program_read_byte_16le(address);
317 }
318
core_set_irq(INT32,INT32 line,INT32 state)319 static void core_set_irq(INT32 /*cpu*/, INT32 line, INT32 state)
320 {
321 M377SetIRQLine(line, state);
322 }
323
324 cpu_core_config M377Config =
325 {
326 "M377xx",
327 M377Open,
328 M377Close,
329 M377ReadByte,
330 M377WriteByte, //M377WriteROM,
331 M377GetActive,
332 M377TotalCycles,
333 M377NewFrame,
334 M377Idle,
335 core_set_irq,
336 M377Run,
337 M377RunEnd,
338 M377Reset,
339 0x1000000,
340 0
341 };
342
343 struct m377_struct {
344 UINT32 a; /* Accumulator */
345 UINT32 b; /* holds high byte of accumulator */
346 UINT32 ba; /* Secondary Accumulator */
347 UINT32 bb; /* holds high byte of secondary accumulator */
348 UINT32 x; /* Index Register X */
349 UINT32 y; /* Index Register Y */
350 UINT32 xh; /* holds high byte of x */
351 UINT32 yh; /* holds high byte of y */
352 UINT32 s; /* Stack Pointer */
353 UINT32 pc; /* Program Counter */
354 UINT32 ppc; /* Previous Program Counter */
355 UINT32 pb; /* Program Bank (shifted left 16) */
356 UINT32 db; /* Data Bank (shifted left 16) */
357 UINT32 d; /* Direct Register */
358 UINT32 flag_e; /* Emulation Mode Flag */
359 UINT32 flag_m; /* Memory/Accumulator Select Flag */
360 UINT32 flag_x; /* Index Select Flag */
361 UINT32 flag_n; /* Negative Flag */
362 UINT32 flag_v; /* Overflow Flag */
363 UINT32 flag_d; /* Decimal Mode Flag */
364 UINT32 flag_i; /* Interrupt Mask Flag */
365 UINT32 flag_z; /* Zero Flag (inverted) */
366 UINT32 flag_c; /* Carry Flag */
367 UINT32 line_irq; /* Bitmask of pending IRQs */
368 UINT32 ipl; /* Interrupt priority level (top of PSW) */
369 UINT32 ir; /* Instruction Register */
370 UINT32 im; /* Immediate load value */
371 UINT32 im2; /* Immediate load target */
372 UINT32 im3; /* Immediate load target */
373 UINT32 im4; /* Immediate load target */
374 UINT32 irq_delay; /* delay 1 instruction before checking irq */
375 UINT32 irq_level; /* irq level */
376 INT32 ICount; /* cycle count */
377 UINT32 source; /* temp register */
378 UINT32 destination; /* temp register */
379 UINT32 stopped; /* Sets how the CPU is stopped */
380
381 // on-board peripheral stuff
382 UINT8 m37710_regs[128];
383 INT32 reload[8+1]; // reload[8] / timers[8] = adc
384 INT32 timers[8+1];
385
386 // for debugger
387 UINT32 debugger_pc;
388 UINT32 debugger_pb;
389 UINT32 debugger_db;
390 UINT32 debugger_p;
391 UINT32 debugger_a;
392 UINT32 debugger_b;
393
394 // DINK
395 INT32 end_run;
396 INT32 total_cycles;
397 INT32 segment_cycles;
398 INT32 subtype; // M37710 / M37702 (defined in m377_intf.h)
399 };
400
401 static m377_struct m377; // cpu!
402
403 // Statics
404 typedef void (*opcode_func)();
405 typedef UINT32 (*get_reg_func)(int regnum);
406 typedef void (*set_reg_func)(int regnum, UINT32 val);
407 typedef void (*set_line_func)(int line, int state);
408 typedef int (*execute_func)(int cycles);
409 typedef void (*set_flag_func)(UINT32 value);
410
411 static const opcode_func *m_opcodes; /* opcodes with no prefix */
412 static const opcode_func *m_opcodes42; /* opcodes with 0x42 prefix */
413 static const opcode_func *m_opcodes89; /* opcodes with 0x89 prefix */
414 static get_reg_func m_get_reg;
415 static set_reg_func m_set_reg;
416 static set_line_func m_set_line;
417 static execute_func m_execute;
418 static set_flag_func m_setflag;
419
420 /* interrupt control mapping */
421
422 static const int m37710_irq_levels[M37710_LINE_MAX] =
423 {
424 // maskable
425 0x70, // ADC 0
426 0x73, // UART 1 XMIT 1
427 0x74, // UART 1 RECV 2
428 0x71, // UART 0 XMIT 3
429 0x72, // UART 0 RECV 4
430 0x7c, // Timer B2 5
431 0x7b, // Timer B1 6
432 0x7a, // Timer B0 7
433 0x79, // Timer A4 8
434 0x78, // Timer A3 9
435 0x77, // Timer A2 10
436 0x76, // Timer A1 11
437 0x75, // Timer A0 12
438 0x7f, // IRQ 2 13
439 0x7e, // IRQ 1 14
440 0x7d, // IRQ 0 15
441
442 // non-maskable
443 0, // watchdog
444 0, // debugger control
445 0, // BRK
446 0, // divide by zero
447 0, // reset
448 };
449
450 static const int m37710_irq_vectors[M37710_LINE_MAX] =
451 {
452 // maskable
453 0xffd6, // A-D converter
454 0xffd8, // UART1 transmit
455 0xffda, // UART1 receive
456 0xffdc, // UART0 transmit
457 0xffde, // UART0 receive
458 0xffe0, // Timer B2
459 0xffe2, // Timer B1
460 0xffe4, // Timer B0
461 0xffe6, // Timer A4
462 0xffe8, // Timer A3
463 0xffea, // Timer A2
464 0xffec, // Timer A1
465 0xffee, // Timer A0
466 0xfff0, // external INT2 pin
467 0xfff2, // external INT1 pin
468 0xfff4, // external INT0 pin
469
470 // non-maskable
471 0xfff6, // watchdog timer
472 0xfff8, // debugger control (not used in shipping ICs?)
473 0xfffa, // BRK
474 0xfffc, // divide by zero
475 0xfffe, // RESET
476 };
477
478 // M37710 internal peripherals
479
480 static const char *const m37710_rnames[128] =
481 {
482 "",
483 "",
484 "Port P0 reg",
485 "Port P1 reg",
486 "Port P0 dir reg",
487 "Port P1 dir reg",
488 "Port P2 reg",
489 "Port P3 reg",
490 "Port P2 dir reg",
491 "Port P3 dir reg",
492 "Port P4 reg",
493 "Port P5 reg",
494 "Port P4 dir reg",
495 "Port P5 dir reg",
496 "Port P6 reg",
497 "Port P7 reg",
498 "Port P6 dir reg", // 16 (0x10)
499 "Port P7 dir reg",
500 "Port P8 reg",
501 "",
502 "Port P8 dir reg",
503 "",
504 "",
505 "",
506 "",
507 "",
508 "",
509 "",
510 "",
511 "",
512 "A/D control reg",
513 "A/D sweep pin select",
514 "A/D 0", // 32 (0x20)
515 "",
516 "A/D 1",
517 "",
518 "A/D 2",
519 "",
520 "A/D 3",
521 "",
522 "A/D 4",
523 "",
524 "A/D 5",
525 "",
526 "A/D 6",
527 "",
528 "A/D 7",
529 "",
530 "UART0 transmit/recv mode", // 48 (0x30)
531 "UART0 baud rate", // 0x31
532 "UART0 transmit buf L", // 0x32
533 "UART0 transmit buf H", // 0x33
534 "UART0 transmit/recv ctrl 0", // 0x34
535 "UART0 transmit/recv ctrl 1", // 0x35
536 "UART0 recv buf L", // 0x36
537 "UART0 recv buf H", // 0x37
538 "UART1 transmit/recv mode", // 0x38
539 "UART1 baud rate",
540 "UART1 transmit buf L",
541 "UART1 transmit buf H",
542 "UART1 transmit/recv ctrl 0",
543 "UART1 transmit/recv ctrl 1",
544 "UART1 recv buf L",
545 "UART1 recv buf H",
546 "Count start", // 0x40
547 "",
548 "One-shot start",
549 "",
550 "Up-down register",
551 "",
552 "Timer A0 L", // 0x46
553 "Timer A0 H",
554 "Timer A1 L",
555 "Timer A1 H",
556 "Timer A2 L",
557 "Timer A2 H",
558 "Timer A3 L",
559 "Timer A3 H",
560 "Timer A4 L",
561 "Timer A4 H",
562 "Timer B0 L",
563 "Timer B0 H", // 0x50
564 "Timer B1 L",
565 "Timer B1 H",
566 "Timer B2 L",
567 "Timer B2 H",
568 "Timer A0 mode",
569 "Timer A1 mode",
570 "Timer A2 mode",
571 "Timer A3 mode",
572 "Timer A4 mode",
573 "Timer B0 mode",
574 "Timer B1 mode",
575 "Timer B2 mode",
576 "Processor mode",
577 "",
578 "Watchdog reset", // 0x60
579 "Watchdog frequency", // 0x61
580 "",
581 "",
582 "",
583 "",
584 "",
585 "",
586 "",
587 "",
588 "",
589 "",
590 "",
591 "",
592 "",
593 "",
594 "A/D IRQ ctrl",
595 "UART0 xmit IRQ ctrl", // 0x70
596 "UART0 recv IRQ ctrl",
597 "UART1 xmit IRQ ctrl",
598 "UART1 recv IRQ ctrl",
599 "Timer A0 IRQ ctrl", // 0x74
600 "Timer A1 IRQ ctrl", // 0x75
601 "Timer A2 IRQ ctrl", // 0x76
602 "Timer A3 IRQ ctrl",
603 "Timer A4 IRQ ctrl", // 0x78
604 "Timer B0 IRQ ctrl",
605 "Timer B1 IRQ ctrl",
606 "Timer B2 IRQ ctrl",
607 "INT0 IRQ ctrl",
608 "INT1 IRQ ctrl",
609 "INT2 IRQ ctrl",
610 };
611
612 static const char *const m37710_tnames[8] =
613 {
614 "A0", "A1", "A2", "A3", "A4", "B0", "B1", "B2"
615 };
616
617 #include "m37710cm.h"
618 #include "m37710il.h"
619
620 #define EXECUTION_MODE EXECUTION_MODE_M0X0
621 #include "m37710op.h"
622 #undef EXECUTION_MODE
623 #define EXECUTION_MODE EXECUTION_MODE_M0X1
624 #include "m37710op.h"
625 #undef EXECUTION_MODE
626 #define EXECUTION_MODE EXECUTION_MODE_M1X0
627 #include "m37710op.h"
628 #undef EXECUTION_MODE
629 #define EXECUTION_MODE EXECUTION_MODE_M1X1
630 #include "m37710op.h"
631 #undef EXECUTION_MODE
632
633
m37710_timer_cb(INT32 param)634 static void m37710_timer_cb(INT32 param)
635 {
636 int which = param;
637 int curirq = M37710_LINE_TIMERA0 - which;
638
639 m377.timers[which] = m377.reload[which];
640
641 m37710_set_irq_line(curirq, HOLD_LINE);
642 }
643
m37710_external_tick(int timer,int state)644 static void m37710_external_tick(int timer, int state)
645 {
646 // we only care if the state is "on"
647 if (!state)
648 {
649 return;
650 }
651
652 // check if enabled
653 if (m377.m37710_regs[0x40] & (1<<timer))
654 {
655 if ((m377.m37710_regs[0x56+timer] & 0x3) == 1)
656 {
657 if (m377.m37710_regs[0x46+(timer*2)] == 0xff)
658 {
659 m377.m37710_regs[0x46+(timer*2)] = 0;
660 m377.m37710_regs[0x46+(timer*2)+1]++;
661 }
662 else
663 {
664 m377.m37710_regs[0x46+(timer*2)]++;
665 }
666 }
667 else
668 {
669 logerror("M37710: external tick for timer %d, not in event counter mode!\n", timer);
670 }
671 }
672 }
673
m37710_recalc_timer(int timer)674 static void m37710_recalc_timer(int timer)
675 {
676 int tval;
677 INT32 time;
678 static const int tscales[4] = { 2, 16, 64, 512 };
679
680 // check if enabled
681 if (m377.m37710_regs[0x40] & (1<<timer))
682 {
683 #if M37710_DEBUG
684 logerror("Timer %d (%s) is enabled\n", timer, m37710_tnames[timer]);
685 #endif
686
687 // set the timer's value
688 tval = m377.m37710_regs[0x46+(timer*2)] | (m377.m37710_regs[0x47+(timer*2)]<<8);
689
690 // HACK: ignore if timer is 8MHz (MAME slows down to a crawl)
691 if (tval == 0 && (m377.m37710_regs[0x56+timer]&0xc0) == 0) return;
692
693 // check timer's mode
694 // modes are slightly different between timer groups A and B
695 if (timer < 5)
696 {
697 switch (m377.m37710_regs[0x56+timer] & 0x3)
698 {
699 case 0: // timer mode
700 //time = attotime::from_hz(unscaled_clock()) * tscales[m377.m37710_regs[0x56+timer]>>6];
701 time = tscales[m377.m37710_regs[0x56+timer]>>6];
702 time *= (tval + 1);
703 time /= 2; // cpu internal divider
704
705 #if M37710_DEBUG
706 logerror("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double());
707 #endif
708 //bprintf(0, _T("Timer %d in timer mode, %d Hz\n"), timer, time);
709 //m377.timers[timer]->adjust(time, timer);
710 m377.timers[timer] = time;
711 m377.reload[timer] = time;
712 break;
713
714 case 1: // event counter mode
715 #if M37710_DEBUG
716 logerror("Timer %d in event counter mode\n", timer);
717 #endif
718 break;
719
720 case 2: // one-shot pulse mode
721 #if M37710_DEBUG
722 logerror("Timer %d in one-shot mode\n", timer);
723 #endif
724 break;
725
726 case 3: // PWM mode
727 #if M37710_DEBUG
728 logerror("Timer %d in PWM mode\n", timer);
729 #endif
730 break;
731 }
732 }
733 else
734 {
735 switch (m377.m37710_regs[0x56+timer] & 0x3)
736 {
737 case 0: // timer mode
738 time = tscales[m377.m37710_regs[0x56+timer]>>6];
739 time *= (tval + 1);
740 time /= 2; // cpu internal divider
741
742 #if M37710_DEBUG
743 logerror("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double());
744 #endif
745 //bprintf(0, _T("Timer %d in timer mode, %d Hz\n"), timer, 1.0 / time);
746
747 m377.timers[timer] = time;
748 m377.reload[timer] = time;
749 break;
750
751 case 1: // event counter mode
752 #if M37710_DEBUG
753 logerror("Timer %d in event counter mode\n", timer);
754 #endif
755 break;
756
757 case 2: // pulse period/pulse width measurement mode
758 #if M37710_DEBUG
759 logerror("Timer %d in pulse period/width measurement mode\n", timer);
760 #endif
761 break;
762
763 case 3:
764 #if M37710_DEBUG
765 logerror("Timer %d in unknown mode!\n", timer);
766 #endif
767 break;
768 }
769 }
770 }
771 }
772
m37710_adc_cb()773 static void m37710_adc_cb()
774 {
775 INT32 line = m377.m37710_regs[0x1e] & 0x07;
776 if (m377.m37710_regs[0x1e] & 0x10) {
777 m377.m37710_regs[0x1e] = (m377.m37710_regs[0x1e] & 0xf8) | ((line + 1) & 0x07);
778 }
779
780 if (m377.m37710_regs[0x1e] & 0x08 || ((m377.m37710_regs[0x1e] & 0x10) && line != (m377.m37710_regs[0x1f] & 0x03) * 2 + 1)) {
781 m377.timers[8] = 0x72 * ((m377.m37710_regs[0x1e] & 0x80) ? 2 : 4);
782 } else {
783 M377SetIRQLine(M37710_LINE_ADC, CPU_IRQSTATUS_HOLD);
784 m377.m37710_regs[0x1e] &= 0xbf;
785 }
786 }
787
788
m37710_internal_r(int offset)789 static UINT8 m37710_internal_r(int offset)
790 {
791 UINT8 d;
792
793 #if M37710_DEBUG
794 if (offset > 1)
795 logerror("m37710_internal_r from %02x: %s (PC=%x)\n", (int)offset, m37710_rnames[(int)offset], REG_PB<<16 | REG_PC);
796 #endif
797 //if (offset > 1)
798 // bprintf(0, _T("m37710_internal_r from %02x: %S (PC=%x)\n"), (int)offset, m37710_rnames[(int)offset], REG_PB<<16 | REG_PC);
799
800 switch (offset)
801 {
802 // ports
803 case 0x02: // p0
804 d = m377.m37710_regs[0x04];
805 if (d != 0xff)
806 return (io_read_byte(M37710_PORT0)&~d) | (m377.m37710_regs[offset]&d);
807 break;
808 case 0x03: // p1
809 d = m377.m37710_regs[0x05];
810 if (d != 0xff)
811 return (io_read_byte(M37710_PORT1)&~d) | (m377.m37710_regs[offset]&d);
812 break;
813 case 0x06: // p2
814 d = m377.m37710_regs[0x08];
815 if (d != 0xff)
816 return (io_read_byte(M37710_PORT2)&~d) | (m377.m37710_regs[offset]&d);
817 break;
818 case 0x07: // p3
819 d = m377.m37710_regs[0x09];
820 if (d != 0xff)
821 return (io_read_byte(M37710_PORT3)&~d) | (m377.m37710_regs[offset]&d);
822 break;
823 case 0x0a: // p4
824 d = m377.m37710_regs[0x0c];
825 if (d != 0xff)
826 return (io_read_byte(M37710_PORT4)&~d) | (m377.m37710_regs[offset]&d);
827 break;
828 case 0x0b: // p5
829 d = m377.m37710_regs[0x0d];
830 if (d != 0xff)
831 return (io_read_byte(M37710_PORT5)&~d) | (m377.m37710_regs[offset]&d);
832 break;
833 case 0x0e: // p6
834 d = m377.m37710_regs[0x10];
835 if (d != 0xff)
836 return (io_read_byte(M37710_PORT6)&~d) | (m377.m37710_regs[offset]&d);
837 break;
838 case 0x0f: // p7
839 d = m377.m37710_regs[0x11];
840 if (d != 0xff)
841 return (io_read_byte(M37710_PORT7)&~d) | (m377.m37710_regs[offset]&d);
842 break;
843 case 0x12: // p8
844 d = m377.m37710_regs[0x14];
845 if (d != 0xff)
846 return (io_read_byte(M37710_PORT8)&~d) | (m377.m37710_regs[offset]&d);
847 break;
848
849 // A-D regs
850 case 0x20:
851 return io_read_byte(M37710_ADC0_L);
852 case 0x21:
853 return io_read_byte(M37710_ADC0_H);
854 case 0x22:
855 return io_read_byte(M37710_ADC1_L);
856 case 0x23:
857 return io_read_byte(M37710_ADC1_H);
858 case 0x24:
859 return io_read_byte(M37710_ADC2_L);
860 case 0x25:
861 return io_read_byte(M37710_ADC2_H);
862 case 0x26:
863 return io_read_byte(M37710_ADC3_L);
864 case 0x27:
865 return io_read_byte(M37710_ADC3_H);
866 case 0x28:
867 return io_read_byte(M37710_ADC4_L);
868 case 0x29:
869 return io_read_byte(M37710_ADC4_H);
870 case 0x2a:
871 return io_read_byte(M37710_ADC5_L);
872 case 0x2b:
873 return io_read_byte(M37710_ADC5_H);
874 case 0x2c:
875 return io_read_byte(M37710_ADC6_L);
876 case 0x2d:
877 return io_read_byte(M37710_ADC6_H);
878 case 0x2e:
879 return io_read_byte(M37710_ADC7_L);
880 case 0x2f:
881 return io_read_byte(M37710_ADC7_H);
882
883 // UART control (not hooked up yet)
884 case 0x34: case 0x3c:
885 return 0x08;
886 case 0x35: case 0x3d:
887 return 0xff;
888
889 // A-D IRQ control (also not properly hooked up yet)
890 case 0x70:
891 return m377.m37710_regs[offset] | 8;
892
893 default:
894 return m377.m37710_regs[offset];
895 }
896
897 return m377.m37710_regs[offset];
898 }
899
m37710_internal_w(int offset,UINT8 data)900 static void m37710_internal_w(int offset, UINT8 data)
901 {
902 int i;
903 UINT8 prevdata;
904 UINT8 d;
905
906 #if M37710_DEBUG
907 if (offset != 0x60) // filter out watchdog
908 logerror("m37710_internal_w %x to %02x: %s = %x\n", data, (int)offset, m37710_rnames[(int)offset], m377.m37710_regs[offset]);
909 #endif
910 //if (offset != 0x60) // filter out watchdog
911 // bprintf(0, _T("m37710_internal_w %x to %02x: %S = %x\n"), data, (int)offset, m37710_rnames[(int)offset], m377.m37710_regs[offset]);
912
913 prevdata = m377.m37710_regs[offset];
914 m377.m37710_regs[offset] = data;
915
916 switch(offset)
917 {
918 // ports
919 case 0x02: // p0
920 d = m377.m37710_regs[0x04];
921 if (d != 0)
922 io_write_byte(M37710_PORT0, data&d);
923 break;
924 case 0x03: // p1
925 d = m377.m37710_regs[0x05];
926 if (d != 0)
927 io_write_byte(M37710_PORT1, data&d);
928 break;
929 case 0x06: // p2
930 d = m377.m37710_regs[0x08];
931 if (d != 0)
932 io_write_byte(M37710_PORT2, data&d);
933 break;
934 case 0x07: // p3
935 d = m377.m37710_regs[0x09];
936 if (d != 0)
937 io_write_byte(M37710_PORT3, data&d);
938 break;
939 case 0x0a: // p4
940 d = m377.m37710_regs[0x0c];
941 if (d != 0)
942 io_write_byte(M37710_PORT4, data&d);
943 break;
944 case 0x0b: // p5
945 d = m377.m37710_regs[0x0d];
946 if (d != 0)
947 io_write_byte(M37710_PORT5, data&d);
948 break;
949 case 0x0e: // p6
950 d = m377.m37710_regs[0x10];
951 if (d != 0)
952 io_write_byte(M37710_PORT6, data&d);
953 break;
954 case 0x0f: // p7
955 d = m377.m37710_regs[0x11];
956 if (d != 0)
957 io_write_byte(M37710_PORT7, data&d);
958 break;
959 case 0x12: // p8
960 d = m377.m37710_regs[0x14];
961 if (d != 0)
962 io_write_byte(M37710_PORT8, data&d);
963 break;
964
965 case 0x1e: // adc timer
966 if (data & 0x40 && ~prevdata & 0x40) {
967 m377.timers[8] = 0x72 * ((data & 0x80) ? 2 : 4);
968 if (data & 0x10) {
969 m377.m37710_regs[offset] &= 0xf8;
970 }
971 } else if (~data & 0x40) {
972 m377.timers[8] = -1; // adc timer OFF
973 }
974 break;
975
976
977 case 0x40: // count start
978 for (i = 0; i < 8; i++)
979 {
980 if ((data & (1<<i)) && !(prevdata & (1<<i)))
981 m37710_recalc_timer(i);
982 }
983 break;
984
985 // internal interrupt control
986 case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75:
987 case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
988 //bprintf(0, _T("Internal Interrupt Control %x\n"), offset);
989 //m37710_set_irq_line(offset, (data & 8) ? HOLD_LINE : CLEAR_LINE);
990 //m37710i_update_irqs();
991 break;
992
993 // external interrupt control
994 case 0x7d: case 0x7e: case 0x7f:
995 //bprintf(0, _T("External Interrupt Control %x\n"), offset);
996 //m37710_set_irq_line(offset, (data & 8) ? HOLD_LINE : CLEAR_LINE);
997 //m37710i_update_irqs();
998
999 // level-sense interrupts are not implemented yet
1000 //if (data & 0x20) logerror("error M37710: INT%d level-sense\n",offset-0x7d);
1001 break;
1002
1003 default:
1004 break;
1005 }
1006 }
1007
m37710i_set_flag_m0x0(UINT32 value)1008 void m37710i_set_flag_m0x0(UINT32 value)
1009 {
1010 if(value & FLAGPOS_M)
1011 {
1012 REG_B = REG_A & 0xff00;
1013 REG_A = MAKE_UINT_8(REG_A);
1014 REG_BB = REG_BA & 0xff00;
1015 REG_BA = MAKE_UINT_8(REG_BA);
1016 FLAG_M = MFLAG_SET;
1017 //bprintf(0, _T("CPU M flag set M\n"));
1018 }
1019 if(value & FLAGPOS_X)
1020 {
1021 REG_XH = REG_X & 0xff00;
1022 REG_X = MAKE_UINT_8(REG_X);
1023 REG_YH = REG_Y & 0xff00;
1024 REG_Y = MAKE_UINT_8(REG_Y);
1025 FLAG_X = XFLAG_SET;
1026 //bprintf(0, _T("CPU X flag set X\n"));
1027 }
1028
1029 m37710i_set_execution_mode((FLAG_M>>4) | (FLAG_X>>4));
1030 }
1031
m37710i_set_flag_m0x1(UINT32 value)1032 void m37710i_set_flag_m0x1(UINT32 value)
1033 {
1034 if(value & FLAGPOS_M)
1035 {
1036 REG_B = REG_A & 0xff00;
1037 REG_A = MAKE_UINT_8(REG_A);
1038 REG_BB = REG_BA & 0xff00;
1039 REG_BA = MAKE_UINT_8(REG_BA);
1040 FLAG_M = MFLAG_SET;
1041 //bprintf(0, _T("CPU M flag set M\n"));
1042 }
1043 if(!(value & FLAGPOS_X))
1044 {
1045 REG_X |= REG_XH;
1046 REG_XH = 0;
1047 REG_Y |= REG_YH;
1048 REG_YH = 0;
1049 FLAG_X = XFLAG_CLEAR;
1050 //bprintf(0, _T("CPU X flag clear X\n"));
1051 }
1052
1053 m37710i_set_execution_mode((FLAG_M>>4) | (FLAG_X>>4));
1054 }
1055
m37710i_set_flag_m1x0(UINT32 value)1056 void m37710i_set_flag_m1x0(UINT32 value)
1057 {
1058 if(!(value & FLAGPOS_M))
1059 {
1060 REG_A |= REG_B;
1061 REG_B = 0;
1062 REG_BA |= REG_BB;
1063 REG_BB = 0;
1064 FLAG_M = MFLAG_CLEAR;
1065 //bprintf(0, _T("CPU M flag clear M\n"));
1066 }
1067
1068 if(value & FLAGPOS_X)
1069 {
1070 REG_XH = REG_X & 0xff00;
1071 REG_X = MAKE_UINT_8(REG_X);
1072 REG_YH = REG_Y & 0xff00;
1073 REG_Y = MAKE_UINT_8(REG_Y);
1074 FLAG_X = XFLAG_SET;
1075 //bprintf(0, _T("CPU X flag set X\n"));
1076 }
1077
1078 m37710i_set_execution_mode((FLAG_M>>4) | (FLAG_X>>4));
1079 }
1080
m37710i_set_flag_m1x1(UINT32 value)1081 void m37710i_set_flag_m1x1(UINT32 value)
1082 {
1083 if(!(value & FLAGPOS_M))
1084 {
1085 REG_A |= REG_B;
1086 REG_B = 0;
1087 REG_BA |= REG_BB;
1088 REG_BB = 0;
1089 FLAG_M = MFLAG_CLEAR;
1090 //bprintf(0, _T("CPU M flag clear M\n"));
1091 }
1092 if(!(value & FLAGPOS_X))
1093 {
1094 REG_X |= REG_XH;
1095 REG_XH = 0;
1096 REG_Y |= REG_YH;
1097 REG_YH = 0;
1098 FLAG_X = XFLAG_CLEAR;
1099 //bprintf(0, _T("CPU X flag clear X\n"));
1100 }
1101
1102 m37710i_set_execution_mode((FLAG_M>>4) | (FLAG_X>>4));
1103 }
1104
1105
m37710i_set_reg_p(UINT32 value)1106 void m37710i_set_reg_p(UINT32 value)
1107 {
1108 FLAG_N = value;
1109 FLAG_V = value << 1;
1110 FLAG_D = value & FLAGPOS_D;
1111 FLAG_Z = !(value & FLAGPOS_Z);
1112 FLAG_C = value << 8;
1113 m_setflag(value);
1114 FLAG_I = value & FLAGPOS_I;
1115 }
1116
1117 const opcode_func *m37710i_opcodes[4] =
1118 {
1119 m37710i_opcodes_M0X0,
1120 m37710i_opcodes_M0X1,
1121 m37710i_opcodes_M1X0,
1122 m37710i_opcodes_M1X1,
1123 };
1124
1125 const opcode_func *m37710i_opcodes2[4] =
1126 {
1127 m37710i_opcodes42_M0X0,
1128 m37710i_opcodes42_M0X1,
1129 m37710i_opcodes42_M1X0,
1130 m37710i_opcodes42_M1X1,
1131 };
1132
1133 const opcode_func *m37710i_opcodes3[4] =
1134 {
1135 m37710i_opcodes89_M0X0,
1136 m37710i_opcodes89_M0X1,
1137 m37710i_opcodes89_M1X0,
1138 m37710i_opcodes89_M1X1,
1139 };
1140
1141 const get_reg_func m37710i_get_reg[4] =
1142 {
1143 &m37710i_get_reg_M0X0,
1144 &m37710i_get_reg_M0X1,
1145 &m37710i_get_reg_M1X0,
1146 &m37710i_get_reg_M1X1,
1147 };
1148
1149 const set_reg_func m37710i_set_reg[4] =
1150 {
1151 &m37710i_set_reg_M0X0,
1152 &m37710i_set_reg_M0X1,
1153 &m37710i_set_reg_M1X0,
1154 &m37710i_set_reg_M1X1,
1155 };
1156
1157 const set_line_func m37710i_set_line[4] =
1158 {
1159 &m37710i_set_line_M0X0,
1160 &m37710i_set_line_M0X1,
1161 &m37710i_set_line_M1X0,
1162 &m37710i_set_line_M1X1,
1163 };
1164
1165 const execute_func m37710i_execute[4] =
1166 {
1167 &m37710i_execute_M0X0,
1168 &m37710i_execute_M0X1,
1169 &m37710i_execute_M1X0,
1170 &m37710i_execute_M1X1,
1171 };
1172
1173 const set_flag_func m37710i_setflag[4] =
1174 {
1175 &m37710i_set_flag_m0x0,
1176 &m37710i_set_flag_m0x1,
1177 &m37710i_set_flag_m1x0,
1178 &m37710i_set_flag_m1x1,
1179 };
1180
1181
1182 /* internal functions */
1183
m37710i_update_irqs()1184 static void m37710i_update_irqs()
1185 {
1186 int curirq, pending = LINE_IRQ;
1187 int wantedIRQ = -1;
1188 int curpri = 0;
1189
1190 for (curirq = M37710_LINE_MAX - 1; curirq >= 0; curirq--)
1191 {
1192 if ((pending & (1 << curirq)))
1193 {
1194 // this IRQ is set
1195 if (m37710_irq_levels[curirq])
1196 {
1197 int control = m377.m37710_regs[m37710_irq_levels[curirq]];
1198 int thispri = control & 7;
1199 // logerror("line %d set, level %x curpri %x IPL %x\n", curirq, thispri, curpri, m377.ipl);
1200 // it's maskable, check if the level works, also make sure it's acceptable for the current CPU level
1201 if (!FLAG_I && thispri > curpri && thispri > m377.ipl)
1202 {
1203 // mark us as the best candidate
1204 wantedIRQ = curirq;
1205 curpri = thispri;
1206 }
1207 }
1208 else
1209 {
1210 // non-maskable
1211 wantedIRQ = curirq;
1212 curpri = 7;
1213 break; // no more processing, NMIs always win
1214 }
1215 }
1216 }
1217
1218 if (wantedIRQ != -1)
1219 {
1220 //standard_irq_callback(wantedIRQ);
1221
1222 // make sure we're running to service the interrupt
1223 CPU_STOPPED &= ~STOP_LEVEL_WAI;
1224
1225 // auto-clear line
1226 m37710_set_irq_line(wantedIRQ, CLEAR_LINE);
1227
1228 // let's do it...
1229 // push PB, then PC, then status
1230 CLK(13);
1231 //bprintf(0, _T("taking IRQ %d: PC = %06x, SP = %04x, IPL %d\n"), wantedIRQ, REG_PB | REG_PC, REG_S, m377.ipl);
1232 m37710i_push_8(REG_PB>>16);
1233 m37710i_push_16(REG_PC);
1234 m37710i_push_8(m377.ipl);
1235 m37710i_push_8(m37710i_get_reg_p());
1236
1237 // set I to 1, set IPL to the interrupt we're taking
1238 FLAG_I = IFLAG_SET;
1239 m377.ipl = curpri;
1240 // then PB=0, PC=(vector)
1241 REG_PB = 0;
1242 REG_PC = m37710_read_16(m37710_irq_vectors[wantedIRQ]);
1243 // logerror("IRQ @ %06x\n", REG_PB | REG_PC);
1244 }
1245 }
1246
1247 /* external functions */
1248
M377Reset()1249 void M377Reset()
1250 {
1251 int i;
1252
1253 /* Reset DINK timers */
1254 for (i = 0; i < (8 + 1); i++) // #8 is ADC timer! -dink
1255 {
1256 m377.timers[i] = -1;
1257 m377.reload[i] = -1;
1258 }
1259
1260 /* Start the CPU */
1261 CPU_STOPPED = 0;
1262
1263 /* Reset internal registers */
1264 // port direction
1265 m377.m37710_regs[0x04] = 0;
1266 m377.m37710_regs[0x05] = 0;
1267 m377.m37710_regs[0x08] = 0;
1268 m377.m37710_regs[0x09] = 0;
1269 m377.m37710_regs[0x0c] = 0;
1270 m377.m37710_regs[0x0d] = 0;
1271 m377.m37710_regs[0x10] = 0;
1272 m377.m37710_regs[0x11] = 0;
1273 m377.m37710_regs[0x14] = 0;
1274
1275 m377.m37710_regs[0x1e] &= 7; // A-D control
1276 m377.m37710_regs[0x1f] |= 3; // A-D sweep
1277
1278 // UART
1279 m377.m37710_regs[0x30] = 0;
1280 m377.m37710_regs[0x38] = 0;
1281 m377.m37710_regs[0x34] = (m377.m37710_regs[0x34] & 0xf0) | 8;
1282 m377.m37710_regs[0x3c] = (m377.m37710_regs[0x3c] & 0xf0) | 8;
1283 m377.m37710_regs[0x35] = 2;
1284 m377.m37710_regs[0x3d] = 2;
1285 m377.m37710_regs[0x37]&= 1;
1286 m377.m37710_regs[0x3f]&= 1;
1287
1288 // timer
1289 m377.m37710_regs[0x40] = 0;
1290 m377.m37710_regs[0x42]&= 0x1f;
1291 m377.m37710_regs[0x44] = 0;
1292 for (i = 0x56; i < 0x5e; i++)
1293 m377.m37710_regs[i] = 0;
1294
1295 m377.m37710_regs[0x5e] = 0; // processor mode
1296 m377.m37710_regs[0x61]&= 1; // watchdog frequency
1297
1298 // interrupt control
1299 m377.m37710_regs[0x7d] &= 0x3f;
1300 m377.m37710_regs[0x7e] &= 0x3f;
1301 m377.m37710_regs[0x7f] &= 0x3f;
1302 for (i = 0x70; i < 0x7d; i++)
1303 m377.m37710_regs[i] &= 0xf;
1304
1305 /* Clear IPL, m, x, D and set I */
1306 m377.ipl = 0;
1307 FLAG_M = MFLAG_CLEAR;
1308 FLAG_X = XFLAG_CLEAR;
1309 FLAG_D = DFLAG_CLEAR;
1310 FLAG_I = IFLAG_SET;
1311
1312 /* Clear all pending interrupts (should we really do this?) */
1313 LINE_IRQ = 0;
1314 IRQ_DELAY = 0;
1315
1316 /* 37710 boots in full native mode */
1317 REG_D = 0;
1318 REG_PB = 0;
1319 REG_DB = 0;
1320 REG_S = (REG_S & 0xff) | 0x100;
1321 REG_XH = REG_X & 0xff00; REG_X &= 0xff;
1322 REG_YH = REG_Y & 0xff00; REG_Y &= 0xff;
1323 REG_B = REG_A & 0xff00; REG_A &= 0xff;
1324 REG_BB = REG_BA & 0xff00; REG_BA &= 0xff;
1325
1326 /* Set the function tables to emulation mode */
1327 m37710i_set_execution_mode(EXECUTION_MODE_M0X0);
1328
1329 /* Fetch the reset vector */
1330 REG_PC = m37710_read_16(0xfffe);
1331 }
1332
m37710_clock_timers(INT32 clkcnt)1333 static void m37710_clock_timers(INT32 clkcnt)
1334 {
1335 for (INT32 c = 0; c < clkcnt; c++) {
1336 for (INT32 i = 0; i < (8 + 1); i++) {
1337 if (m377.timers[i] > 0) { // active
1338 m377.timers[i]--;
1339 if (m377.timers[i] <= 0) { // timer hits!
1340 m377.timers[i] = -1; // disable this timer
1341 //bprintf(0, _T("timer %x hits!\n"), i);
1342 if (i == 8) {
1343 m37710_adc_cb();
1344 } else {
1345 m37710_timer_cb(i);
1346 }
1347 }
1348 }
1349 }
1350 }
1351 }
1352
1353 static INT32 current_cpu = -1;
1354
M377GetActive()1355 INT32 M377GetActive()
1356 {
1357 return current_cpu;
1358 }
1359
M377Open(INT32 cpunum)1360 void M377Open(INT32 cpunum)
1361 {
1362 current_cpu = cpunum; // dummy, currently single-cpu core
1363 }
1364
M377Close()1365 void M377Close()
1366 {
1367 current_cpu = -1; // dummy, currently single-cpu core
1368 }
1369
M377RunEnd()1370 void M377RunEnd()
1371 {
1372 m377.end_run = 1;
1373 }
1374
M377Idle(INT32 cycles)1375 INT32 M377Idle(INT32 cycles)
1376 {
1377 m377.total_cycles += cycles;
1378
1379 return cycles;
1380 }
1381
M377GetPC()1382 INT32 M377GetPC()
1383 {
1384 return REG_PB | REG_PC;
1385 }
1386
M377GetPPC()1387 INT32 M377GetPPC()
1388 {
1389 return REG_PB | REG_PPC;
1390 }
1391
1392 /* Execute some instructions */
M377Run(INT32 cycles)1393 INT32 M377Run(INT32 cycles)
1394 {
1395 m377.end_run = 0;
1396 m377.ICount = cycles;
1397 m377.segment_cycles = cycles;
1398
1399 m37710i_update_irqs();
1400
1401 (*m_execute)(m377.ICount);
1402
1403 cycles = cycles - m377.ICount;
1404
1405 m377.segment_cycles = m377.ICount = 0;
1406
1407 m377.total_cycles += cycles;
1408
1409 return cycles;
1410 }
1411
M377NewFrame()1412 void M377NewFrame()
1413 {
1414 m377.total_cycles = 0;
1415 }
1416
M377TotalCycles()1417 INT32 M377TotalCycles()
1418 {
1419 return m377.total_cycles + (m377.segment_cycles - m377.ICount);
1420 }
1421
1422
1423 /* Set the Program Counter */
m37710_set_pc(unsigned val)1424 void m37710_set_pc(unsigned val)
1425 {
1426 REG_PC = MAKE_UINT_16(val);
1427 }
1428
1429 /* Get the current Stack Pointer */
m37710_get_sp()1430 unsigned m37710_get_sp()
1431 {
1432 return REG_S;
1433 }
1434
1435 /* Set the Stack Pointer */
m37710_set_sp(unsigned val)1436 void m37710_set_sp(unsigned val)
1437 {
1438 REG_S = MAKE_UINT_16(val);
1439 }
1440
1441 /* Get a register */
m37710_get_reg(int regnum)1442 unsigned m37710_get_reg(int regnum)
1443 {
1444 return (*m_get_reg)(regnum);
1445 }
1446
1447 /* Set a register */
m37710_set_reg(int regnum,unsigned value)1448 void m37710_set_reg(int regnum, unsigned value)
1449 {
1450 (*m_set_reg)(regnum, value);
1451 }
1452
1453 /* Set an interrupt line */
m37710_set_irq_line(int line,int state)1454 static void m37710_set_irq_line(int line, int state)
1455 {
1456 (*m_set_line)(line, state);
1457 }
1458
1459
m37710_restore_state()1460 void m37710_restore_state()
1461 {
1462 // restore proper function pointers
1463 m37710i_set_execution_mode((FLAG_M>>4) | (FLAG_X>>4));
1464 }
1465
M377Scan(INT32 nAction)1466 INT32 M377Scan(INT32 nAction)
1467 {
1468 if ((nAction & ACB_DRIVER_DATA) == 0) {
1469 return 1;
1470 }
1471
1472 ScanVar(internal_ram, (m377.subtype == M37710) ? 0x800 : 0x200, "M377xx Int.RAM");
1473
1474 SCAN_VAR(m377);
1475
1476 if (nAction & ACB_WRITE) {
1477 m37710_restore_state();
1478 }
1479
1480 return 0;
1481 }
1482
M377Init(INT32 cpunum,INT32 cputype)1483 void M377Init(INT32 cpunum, INT32 cputype)
1484 {
1485 cpunum = cpunum; // dummy
1486
1487 for (INT32 i = 0; i < 3; i++) {
1488 mem[i] = (UINT8**)BurnMalloc(((address_mask / page_size) + 1) * sizeof(UINT8**));
1489 memset (mem[i], 0, ((address_mask / page_size) + 1) * sizeof(UINT8**));
1490 }
1491 mem_flags = (UINT8*)BurnMalloc(((address_mask / page_size) + 1) * sizeof(UINT8));
1492 memset(mem_flags, 0, ((address_mask / page_size) + 1) * sizeof(UINT8));
1493
1494 internal_ram = (UINT8*)BurnMalloc(0x800);
1495
1496 switch (cputype) {
1497 case M37702:
1498 M377MapMemory(internal_ram, 0x80, 0x27f, MAP_RAM);
1499 break;
1500 case M37710:
1501 M377MapMemory(internal_ram, 0x80, 0x87f, MAP_RAM);
1502 break;
1503 default:
1504 bprintf(0, _T("M377Init(%d, %d): Invalid CPUtype (2nd parameter)!\n"), cpunum, cputype);
1505 }
1506
1507 memset(&m377, 0, sizeof(m377));
1508 memset(internal_ram, 0, 0x800);
1509
1510 m377.subtype = cputype;
1511
1512 for (int i = 0; i < (8 + 1); i++)
1513 {
1514 m377.timers[i] = -1;
1515 m377.reload[i] = -1;
1516 }
1517
1518 CpuCheatRegister(0, &M377Config);
1519 }
1520
M377Exit()1521 void M377Exit()
1522 {
1523 for (INT32 i = 0; i < 3; i++) {
1524 BurnFree(mem[i]);
1525 }
1526
1527 BurnFree(internal_ram);
1528 BurnFree(mem_flags);
1529 }
1530
M377SetIRQLine(INT32 inputnum,INT32 state)1531 void M377SetIRQLine(INT32 inputnum, INT32 state)
1532 {
1533 switch( inputnum )
1534 {
1535 case M37710_LINE_ADC:
1536 case M37710_LINE_IRQ0:
1537 case M37710_LINE_IRQ1:
1538 case M37710_LINE_IRQ2:
1539 m37710_set_irq_line(inputnum, state);
1540 break;
1541
1542 case M37710_LINE_TIMERA0TICK:
1543 case M37710_LINE_TIMERA1TICK:
1544 case M37710_LINE_TIMERA2TICK:
1545 case M37710_LINE_TIMERA3TICK:
1546 case M37710_LINE_TIMERA4TICK:
1547 case M37710_LINE_TIMERB0TICK:
1548 case M37710_LINE_TIMERB1TICK:
1549 case M37710_LINE_TIMERB2TICK:
1550 m37710_external_tick(inputnum - M37710_LINE_TIMERA0TICK, state);
1551 break;
1552 }
1553 }
1554
1555
m37710i_set_execution_mode(UINT32 mode)1556 static void m37710i_set_execution_mode(UINT32 mode)
1557 {
1558 //bprintf(0, _T("** M377xx: set execution mode %x PC: %x\n"), mode, M377GetPC());
1559 m_opcodes = m37710i_opcodes[mode];
1560 m_opcodes42 = m37710i_opcodes2[mode];
1561 m_opcodes89 = m37710i_opcodes3[mode];
1562 m_get_reg = m37710i_get_reg[mode];
1563 m_set_reg = m37710i_set_reg[mode];
1564 m_set_line = m37710i_set_line[mode];
1565 m_execute = m37710i_execute[mode];
1566 m_setflag = m37710i_setflag[mode];
1567 }
1568
1569
1570 /* ======================================================================== */
1571 /* =============================== INTERRUPTS ============================= */
1572 /* ======================================================================== */
1573
m37710i_interrupt_software(UINT32 vector)1574 static void m37710i_interrupt_software(UINT32 vector)
1575 {
1576 CLK(13);
1577 m37710i_push_8(REG_PB>>16);
1578 m37710i_push_16(REG_PC);
1579 m37710i_push_8(m377.ipl);
1580 m37710i_push_8(m37710i_get_reg_p());
1581 FLAG_I = IFLAG_SET;
1582 REG_PB = 0;
1583 REG_PC = m37710_read_16(vector);
1584 }
1585
1586
1587
1588 /* ======================================================================== */
1589 /* ============================== END OF FILE ============================= */
1590 /* ======================================================================== */
1591