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