1 // license:BSD-3-Clause
2 // copyright-holders:Dan Boris
3 /***************************************************************************
4 
5     Atari I, Robot hardware
6 
7 ***************************************************************************/
8 
9 #include "emu.h"
10 #include "cpu/m6809/m6809.h"
11 #include "includes/irobot.h"
12 
13 /* Note:
14  * There's probably something wrong with the way the Mathbox gets started.
15  * Try compiling with IR_TIMING=1, run with logging on and take a look at
16  * the resulting logilfe.
17  * The mathbox is started in short intervals (<10 scanlines) without (!)
18  * checking its idle status.
19  * It also seems that the mathbox in this emulation would have to cope with
20  * approx. 5000 instructions per scanline [look at the number of instructions
21  * and the number of scanlines to the next mathbox start]. This seems a bit
22  * too high.
23  */
24 
25 #define DISASSEMBLE_MB_ROM      0       /* generate a disassembly of the mathbox ROMs */
26 
27 #define IR_CPU_STATE() \
28 	logerror(\
29 			"%s, scanline: %d\n", machine().describe_context(), m_screen->vpos())
30 
31 
irobot_sharedmem_r(offs_t offset)32 uint8_t irobot_state::irobot_sharedmem_r(offs_t offset)
33 {
34 	if (m_outx == 3)
35 		return m_mbRAM[BYTE_XOR_BE(offset)];
36 
37 	if (m_outx == 2)
38 		return m_combase[BYTE_XOR_BE(offset & 0xFFF)];
39 
40 	if (m_outx == 0)
41 		return m_mbROM[((m_mpage & 1) << 13) + BYTE_XOR_BE(offset)];
42 
43 	if (m_outx == 1)
44 		return m_mbROM[0x4000 + ((m_mpage & 3) << 13) + BYTE_XOR_BE(offset)];
45 
46 	return 0xFF;
47 }
48 
49 /* Comment out the mbRAM =, comRAM2 = or comRAM1 = and it will start working */
irobot_sharedmem_w(offs_t offset,uint8_t data)50 void irobot_state::irobot_sharedmem_w(offs_t offset, uint8_t data)
51 {
52 	if (m_outx == 3)
53 		m_mbRAM[BYTE_XOR_BE(offset)] = data;
54 
55 	if (m_outx == 2)
56 		m_combase[BYTE_XOR_BE(offset & 0xFFF)] = data;
57 }
58 
TIMER_DEVICE_CALLBACK_MEMBER(irobot_state::irobot_irvg_done_callback)59 TIMER_DEVICE_CALLBACK_MEMBER(irobot_state::irobot_irvg_done_callback)
60 {
61 	logerror("vg done. ");
62 	m_irvg_running = 0;
63 }
64 
irobot_statwr_w(uint8_t data)65 void irobot_state::irobot_statwr_w(uint8_t data)
66 {
67 	logerror("write %2x ", data);
68 	IR_CPU_STATE();
69 
70 	m_combase = m_comRAM[BIT(data, 7)];
71 	m_combase_mb = m_comRAM[BIT(data, 7) ^ 1];
72 	m_bufsel = BIT(data, 1);
73 	if (BIT(data, 0) && (m_vg_clear == 0))
74 		irobot_poly_clear();
75 
76 	m_vg_clear = BIT(data, 0);
77 
78 	if (BIT(data, 2) && !BIT(m_statwr, 2))
79 	{
80 		irobot_run_video();
81 #if IR_TIMING
82 		if (m_irvg_running == 0)
83 			logerror("vg start ");
84 		else
85 			logerror("vg start [busy!] ");
86 		IR_CPU_STATE();
87 		m_irvg_timer->adjust(attotime::from_msec(10));
88 #endif
89 		m_irvg_running=1;
90 	}
91 	if (BIT(data, 4) && !BIT(m_statwr, 4))
92 		irmb_run();
93 
94 	m_novram->recall(!BIT(data, 6));
95 
96 	m_statwr = data;
97 }
98 
irobot_out0_w(uint8_t data)99 void irobot_state::irobot_out0_w(uint8_t data)
100 {
101 	uint8_t *RAM = memregion("maincpu")->base();
102 
103 	m_out0 = data;
104 	switch (data & 0x60)
105 	{
106 		case 0:
107 			membank("bank2")->set_base(&RAM[0x1C000]);
108 			break;
109 		case 0x20:
110 			membank("bank2")->set_base(&RAM[0x1C800]);
111 			break;
112 		case 0x40:
113 			membank("bank2")->set_base(&RAM[0x1D000]);
114 			break;
115 	}
116 	m_outx = (data & 0x18) >> 3;
117 	m_mpage = (data & 0x06) >> 1;
118 	m_alphamap = (data & 0x80);
119 }
120 
irobot_rom_banksel_w(uint8_t data)121 void irobot_state::irobot_rom_banksel_w(uint8_t data)
122 {
123 	uint8_t *RAM = memregion("maincpu")->base();
124 
125 	switch ((data & 0x0E) >> 1)
126 	{
127 		case 0:
128 			membank("bank1")->set_base(&RAM[0x10000]);
129 			break;
130 		case 1:
131 			membank("bank1")->set_base(&RAM[0x12000]);
132 			break;
133 		case 2:
134 			membank("bank1")->set_base(&RAM[0x14000]);
135 			break;
136 		case 3:
137 			membank("bank1")->set_base(&RAM[0x16000]);
138 			break;
139 		case 4:
140 			membank("bank1")->set_base(&RAM[0x18000]);
141 			break;
142 		case 5:
143 			membank("bank1")->set_base(&RAM[0x1A000]);
144 			break;
145 	}
146 	m_leds[0] = BIT(data, 4);
147 	m_leds[1] = BIT(data, 5);
148 }
149 
TIMER_CALLBACK_MEMBER(irobot_state::scanline_callback)150 TIMER_CALLBACK_MEMBER(irobot_state::scanline_callback)
151 {
152 	int scanline = param;
153 
154 	if (scanline == 0) m_irvg_vblank=0;
155 	if (scanline == 224) m_irvg_vblank=1;
156 	logerror("SCANLINE CALLBACK %d\n",scanline);
157 	/* set the IRQ line state based on the 32V line state */
158 	m_maincpu->set_input_line(M6809_IRQ_LINE, (scanline & 32) ? ASSERT_LINE : CLEAR_LINE);
159 
160 	/* set a callback for the next 32-scanline increment */
161 	scanline += 32;
162 	if (scanline >= 256) scanline = 0;
163 	m_scanline_timer->adjust(m_screen->time_until_pos(scanline), scanline);
164 }
165 
machine_start()166 void irobot_state::machine_start()
167 {
168 	m_leds.resolve();
169 	m_vg_clear = 0;
170 	m_statwr = 0;
171 
172 	/* set an initial timer to go off on scanline 0 */
173 	m_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(irobot_state::scanline_callback), this));
174 	m_scanline_timer->adjust(m_screen->time_until_pos(0));
175 }
176 
machine_reset()177 void irobot_state::machine_reset()
178 {
179 	uint8_t *MB = memregion("mathbox")->base();
180 
181 	/* initialize the memory regions */
182 	m_mbROM     = MB + 0x00000;
183 	m_mbRAM     = MB + 0x0c000;
184 	m_comRAM[0] = MB + 0x0e000;
185 	m_comRAM[1] = MB + 0x0f000;
186 
187 	m_irvg_vblank=0;
188 	m_irvg_running = 0;
189 	m_irmb_running = 0;
190 
191 	irobot_rom_banksel_w(0);
192 	irobot_out0_w(0);
193 	irobot_statwr_w(0);
194 	m_outx = 0;
195 }
196 
197 /*  we allow irmb_running and irvg_running to appear running before clearing
198     them to simulate the mathbox and vector generator running in real time */
irobot_status_r()199 uint8_t irobot_state::irobot_status_r()
200 {
201 	int d=0;
202 
203 	logerror("status read. ");
204 	IR_CPU_STATE();
205 
206 	if (!m_irmb_running) d |= 0x20;
207 	if (m_irvg_running) d |= 0x40;
208 
209 	//        d = (m_irmb_running * 0x20) | (m_irvg_running * 0x40);
210 	if (m_irvg_vblank) d = d | 0x80;
211 #if IR_TIMING
212 	/* flags are cleared by callbacks */
213 #else
214 	m_irmb_running=0;
215 	m_irvg_running=0;
216 #endif
217 	return d;
218 }
219 
220 
221 /***********************************************************************
222 
223     I-Robot Mathbox
224 
225     Based on 4 2901 chips slice processors connected to form a 16-bit ALU
226 
227     Microcode roms:
228     6N: bits 0..3: Address of ALU A register
229     5P: bits 0..3: Address of ALU B register
230     6M: bits 0..3: ALU Function bits 5..8
231     7N: bits 0..3: ALU Function bits 1..4
232     8N: bits 0,1: Memory write timing
233         bit 2: Hardware multiply mode
234         bit 3: ALU Function bit 0
235     6P: bits 0,1: Direct addressing bits 0,1
236         bits 2,3: Jump address bits 0,1
237     8M: bits 0..3: Jump address bits 6..9
238     9N: bits 0..3: Jump address bits 2..5
239     8P: bits 0..3: Memory address bits 2..5
240     9M: bit 0: Shift control
241         bits 1..3: Jump type
242             0 = No Jump
243             1 = On carry
244             2 = On zero
245             3 = On positive
246             4 = On negative
247             5 = Unconditional
248             6 = Jump to Subroutine
249             7 = Return from Subroutine
250     7M: Bit 0: Mathbox memory enable
251         Bit 1: Latch data to address bus
252         Bit 2: Carry in select
253         Bit 3: Carry in value
254         (if 2,3 = 11 then mathbox is done)
255     9P: Bit 0: Hardware divide enable
256         Bits 1,2: Memory select
257         Bit 3: Memory R/W
258     7P: Bits 0,1: Direct addressing bits 6,7
259         Bits 2,3: Unused
260 
261 ***********************************************************************/
262 
263 #define FL_MULT 0x01
264 #define FL_shift 0x02
265 #define FL_MBMEMDEC 0x04
266 #define FL_ADDEN 0x08
267 #define FL_DPSEL 0x10
268 #define FL_carry 0x20
269 #define FL_DIV 0x40
270 #define FL_MBRW 0x80
271 
272 
273 #if DISASSEMBLE_MB_ROM
274 static void disassemble_instruction(irobot_state::irmb_ops const *op);
275 #endif
276 
277 
irmb_din(const irmb_ops * curop)278 uint32_t irobot_state::irmb_din(const irmb_ops *curop)
279 {
280 	uint32_t d = 0;
281 
282 	if (!(curop->flags & FL_MBMEMDEC) && (curop->flags & FL_MBRW))
283 	{
284 		uint32_t ad = curop->diradd | (m_irmb_latch & curop->latchmask);
285 
286 		if (curop->diren || (m_irmb_latch & 0x6000) == 0)
287 			d = ((uint16_t *)m_mbRAM)[ad & 0xfff];             /* MB RAM read */
288 		else if (m_irmb_latch & 0x4000)
289 			d = ((uint16_t *)m_mbROM)[ad + 0x2000];                /* MB ROM read, CEMATH = 1 */
290 		else
291 			d = ((uint16_t *)m_mbROM)[ad & 0x1fff];                /* MB ROM read, CEMATH = 0 */
292 	}
293 	return d;
294 }
295 
296 
irmb_dout(const irmb_ops * curop,uint32_t d)297 void irobot_state::irmb_dout(const irmb_ops *curop, uint32_t d)
298 {
299 	/* Write to video com ram */
300 	if (curop->ramsel == 3)
301 		((uint16_t *)m_combase_mb)[m_irmb_latch & 0x7ff] = d;
302 
303 	/* Write to mathox ram */
304 	if (!(curop->flags & FL_MBMEMDEC))
305 	{
306 		uint32_t ad = curop->diradd | (m_irmb_latch & curop->latchmask);
307 
308 		if (curop->diren || (m_irmb_latch & 0x6000) == 0)
309 			((uint16_t *)m_mbRAM)[ad & 0xfff] = d;             /* MB RAM write */
310 	}
311 }
312 
313 
314 /* Convert microcode roms to a more usable form */
load_oproms()315 void irobot_state::load_oproms()
316 {
317 	uint8_t *MB = memregion("proms")->base() + 0x20;
318 	int i;
319 
320 	/* allocate RAM */
321 	m_mbops = std::make_unique<irmb_ops[]>(1024);
322 
323 	for (i = 0; i < 1024; i++)
324 	{
325 		int nxtadd, func, ramsel, diradd, latchmask, dirmask, time;
326 
327 		m_mbops[i].areg = &m_irmb_regs[MB[0x0000 + i] & 0x0F];
328 		m_mbops[i].breg = &m_irmb_regs[MB[0x0400 + i] & 0x0F];
329 		func = (MB[0x0800 + i] & 0x0F) << 5;
330 		func |= ((MB[0x0C00 +i] & 0x0F) << 1);
331 		func |= (MB[0x1000 + i] & 0x08) >> 3;
332 		time = MB[0x1000 + i] & 0x03;
333 		m_mbops[i].flags = (MB[0x1000 + i] & 0x04) >> 2;
334 		nxtadd = (MB[0x1400 + i] & 0x0C) >> 2;
335 		diradd = MB[0x1400 + i] & 0x03;
336 		nxtadd |= ((MB[0x1800 + i] & 0x0F) << 6);
337 		nxtadd |= ((MB[0x1C00 + i] & 0x0F) << 2);
338 		diradd |= (MB[0x2000 + i] & 0x0F) << 2;
339 		func |= (MB[0x2400 + i] & 0x0E) << 9;
340 		m_mbops[i].flags |= (MB[0x2400 + i] & 0x01) << 1;
341 		m_mbops[i].flags |= (MB[0x2800 + i] & 0x0F) << 2;
342 		m_mbops[i].flags |= ((MB[0x2C00 + i] & 0x01) << 6);
343 		m_mbops[i].flags |= (MB[0x2C00 + i] & 0x08) << 4;
344 		ramsel = (MB[0x2C00 + i] & 0x06) >> 1;
345 		diradd |= (MB[0x3000 + i] & 0x03) << 6;
346 
347 		if (m_mbops[i].flags & FL_shift) func |= 0x200;
348 
349 		m_mbops[i].func = func;
350 		m_mbops[i].nxtop = &m_mbops[nxtadd];
351 
352 		/* determine the number of 12MHz cycles for this operation */
353 		if (time == 3)
354 			m_mbops[i].cycles = 2;
355 		else
356 			m_mbops[i].cycles = 3 + time;
357 
358 		/* precompute the hardcoded address bits and the mask to be used on the latch value */
359 		if (ramsel == 0)
360 		{
361 			dirmask = 0x00FC;
362 			latchmask = 0x3000;
363 		}
364 		else
365 		{
366 			dirmask = 0x0000;
367 			latchmask = 0x3FFC;
368 		}
369 		if (ramsel & 2)
370 			latchmask |= 0x0003;
371 		else
372 			dirmask |= 0x0003;
373 
374 		m_mbops[i].ramsel = ramsel;
375 		m_mbops[i].diradd = diradd & dirmask;
376 		m_mbops[i].latchmask = latchmask;
377 		m_mbops[i].diren = (ramsel == 0);
378 
379 #if DISASSEMBLE_MB_ROM
380 		disassemble_instruction(&m_mbops[i]);
381 #endif
382 	}
383 }
384 
385 
386 /* Init mathbox (only called once) */
init_irobot()387 void irobot_state::init_irobot()
388 {
389 	for (int i = 0; i < 16; i++)
390 	{
391 		m_irmb_stack[i] = &m_mbops[0];
392 		m_irmb_regs[i] = 0;
393 	}
394 	m_irmb_latch = 0;
395 	load_oproms();
396 }
397 
TIMER_DEVICE_CALLBACK_MEMBER(irobot_state::irobot_irmb_done_callback)398 TIMER_DEVICE_CALLBACK_MEMBER(irobot_state::irobot_irmb_done_callback)
399 {
400 	logerror("mb done. ");
401 	m_irmb_running = 0;
402 	m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
403 }
404 
405 
406 #define COMPUTE_CI \
407 	CI = 0;\
408 	if (curop->flags & FL_DPSEL)\
409 		CI = cflag;\
410 	else\
411 	{\
412 		if (curop->flags & FL_carry)\
413 			CI = 1;\
414 		if (!(prevop->flags & FL_DIV) && !nflag)\
415 			CI = 1;\
416 	}
417 
418 #define ADD(r,s) \
419 	COMPUTE_CI;\
420 	result = r + s + CI;\
421 	cflag = (result >> 16) & 1;\
422 	vflag = (((r & 0x7fff) + (s & 0x7fff) + CI) >> 15) ^ cflag
423 
424 #define SUBR(r,s) \
425 	COMPUTE_CI;\
426 	result = (r ^ 0xFFFF) + s + CI;         /*S - R + CI - 1*/ \
427 	cflag = (result >> 16) & 1;\
428 	vflag = (((s & 0x7fff) + ((r ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag
429 
430 #define SUB(r,s) \
431 	COMPUTE_CI;\
432 	result = r + (s ^ 0xFFFF) + CI;      /*R - S + CI - 1*/ \
433 	cflag = (result >> 16) & 1;\
434 	vflag = (((r & 0x7fff) + ((s ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag
435 
436 #define OR(r,s) \
437 	result = r | s;\
438 	vflag = cflag = 0
439 
440 #define AND(r,s) \
441 	result = r & s;\
442 	vflag = cflag = 0
443 
444 #define IAND(r,s) \
445 	result = (r ^ 0xFFFF) & s;\
446 	vflag = cflag = 0
447 
448 #define XOR(r,s) \
449 	result = r ^ s;\
450 	vflag = cflag = 0
451 
452 #define IXOR(r,s) \
453 	result = (r ^ s) ^ 0xFFFF;\
454 	vflag = cflag = 0
455 
456 
457 #define DEST0 \
458 	Q = Y = zresult
459 
460 #define DEST1 \
461 	Y = zresult
462 
463 #define DEST2 \
464 	Y = *curop->areg;\
465 	*curop->breg = zresult
466 
467 #define DEST3 \
468 	*curop->breg = zresult;\
469 	Y = zresult
470 
471 #define DEST4_NOSHIFT \
472 	*curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\
473 	Q = (Q >> 1) | ((curop->flags & 0x20) << 10);\
474 	Y = zresult
475 
476 #define DEST4_SHIFT \
477 	*curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\
478 	Q = (Q >> 1) | ((zresult & 0x01) << 15);\
479 	Y = zresult
480 
481 #define DEST5_NOSHIFT \
482 	*curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\
483 	Y = zresult
484 
485 #define DEST5_SHIFT \
486 	*curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\
487 	Y = zresult
488 
489 #define DEST6_NOSHIFT \
490 	*curop->breg = zresult << 1;\
491 	Q = ((Q << 1) & 0xffff) | (nflag ^ 1);\
492 	Y = zresult
493 
494 #define DEST6_SHIFT \
495 	*curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\
496 	Q = (Q << 1) & 0xffff;\
497 	Y = zresult
498 
499 #define DEST7_NOSHIFT \
500 	*curop->breg = zresult << 1;\
501 	Y = zresult
502 
503 #define DEST7_SHIFT \
504 	*curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\
505 	Y = zresult
506 
507 
508 #define JUMP0   curop++;
509 #define JUMP1   if (cflag) curop = curop->nxtop; else curop++;
510 #define JUMP2   if (!zresult) curop = curop->nxtop; else curop++;
511 #define JUMP3   if (!nflag) curop = curop->nxtop; else curop++;
512 #define JUMP4   if (nflag) curop = curop->nxtop; else curop++;
513 #define JUMP5   curop = curop->nxtop;
514 #define JUMP6   m_irmb_stack[SP] = curop + 1; SP = (SP + 1) & 15; curop = curop->nxtop;
515 #define JUMP7   SP = (SP - 1) & 15; curop = m_irmb_stack[SP];
516 
517 
518 /* Run mathbox */
irmb_run()519 void irobot_state::irmb_run()
520 {
521 	const irmb_ops *prevop = &m_mbops[0];
522 	const irmb_ops *curop = &m_mbops[0];
523 
524 	uint32_t Q = 0;
525 	uint32_t Y = 0;
526 	uint32_t nflag = 0;
527 	uint32_t vflag = 0;
528 	uint32_t cflag = 0;
529 	uint32_t zresult = 1;
530 	uint32_t CI = 0;
531 	uint32_t SP = 0;
532 	uint32_t icount = 0;
533 
534 	g_profiler.start(PROFILER_USER1);
535 
536 	while ((prevop->flags & (FL_DPSEL | FL_carry)) != (FL_DPSEL | FL_carry))
537 	{
538 		uint32_t result;
539 		uint32_t fu;
540 		uint32_t tmp;
541 
542 		icount += curop->cycles;
543 
544 		/* Get function code */
545 		fu = curop->func;
546 
547 		/* Modify function for MULT */
548 		if (!(prevop->flags & FL_MULT) || (Q & 1))
549 			fu = fu ^ 0x02;
550 		else
551 			fu = fu | 0x02;
552 
553 		/* Modify function for DIV */
554 		if ((prevop->flags & FL_DIV) || nflag)
555 			fu = fu ^ 0x08;
556 		else
557 			fu = fu | 0x08;
558 
559 		/* Do source and operation */
560 		switch (fu & 0x03f)
561 		{
562 			case 0x00:  ADD(*curop->areg, Q);                               break;
563 			case 0x01:  ADD(*curop->areg, *curop->breg);                    break;
564 			case 0x02:  ADD(0, Q);                                          break;
565 			case 0x03:  ADD(0, *curop->breg);                               break;
566 			case 0x04:  ADD(0, *curop->areg);                               break;
567 			case 0x05:  tmp = irmb_din(curop); ADD(tmp, *curop->areg);       break;
568 			case 0x06:  tmp = irmb_din(curop); ADD(tmp, Q);                  break;
569 			case 0x07:  tmp = irmb_din(curop); ADD(tmp, 0);                  break;
570 			case 0x08:  SUBR(*curop->areg, Q);                              break;
571 			case 0x09:  SUBR(*curop->areg, *curop->breg);                   break;
572 			case 0x0a:  SUBR(0, Q);                                         break;
573 			case 0x0b:  SUBR(0, *curop->breg);                              break;
574 			case 0x0c:  SUBR(0, *curop->areg);                              break;
575 			case 0x0d:  tmp = irmb_din(curop); SUBR(tmp, *curop->areg);      break;
576 			case 0x0e:  tmp = irmb_din(curop); SUBR(tmp, Q);             break;
577 			case 0x0f:  tmp = irmb_din(curop); SUBR(tmp, 0);             break;
578 			case 0x10:  SUB(*curop->areg, Q);                               break;
579 			case 0x11:  SUB(*curop->areg, *curop->breg);                    break;
580 			case 0x12:  SUB(0, Q);                                          break;
581 			case 0x13:  SUB(0, *curop->breg);                               break;
582 			case 0x14:  SUB(0, *curop->areg);                               break;
583 			case 0x15:  tmp = irmb_din(curop); SUB(tmp, *curop->areg);       break;
584 			case 0x16:  tmp = irmb_din(curop); SUB(tmp, Q);                  break;
585 			case 0x17:  tmp = irmb_din(curop); SUB(tmp, 0);                  break;
586 			case 0x18:  OR(*curop->areg, Q);                                break;
587 			case 0x19:  OR(*curop->areg, *curop->breg);                     break;
588 			case 0x1a:  OR(0, Q);                                           break;
589 			case 0x1b:  OR(0, *curop->breg);                                break;
590 			case 0x1c:  OR(0, *curop->areg);                                break;
591 			case 0x1d:  OR(irmb_din(curop), *curop->areg);                   break;
592 			case 0x1e:  OR(irmb_din(curop), Q);                              break;
593 			case 0x1f:  OR(irmb_din(curop), 0);                              break;
594 			case 0x20:  AND(*curop->areg, Q);                               break;
595 			case 0x21:  AND(*curop->areg, *curop->breg);                    break;
596 			case 0x22:  AND(0, Q);                                          break;
597 			case 0x23:  AND(0, *curop->breg);                               break;
598 			case 0x24:  AND(0, *curop->areg);                               break;
599 			case 0x25:  AND(irmb_din(curop), *curop->areg);                  break;
600 			case 0x26:  AND(irmb_din(curop), Q);                         break;
601 			case 0x27:  AND(irmb_din(curop), 0);                         break;
602 			case 0x28:  IAND(*curop->areg, Q);                              break;
603 			case 0x29:  IAND(*curop->areg, *curop->breg);                   break;
604 			case 0x2a:  IAND(0, Q);                                         break;
605 			case 0x2b:  IAND(0, *curop->breg);                              break;
606 			case 0x2c:  IAND(0, *curop->areg);                              break;
607 			case 0x2d:  IAND(irmb_din(curop), *curop->areg);             break;
608 			case 0x2e:  IAND(irmb_din(curop), Q);                            break;
609 			case 0x2f:  IAND(irmb_din(curop), 0);                            break;
610 			case 0x30:  XOR(*curop->areg, Q);                               break;
611 			case 0x31:  XOR(*curop->areg, *curop->breg);                    break;
612 			case 0x32:  XOR(0, Q);                                          break;
613 			case 0x33:  XOR(0, *curop->breg);                               break;
614 			case 0x34:  XOR(0, *curop->areg);                               break;
615 			case 0x35:  XOR(irmb_din(curop), *curop->areg);                  break;
616 			case 0x36:  XOR(irmb_din(curop), Q);                         break;
617 			case 0x37:  XOR(irmb_din(curop), 0);                         break;
618 			case 0x38:  IXOR(*curop->areg, Q);                              break;
619 			case 0x39:  IXOR(*curop->areg, *curop->breg);                   break;
620 			case 0x3a:  IXOR(0, Q);                                         break;
621 			case 0x3b:  IXOR(0, *curop->breg);                              break;
622 			case 0x3c:  IXOR(0, *curop->areg);                              break;
623 			case 0x3d:  IXOR(irmb_din(curop), *curop->areg);             break;
624 			case 0x3e:  IXOR(irmb_din(curop), Q);                            break;
625 default:    case 0x3f:  IXOR(irmb_din(curop), 0);                            break;
626 		}
627 
628 		/* Evaluate flags */
629 		zresult = result & 0xFFFF;
630 		nflag = zresult >> 15;
631 
632 		prevop = curop;
633 
634 		/* Do destination and jump */
635 		switch (fu >> 6)
636 		{
637 			case 0x00:
638 			case 0x08:  DEST0;          JUMP0;  break;
639 			case 0x01:
640 			case 0x09:  DEST1;          JUMP0;  break;
641 			case 0x02:
642 			case 0x0a:  DEST2;          JUMP0;  break;
643 			case 0x03:
644 			case 0x0b:  DEST3;          JUMP0;  break;
645 			case 0x04:  DEST4_NOSHIFT;  JUMP0;  break;
646 			case 0x05:  DEST5_NOSHIFT;  JUMP0;  break;
647 			case 0x06:  DEST6_NOSHIFT;  JUMP0;  break;
648 			case 0x07:  DEST7_NOSHIFT;  JUMP0;  break;
649 			case 0x0c:  DEST4_SHIFT;    JUMP0;  break;
650 			case 0x0d:  DEST5_SHIFT;    JUMP0;  break;
651 			case 0x0e:  DEST6_SHIFT;    JUMP0;  break;
652 			case 0x0f:  DEST7_SHIFT;    JUMP0;  break;
653 
654 			case 0x10:
655 			case 0x18:  DEST0;          JUMP1;  break;
656 			case 0x11:
657 			case 0x19:  DEST1;          JUMP1;  break;
658 			case 0x12:
659 			case 0x1a:  DEST2;          JUMP1;  break;
660 			case 0x13:
661 			case 0x1b:  DEST3;          JUMP1;  break;
662 			case 0x14:  DEST4_NOSHIFT;  JUMP1;  break;
663 			case 0x15:  DEST5_NOSHIFT;  JUMP1;  break;
664 			case 0x16:  DEST6_NOSHIFT;  JUMP1;  break;
665 			case 0x17:  DEST7_NOSHIFT;  JUMP1;  break;
666 			case 0x1c:  DEST4_SHIFT;    JUMP1;  break;
667 			case 0x1d:  DEST5_SHIFT;    JUMP1;  break;
668 			case 0x1e:  DEST6_SHIFT;    JUMP1;  break;
669 			case 0x1f:  DEST7_SHIFT;    JUMP1;  break;
670 
671 			case 0x20:
672 			case 0x28:  DEST0;          JUMP2;  break;
673 			case 0x21:
674 			case 0x29:  DEST1;          JUMP2;  break;
675 			case 0x22:
676 			case 0x2a:  DEST2;          JUMP2;  break;
677 			case 0x23:
678 			case 0x2b:  DEST3;          JUMP2;  break;
679 			case 0x24:  DEST4_NOSHIFT;  JUMP2;  break;
680 			case 0x25:  DEST5_NOSHIFT;  JUMP2;  break;
681 			case 0x26:  DEST6_NOSHIFT;  JUMP2;  break;
682 			case 0x27:  DEST7_NOSHIFT;  JUMP2;  break;
683 			case 0x2c:  DEST4_SHIFT;    JUMP2;  break;
684 			case 0x2d:  DEST5_SHIFT;    JUMP2;  break;
685 			case 0x2e:  DEST6_SHIFT;    JUMP2;  break;
686 			case 0x2f:  DEST7_SHIFT;    JUMP2;  break;
687 
688 			case 0x30:
689 			case 0x38:  DEST0;          JUMP3;  break;
690 			case 0x31:
691 			case 0x39:  DEST1;          JUMP3;  break;
692 			case 0x32:
693 			case 0x3a:  DEST2;          JUMP3;  break;
694 			case 0x33:
695 			case 0x3b:  DEST3;          JUMP3;  break;
696 			case 0x34:  DEST4_NOSHIFT;  JUMP3;  break;
697 			case 0x35:  DEST5_NOSHIFT;  JUMP3;  break;
698 			case 0x36:  DEST6_NOSHIFT;  JUMP3;  break;
699 			case 0x37:  DEST7_NOSHIFT;  JUMP3;  break;
700 			case 0x3c:  DEST4_SHIFT;    JUMP3;  break;
701 			case 0x3d:  DEST5_SHIFT;    JUMP3;  break;
702 			case 0x3e:  DEST6_SHIFT;    JUMP3;  break;
703 			case 0x3f:  DEST7_SHIFT;    JUMP3;  break;
704 
705 			case 0x40:
706 			case 0x48:  DEST0;          JUMP4;  break;
707 			case 0x41:
708 			case 0x49:  DEST1;          JUMP4;  break;
709 			case 0x42:
710 			case 0x4a:  DEST2;          JUMP4;  break;
711 			case 0x43:
712 			case 0x4b:  DEST3;          JUMP4;  break;
713 			case 0x44:  DEST4_NOSHIFT;  JUMP4;  break;
714 			case 0x45:  DEST5_NOSHIFT;  JUMP4;  break;
715 			case 0x46:  DEST6_NOSHIFT;  JUMP4;  break;
716 			case 0x47:  DEST7_NOSHIFT;  JUMP4;  break;
717 			case 0x4c:  DEST4_SHIFT;    JUMP4;  break;
718 			case 0x4d:  DEST5_SHIFT;    JUMP4;  break;
719 			case 0x4e:  DEST6_SHIFT;    JUMP4;  break;
720 			case 0x4f:  DEST7_SHIFT;    JUMP4;  break;
721 
722 			case 0x50:
723 			case 0x58:  DEST0;          JUMP5;  break;
724 			case 0x51:
725 			case 0x59:  DEST1;          JUMP5;  break;
726 			case 0x52:
727 			case 0x5a:  DEST2;          JUMP5;  break;
728 			case 0x53:
729 			case 0x5b:  DEST3;          JUMP5;  break;
730 			case 0x54:  DEST4_NOSHIFT;  JUMP5;  break;
731 			case 0x55:  DEST5_NOSHIFT;  JUMP5;  break;
732 			case 0x56:  DEST6_NOSHIFT;  JUMP5;  break;
733 			case 0x57:  DEST7_NOSHIFT;  JUMP5;  break;
734 			case 0x5c:  DEST4_SHIFT;    JUMP5;  break;
735 			case 0x5d:  DEST5_SHIFT;    JUMP5;  break;
736 			case 0x5e:  DEST6_SHIFT;    JUMP5;  break;
737 			case 0x5f:  DEST7_SHIFT;    JUMP5;  break;
738 
739 			case 0x60:
740 			case 0x68:  DEST0;          JUMP6;  break;
741 			case 0x61:
742 			case 0x69:  DEST1;          JUMP6;  break;
743 			case 0x62:
744 			case 0x6a:  DEST2;          JUMP6;  break;
745 			case 0x63:
746 			case 0x6b:  DEST3;          JUMP6;  break;
747 			case 0x64:  DEST4_NOSHIFT;  JUMP6;  break;
748 			case 0x65:  DEST5_NOSHIFT;  JUMP6;  break;
749 			case 0x66:  DEST6_NOSHIFT;  JUMP6;  break;
750 			case 0x67:  DEST7_NOSHIFT;  JUMP6;  break;
751 			case 0x6c:  DEST4_SHIFT;    JUMP6;  break;
752 			case 0x6d:  DEST5_SHIFT;    JUMP6;  break;
753 			case 0x6e:  DEST6_SHIFT;    JUMP6;  break;
754 			case 0x6f:  DEST7_SHIFT;    JUMP6;  break;
755 
756 			case 0x70:
757 			case 0x78:  DEST0;          JUMP7;  break;
758 			case 0x71:
759 			case 0x79:  DEST1;          JUMP7;  break;
760 			case 0x72:
761 			case 0x7a:  DEST2;          JUMP7;  break;
762 			case 0x73:
763 			case 0x7b:  DEST3;          JUMP7;  break;
764 			case 0x74:  DEST4_NOSHIFT;  JUMP7;  break;
765 			case 0x75:  DEST5_NOSHIFT;  JUMP7;  break;
766 			case 0x76:  DEST6_NOSHIFT;  JUMP7;  break;
767 			case 0x77:  DEST7_NOSHIFT;  JUMP7;  break;
768 			case 0x7c:  DEST4_SHIFT;    JUMP7;  break;
769 			case 0x7d:  DEST5_SHIFT;    JUMP7;  break;
770 			case 0x7e:  DEST6_SHIFT;    JUMP7;  break;
771 			case 0x7f:  DEST7_SHIFT;    JUMP7;  break;
772 		}
773 
774 		/* Do write */
775 		if (!(prevop->flags & FL_MBRW))
776 			irmb_dout(prevop, Y);
777 
778 		/* ADDEN */
779 		if (!(prevop->flags & FL_ADDEN))
780 		{
781 			if (prevop->flags & FL_MBRW)
782 				m_irmb_latch = irmb_din(prevop);
783 			else
784 				m_irmb_latch = Y;
785 		}
786 	}
787 	g_profiler.stop();
788 
789 	logerror("%d instructions for Mathbox \n", icount);
790 
791 
792 #if IR_TIMING
793 	if (m_irmb_running == 0)
794 	{
795 		m_irmb_timer->adjust(attotime::from_hz(12000000) * icount);
796 		logerror("mb start ");
797 		IR_CPU_STATE();
798 	}
799 	else
800 	{
801 		logerror("mb start [busy!] ");
802 		IR_CPU_STATE();
803 		m_irmb_timer->adjust(attotime::from_hz(200) * icount);
804 	}
805 #else
806 	m_maincpu->set_input_line(M6809_FIRQ_LINE, ASSERT_LINE);
807 #endif
808 	m_irmb_running=1;
809 }
810 
811 
812 
813 
814 #if DISASSEMBLE_MB_ROM
disassemble_instruction(irobot_state::irmb_ops const * op)815 static void disassemble_instruction(irobot_state::irmb_ops const *op)
816 {
817 	int lp;
818 
819 	if (i==0)
820 		logerror(" Address  a b func stor: Q :Y, R, S RDCSAESM da m rs\n");
821 	logerror("%04X    : ",i);
822 	logerror("%X ",op->areg);
823 	logerror("%X ",op->breg);
824 
825 	lp=(op->func & 0x38)>>3;
826 	if ((lp&1)==0)
827 		lp|=1;
828 	else if((op->flags & FL_DIV) != 0)
829 		lp&=6;
830 	else
831 		logerror("*");
832 
833 	switch (lp)
834 	{
835 		case 0:
836 			logerror("ADD  ");
837 			break;
838 		case 1:
839 			logerror("SUBR ");
840 			break;
841 		case 2:
842 			logerror("SUB  ");
843 			break;
844 		case 3:
845 			logerror("OR   ");
846 			break;
847 		case 4:
848 			logerror("AND  ");
849 			break;
850 		case 5:
851 			logerror("AND  ");
852 			break;
853 		case 6:
854 			logerror("XOR  ");
855 			break;
856 		case 7:
857 			logerror("XNOR ");
858 			break;
859 	}
860 
861 	switch ((op->func & 0x1c0)>>6)
862 	{
863 		case 0:
864 			logerror("  - : Q :F,");
865 			break;
866 		case 1:
867 			logerror("  - : - :F,");
868 			break;
869 		case 2:
870 			logerror("  R%x: - :A,",op->breg);
871 			break;
872 		case 3:
873 			logerror("  R%x: - :F,",op->breg);
874 			break;
875 		case 4:
876 			logerror(">>R%x:>>Q:F,",op->breg);
877 			break;
878 		case 5:
879 			logerror(">>R%x: - :F,",op->breg);
880 			break;
881 		case 6:
882 			logerror("<<R%x:<<Q:F,",op->breg);
883 			break;
884 		case 7:
885 			logerror("<<R%x: - :F,",op->breg);
886 			break;
887 	}
888 
889 	lp=(op->func & 0x7);
890 	if ((lp&2)==0)
891 		lp|=2;
892 	else if((op->flags & FL_MULT) == 0)
893 		lp&=5;
894 	else
895 		logerror("*");
896 
897 	switch (lp)
898 	{
899 		case 0:
900 			logerror("R%x, Q ",op->areg);
901 			break;
902 		case 1:
903 			logerror("R%x,R%x ",op->areg,op->breg);
904 			break;
905 		case 2:
906 			logerror("00, Q ");
907 			break;
908 		case 3:
909 			logerror("00,R%x ",op->breg);
910 			break;
911 		case 4:
912 			logerror("00,R%x ",op->areg);
913 			break;
914 		case 5:
915 			logerror(" D,R%x ",op->areg);
916 			break;
917 		case 6:
918 			logerror(" D, Q ");
919 			break;
920 		case 7:
921 			logerror(" D,00 ");
922 			break;
923 	}
924 
925 	for (lp=0;lp<8;lp++)
926 		if (op->flags & (0x80>>lp))
927 			logerror("1");
928 		else
929 			logerror("0");
930 
931 	logerror(" %02X ",op->diradd);
932 	logerror("%X\n",op->ramsel);
933 	if (op->jtype)
934 	{
935 		logerror("              ");
936 		switch (op->jtype)
937 		{
938 			case 1:
939 				logerror("BO ");
940 				break;
941 			case 2:
942 				logerror("BZ ");
943 				break;
944 			case 3:
945 				logerror("BH ");
946 				break;
947 			case 4:
948 				logerror("BL ");
949 				break;
950 			case 5:
951 				logerror("B  ");
952 				break;
953 			case 6:
954 				logerror("Cl ");
955 				break;
956 			case 7:
957 				logerror("Return\n\n");
958 				break;
959 		}
960 		if (op->jtype != 7) logerror("  %04X    \n",op->nxtadd);
961 		if (op->jtype == 5) logerror("\n");
962 	}
963 }
964 #endif // DISASSEMBLE_MB_ROM
965