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