1 /*****************************************************************************
2 *
3 * i8x41.c
4 * Portable UPI-41/8041/8741/8042/8742 emulator V0.2
5 *
6 * Copyright (c) 1999 Juergen Buchmueller, all rights reserved.
7 *
8 * - This source code is released as freeware for non-commercial purposes.
9 * - You are free to use and redistribute this code in modified or
10 * unmodified form, provided you list me in the credits.
11 * - If you modify this source code, you must add a notice to each modified
12 * source file that it has been changed. If you're a nice person, you
13 * will clearly mark each change too. :)
14 * - If you wish to use this for commercial purposes, please contact me at
15 * pullmoll@t-online.de
16 * - The author of this copywritten work reserves the right to change the
17 * terms of its usage and license at any time, including retroactively
18 * - This entire notice must remain in the source code.
19 *
20 * This work is solely based on the
21 * 'Intel(tm) UPI(tm)-41AH/42AH Users Manual'
22 *
23 *
24 * **** Change Log ****
25 *
26 * TLP (10-Jan-2003) Changed ver from 0.1 to 0.2
27 * -�Changed the internal RAM mask from 3Fh to FFh . The i8x41/i8x42 have
28 * 128/256 bytes of internal RAM respectively.
29 * -�Added output port data to the debug register view window.
30 * -�Added some missing break commands to the set_reg switch function.
31 * -�Changed Ports 1 and 2 to latched types (Quasi-bidirectional).
32 * -�Stopped illegal access to Port 0 and 3 (they don't exist).
33 * -�Changed ANLD, ORLD and MOVD instructions to act through Port 2 in
34 * nibble mode.
35 * -�Copied F0 and moved F1 flags to the STATE flag bits where they belong.
36 * -�Corrected the 'addr' field by changing it from UINT8 to UINT16 for:
37 * 'INC @Rr' 'MOV @Rr,A' 'MOV @Rr,#N' 'XCH A,@Rr' 'XCHD A,@Rr'
38 * -�Added mask to TIMER when the TEST1 Counter overflows.
39 * - Seperated the prescaler out of the timer/counter, in order to correct
40 * the TEST1 input counter step.
41 * -�Moved TEST0 and TEST1 status flags out of the STATE register.
42 * STATE register uses these upper bits for user definable purposes.
43 * -�TEST0 and TEST1 input lines are now sampled during the JTx/JNTx
44 * instructions.
45 * -�Two methods for updating TEST1 input during counter mode are now
46 * supported depending on the mode of use required.
47 * You can use the Interrupt method, or input port read method.
48 * -�TIMER is now only controlled by the timer or counter (not both)
49 * ie, When Starting the Counter, Stop the Timer and viceversa.
50 * -�Nested IRQs of any sort are no longer allowed, however IRQs can
51 * become pending while a current interrupt is being serviced.
52 * -�IBF Interrupt now has priority over the Timer Interrupt, when they
53 * occur simultaneously.
54 * -�Add the external Interrupt FLAGS (Port 24, Port 25).
55 * To Do:
56 * -�Add the external DMA FLAGS (Port 26, Port 27). Page 4 and 37
57 *
58 *****************************************************************************/
59
60 #include <stdio.h>
61 #include "driver.h"
62 #include "state.h"
63 #include "mamedbg.h"
64 #include "i8x41.h"
65
66 typedef struct {
67 UINT16 ppc;
68 UINT16 pc;
69 UINT8 timer;
70 UINT8 prescaler;
71 UINT16 subtype;
72 UINT8 a;
73 UINT8 psw;
74 UINT8 state;
75 UINT8 enable;
76 UINT8 control;
77 UINT8 dbbi;
78 UINT8 dbbo;
79 UINT8 p1;
80 UINT8 p2;
81 UINT8 p2_hs;
82 UINT8 *ram;
83 int (*irq_callback)(int irqline);
84 } I8X41;
85
86 int i8x41_ICount;
87
88 static I8X41 i8x41;
89
90 /* Layout of the registers in the debugger */
91 static UINT8 i8x41_reg_layout[] = {
92 I8X41_PC, I8X41_SP, I8X41_PSW, I8X41_T, I8X41_DATA_DASM, I8X41_CMND_DASM, I8X41_STAT, I8X41_P1, I8X41_P2, -1,
93 I8X41_A, I8X41_R0, I8X41_R1, I8X41_R2, I8X41_R3, I8X41_R4, I8X41_R5, I8X41_R6, I8X41_R7, 0
94 };
95
96 /* Layout of the debugger windows x,y,w,h */
97 static UINT8 i8x41_win_layout[] = {
98 0, 0,80, 2, /* register window (top rows) */
99 0, 3,24,19, /* disassembler window (left colums) */
100 25, 3,55, 9, /* memory #1 window (right, upper middle) */
101 25,13,55, 9, /* memory #2 window (right, lower middle) */
102 0,23,80, 1, /* command line window (bottom rows) */
103 };
104
105 #define RM(a) cpu_readmem16(a)
106 #define WM(a,v) cpu_writemem16(a,v)
107 #define RP(a) cpu_readport16(a)
108 #define WP(a,v) cpu_writeport16(a,v)
109 #define ROP(pc) cpu_readop(pc)
110 #define ROP_ARG(pc) cpu_readop_arg(pc)
111
112 /* PC vectors */
113 #define V_RESET 0x000 /* power on address */
114 #define V_IBF 0x003 /* input buffer full interrupt vector */
115 #define V_TIMER 0x007 /* timer/counter interrupt vector */
116
117 /*
118 * Memory locations
119 * Note:
120 * 000-3ff internal ROM for 8x41 (1K)
121 * 400-7ff (more) internal for 8x42 type (2K)
122 * 800-8ff internal RAM
123 */
124 #define M_IRAM 0x800 /* internal RAM is mapped here */
125 #define M_BANK0 0x800 /* register bank 0 (8 times 8 bits) */
126 #define M_STACK 0x808 /* stack (8 times 16 bits) */
127 #define M_BANK1 0x818 /* register bank 1 (8 times 8 bits) */
128 #define M_USER 0x820 /* user memory (224 times 8 bits) */
129
130 /* PSW flag bits */
131 #define FC 0x80 /* carry flag */
132 #define FA 0x40 /* auxiliary carry flag */
133 #define Ff0 0x20 /* flag 0 - same flag as F0 below */
134 #define BS 0x10 /* bank select */
135 #define FU 0x08 /* unused */
136 #define SP 0x07 /* lower three bits are used as stack pointer */
137
138 /* STATE flag bits */
139 #define OBF 0x01 /* output buffer full */
140 #define IBF 0x02 /* input buffer full */
141 #define F0 0x04 /* flag 0 - same flag as Ff0 above */
142 #define F1 0x08 /* flag 1 */
143
144 /* ENABLE flag bits */
145 #define IBFI 0x01 /* input buffer full interrupt */
146 #define TCNTI 0x02 /* timer/counter interrupt */
147 #define DMA 0x04 /* DMA mode */
148 #define FLAGS 0x08 /* FLAGS mode */
149 #define T 0x10 /* timer */
150 #define CNT 0x20 /* counter */
151
152 /* CONTROL flag bits */
153 #define IBFI_EXEC 0x01 /* IBFI is currently being serviced */
154 #define IBFI_PEND 0x02 /* IBFI is pending */
155 #define TIRQ_EXEC 0x04 /* Timer interrupt is currently being serviced */
156 #define TIRQ_PEND 0x08 /* Timer interrupt is pending */
157 #define TEST1 0x10 /* Test1 line mode */
158 #define TOVF 0x20 /* Timer Overflow Flag */
159
160 #define IRQ_EXEC 0x05 /* Mask for IRQs being serviced */
161 #define IRQ_PEND 0x0a /* Mask for IRQs pending */
162
163
164 /* shorter names for the I8x41 structure elements */
165 #define PPC i8x41.ppc
166 #define PC i8x41.pc
167 #define A i8x41.a
168 #define PSW i8x41.psw
169 #define DBBI i8x41.dbbi
170 #define DBBO i8x41.dbbo
171 #define R(n) i8x41.ram[((PSW & BS) ? M_BANK1:M_BANK0)+(n)]
172 #define STATE i8x41.state
173 #define ENABLE i8x41.enable
174 #define TIMER i8x41.timer
175 #define PRESCALER i8x41.prescaler
176 #define P1 i8x41.p1
177 #define P2 i8x41.p2
178 #define P2_HS i8x41.p2_hs /* Port 2 Hand Shaking */
179 #define CONTROL i8x41.control
180
181
182
183 /************************************************************************
184 * Shortcuts
185 ************************************************************************/
186
PUSH_PC_TO_STACK(void)187 static INLINE void PUSH_PC_TO_STACK(void)
188 {
189 WM( M_STACK + (PSW&SP) * 2 + 0, PC & 0xff);
190 WM( M_STACK + (PSW&SP) * 2 + 1, ((PC >> 8) & 0x0f) | (PSW & 0xf0) );
191 PSW = (PSW & ~SP) | ((PSW + 1) & SP);
192 }
193
194
195 /************************************************************************
196 * Emulate the Instructions
197 ************************************************************************/
198
199 /***********************************
200 * illegal opcodes
201 ***********************************/
illegal(void)202 static INLINE void illegal(void)
203 {
204 logerror("i8x41 #%d: illegal opcode at 0x%03x: %02x\n", cpu_getactivecpu(), PC, ROP(PC));
205 }
206
207 /***********************************
208 * 0110 1rrr * ADD A,Rr
209 ***********************************/
add_r(int r)210 static INLINE void add_r(int r)
211 {
212 UINT8 res = A + R(r);
213 if( res < A ) PSW |= FC;
214 if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
215 A = res;
216 }
217
218 /***********************************
219 * 0110 000r
220 * ADD A,@Rr
221 ***********************************/
add_rm(int r)222 static INLINE void add_rm(int r)
223 {
224 UINT8 res = A + RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
225 if( res < A ) PSW |= FC;
226 if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
227 A = res;
228 }
229
230 /***********************************
231 * 0000 0011 7654 3210
232 * ADD A,#n
233 ***********************************/
add_i(void)234 static INLINE void add_i(void)
235 {
236 UINT8 res = A + ROP_ARG(PC);
237 PC++;
238 if( res < A ) PSW |= FC;
239 if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
240 A = res;
241 }
242
243 /***********************************
244 * 0111 1rrr
245 * ADDC A,Rr
246 ***********************************/
addc_r(int r)247 static INLINE void addc_r(int r)
248 {
249 UINT8 res = A + R(r) + (PSW >> 7);
250 if( res <= A ) PSW |= FC;
251 if( (res & 0x0f) <= (A & 0x0f) ) PSW |= FA;
252 A = res;
253 }
254
255 /***********************************
256 * 0111 000r
257 * ADDC A,@Rr
258 ***********************************/
addc_rm(int r)259 static INLINE void addc_rm(int r)
260 {
261 UINT8 res = A + RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) ) + (PSW >> 7);
262 if( res <= A ) PSW |= FC;
263 if( (res & 0x0f) <= (A & 0x0f) ) PSW |= FA;
264 A = res;
265 }
266
267 /***********************************
268 * 0001 0011 7654 3210
269 * ADDC A,#n
270 ***********************************/
addc_i(void)271 static INLINE void addc_i(void)
272 {
273 UINT8 res = A + ROP_ARG(PC);
274 PC++;
275 if( res < A ) PSW |= FC;
276 if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
277 A = res;
278 }
279
280 /***********************************
281 * 0101 1rrr
282 * ANL A,Rr
283 ***********************************/
anl_r(int r)284 static INLINE void anl_r(int r)
285 {
286 A = A & R(r);
287 }
288
289 /***********************************
290 * 0101 000r
291 * ANL A,@Rr
292 ***********************************/
anl_rm(int r)293 static INLINE void anl_rm(int r)
294 {
295 A = A & RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
296 }
297
298 /***********************************
299 * 0101 0011 7654 3210
300 * ANL A,#n
301 ***********************************/
anl_i(void)302 static INLINE void anl_i(void)
303 {
304 A = A & ROP_ARG(PC);
305 PC++;
306 }
307
308 /***********************************
309 * 1001 10pp 7654 3210
310 * ANL Pp,#n
311 ***********************************/
anl_p_i(int p)312 static INLINE void anl_p_i(int p)
313 {
314 UINT8 val = ROP_ARG(PC);
315 PC++;
316 /* changed to latched port scheme */
317 switch (p)
318 {
319 case 00: break; /* invalid port */
320 case 01: P1 &= val; WP(p, P1); break;
321 case 02: P2 &= val; WP(p, (P2 & P2_HS) ); break;
322 case 03: break; /* invalid port */
323 default: break;
324 }
325 }
326
327 /***********************************
328 * 1001 11pp 7654 3210
329 * ANLD Pp,A
330 ***********************************/
anld_p_a(int p)331 static INLINE void anld_p_a(int p)
332 {
333 /* added proper expanded port setup */
334 WP(2, (P2 & 0xf0) | 0x0c | p); /* AND mode */
335 WP(I8X41_ps, 0); /* activate command strobe */
336 WP(2, (A & 0x0f)); /* Expander to take care of AND function */
337 WP(I8X41_ps, 1); /* release command strobe */
338 }
339
340 /***********************************
341 * aaa1 0100 7654 3210
342 * CALL addr
343 ***********************************/
call_i(int page)344 static INLINE void call_i(int page)
345 {
346 UINT8 adr = ROP_ARG(PC);
347 PC++;
348 PUSH_PC_TO_STACK();
349 PC = page | adr;
350 }
351
352 /***********************************
353 * 0010 0111
354 * CLR A
355 ***********************************/
clr_a(void)356 static INLINE void clr_a(void)
357 {
358 A = 0;
359 }
360
361 /***********************************
362 * 1001 0111
363 * CLR C
364 ***********************************/
clr_c(void)365 static INLINE void clr_c(void)
366 {
367 PSW &= ~FC;
368 }
369
370 /***********************************
371 * 1000 0101
372 * CLR F0
373 ***********************************/
clr_f0(void)374 static INLINE void clr_f0(void)
375 {
376 PSW &= ~Ff0;
377 STATE &= ~F0;
378 }
379
380 /***********************************
381 * 1010 0101
382 * CLR F1
383 ***********************************/
clr_f1(void)384 static INLINE void clr_f1(void)
385 {
386 STATE &= ~F1;
387 }
388
389 /***********************************
390 * 0011 0111
391 * CPL A
392 ***********************************/
cpl_a(void)393 static INLINE void cpl_a(void)
394 {
395 A = ~A;
396 }
397
398 /***********************************
399 * 1010 0111
400 * CPL C
401 ***********************************/
cpl_c(void)402 static INLINE void cpl_c(void)
403 {
404 PSW ^= FC;
405 }
406
407 /***********************************
408 * 1001 0101
409 * CPL F0
410 ***********************************/
cpl_f0(void)411 static INLINE void cpl_f0(void)
412 {
413 PSW ^= Ff0;
414 STATE ^= F0;
415 }
416
417 /***********************************
418 * 1011 0101
419 * CPL F1
420 ***********************************/
cpl_f1(void)421 static INLINE void cpl_f1(void)
422 {
423 STATE ^= F1;
424 }
425
426 /***********************************
427 * 0101 0111
428 * DA A
429 ***********************************/
da_a(void)430 static INLINE void da_a(void)
431 {
432 UINT8 res = A + ((PSW & FA) || ((A & 0x0f) > 0x09)) ? 0x06 : 0x00;
433 if( (PSW & FC) || ((res & 0xf0) > 0x90) )
434 res += 0x60;
435 if( res < A )
436 PSW |= FC;
437 else
438 PSW &= ~FC;
439 A = res;
440 }
441
442 /***********************************
443 * 0000 0111
444 * DEC A
445 ***********************************/
dec_a(void)446 static INLINE void dec_a(void)
447 {
448 A -= 1;
449 }
450
451 /***********************************
452 * 1100 1rrr
453 * DEC Rr
454 ***********************************/
dec_r(int r)455 static INLINE void dec_r(int r)
456 {
457 R(r) -= 1;
458 }
459
460 /***********************************
461 * 0001 0101
462 * DIS I
463 ***********************************/
dis_i(void)464 static INLINE void dis_i(void)
465 {
466 ENABLE &= ~IBFI; /* disable input buffer full interrupt */
467 }
468
469 /***********************************
470 * 0011 0101
471 * DIS TCNTI
472 ***********************************/
dis_tcnti(void)473 static INLINE void dis_tcnti(void)
474 {
475 ENABLE &= ~TCNTI; /* disable timer/counter interrupt */
476 }
477
478 /***********************************
479 * 0111 1rrr 7654 3210
480 * DJNZ Rr,addr
481 ***********************************/
djnz_r_i(int r)482 static INLINE void djnz_r_i(int r)
483 {
484 UINT8 adr = ROP_ARG(PC);
485 PC++;
486 R(r) -= 1;
487 if( R(r) )
488 PC = (PC & 0x700) | adr;
489 }
490
491 /***********************************
492 * 1110 0101
493 * EN DMA
494 ***********************************/
en_dma(void)495 static INLINE void en_dma(void)
496 {
497 ENABLE |= DMA; /* enable DMA handshake lines */
498 P2_HS &= 0xbf;
499 WP(0x02, (P2 & P2_HS) );
500 }
501
502 /***********************************
503 * 1111 0101
504 * EN FLAGS
505 ***********************************/
en_flags(void)506 static INLINE void en_flags(void)
507 {
508 if( 0 == (ENABLE & FLAGS) )
509 {
510 /* Configure upper lines on Port 2 for IRQ handshaking (P24 and P25) */
511
512 ENABLE |= FLAGS;
513 if( STATE & OBF ) P2_HS |= 0x10;
514 else P2_HS &= 0xef;
515 if( STATE & IBF ) P2_HS |= 0x20;
516 else P2_HS &= 0xdf;
517 WP(0x02, (P2 & P2_HS) );
518 }
519 }
520
521 /***********************************
522 * 0000 0101
523 * EN I
524 ***********************************/
en_i(void)525 static INLINE void en_i(void)
526 {
527 if( 0 == (ENABLE & IBFI) )
528 {
529 ENABLE |= IBFI; /* enable input buffer full interrupt */
530 if( STATE & IBF ) /* already got data in the buffer? */
531 i8x41_set_irq_line(I8X41_INT_IBF, HOLD_LINE);
532 }
533 }
534
535 /***********************************
536 * 0010 0101
537 * EN TCNTI
538 ***********************************/
en_tcnti(void)539 static INLINE void en_tcnti(void)
540 {
541 ENABLE |= TCNTI; /* enable timer/counter interrupt */
542 }
543
544 /***********************************
545 * 0010 0010
546 * IN A,DBB
547 ***********************************/
in_a_dbb(void)548 static INLINE void in_a_dbb(void)
549 {
550 if( i8x41.irq_callback )
551 (*i8x41.irq_callback)(I8X41_INT_IBF);
552
553 STATE &= ~IBF; /* clear input buffer full flag */
554 if( ENABLE & FLAGS )
555 {
556 P2_HS &= 0xdf;
557 if( STATE & OBF ) P2_HS |= 0x10;
558 else P2_HS &= 0xef;
559 WP(0x02, (P2 & P2_HS) ); /* Clear the DBBI IRQ out on P25 */
560 }
561 A = DBBI;
562 }
563
564 /***********************************
565 * 0000 10pp
566 * IN A,Pp
567 ***********************************/
in_a_p(int p)568 static INLINE void in_a_p(int p)
569 {
570 /* changed to latched port scheme */
571 switch( p )
572 {
573 case 00: break; /* invalid port */
574 case 01: A = (RP(p) & P1); break;
575 case 02: A = (RP(p) & P2); break;
576 case 03: break; /* invalid port */
577 default: break;
578 }
579 }
580
581 /***********************************
582 * 0001 0111
583 * INC A
584 ***********************************/
inc_a(void)585 static INLINE void inc_a(void)
586 {
587 A += 1;
588 }
589
590 /***********************************
591 * 0001 1rrr
592 * INC Rr
593 ***********************************/
inc_r(int r)594 static INLINE void inc_r(int r)
595 {
596 R(r) += 1;
597 }
598
599 /***********************************
600 * 0001 000r
601 * INC @ Rr
602 ***********************************/
inc_rm(int r)603 static INLINE void inc_rm(int r)
604 {
605 UINT16 addr = M_IRAM + (R(r) & I8X42_intRAM_MASK);
606 WM( addr, RM(addr) + 1 );
607 }
608
609 /***********************************
610 * bbb1 0010
611 * JBb addr
612 ***********************************/
jbb_i(int bit)613 static INLINE void jbb_i(int bit)
614 {
615 UINT8 adr = ROP_ARG(PC);
616 PC += 1;
617 if( A & (1 << bit) )
618 PC = (PC & 0x700) | adr;
619 }
620
621 /***********************************
622 * 1111 0110
623 * JC addr
624 ***********************************/
jc_i(void)625 static INLINE void jc_i(void)
626 {
627 UINT8 adr = ROP_ARG(PC);
628 PC += 1;
629 if( PSW & FC )
630 PC = (PC & 0x700) | adr;
631 }
632
633 /***********************************
634 * 1011 0110
635 * JF0 addr
636 ***********************************/
jf0_i(void)637 static INLINE void jf0_i(void)
638 {
639 UINT8 adr = ROP_ARG(PC);
640 PC += 1;
641 if( STATE & F0 )
642 PC = (PC & 0x700) | adr;
643 }
644
645 /***********************************
646 * 0111 0110
647 * JF1 addr
648 ***********************************/
jf1_i(void)649 static INLINE void jf1_i(void)
650 {
651 UINT8 adr = ROP_ARG(PC);
652 PC += 1;
653 if( STATE & F1 )
654 PC = (PC & 0x700) | adr;
655 }
656
657 /***********************************
658 * aaa0 0100
659 * JMP addr
660 ***********************************/
jmp_i(int page)661 static INLINE void jmp_i(int page)
662 {
663 /* err.. do we have 10 or 11 PC bits?
664 * CALL is said to use 0aa1 (4 pages)
665 * JMP is said to use aaa0 (8 pages)
666 */
667 UINT8 adr = ROP_ARG(PC);
668 PC = page | adr;
669 }
670
671 /***********************************
672 * 1011 0011
673 * JMP @ A
674 ***********************************/
jmpp_a(void)675 static INLINE void jmpp_a(void)
676 {
677 UINT16 adr = (PC & 0x700) | A;
678 PC = (PC & 0x700) | RM(adr);
679 }
680
681 /***********************************
682 * 1110 0110
683 * JNC addr
684 ***********************************/
jnc_i(void)685 static INLINE void jnc_i(void)
686 {
687 UINT8 adr = ROP_ARG(PC);
688 PC += 1;
689 if( !(PSW & FC) )
690 PC = (PC & 0x700) | adr;
691 }
692
693 /***********************************
694 * 1101 0110
695 * JNIBF addr
696 ***********************************/
jnibf_i(void)697 static INLINE void jnibf_i(void)
698 {
699 UINT8 adr = ROP_ARG(PC);
700 PC += 1;
701 if( 0 == (STATE & IBF) )
702 PC = (PC & 0x700) | adr;
703 }
704
705 /***********************************
706 * 0010 0110
707 * JNT0 addr
708 ***********************************/
jnt0_i(void)709 static INLINE void jnt0_i(void)
710 {
711 UINT8 adr = ROP_ARG(PC);
712 PC += 1;
713 if( 0 == RP(I8X41_t0) )
714 PC = (PC & 0x700) | adr;
715 }
716
717 /***********************************
718 * 0100 0110
719 * JNT1 addr
720 ***********************************/
jnt1_i(void)721 static INLINE void jnt1_i(void)
722 {
723 UINT8 adr = ROP_ARG(PC);
724 PC += 1;
725 if( !(ENABLE & CNT) )
726 {
727 UINT8 level = RP(I8X41_t1);
728 if( level ) CONTROL |= TEST1;
729 else CONTROL &= ~TEST1;
730 }
731 if( !(CONTROL & TEST1) )
732 PC = (PC & 0x700) | adr;
733 }
734
735 /***********************************
736 * 1001 0110
737 * JNZ addr
738 ***********************************/
jnz_i(void)739 static INLINE void jnz_i(void)
740 {
741 UINT8 adr = ROP_ARG(PC);
742 PC += 1;
743 if( A )
744 PC = (PC & 0x700) | adr;
745 }
746
747 /***********************************
748 * 1000 0110
749 * JOBF addr
750 ***********************************/
jobf_i(void)751 static INLINE void jobf_i(void)
752 {
753 UINT8 adr = ROP_ARG(PC);
754 PC += 1;
755 if( STATE & OBF )
756 PC = (PC & 0x700) | adr;
757 }
758
759 /***********************************
760 * 0001 0110
761 * JTF addr
762 ***********************************/
jtf_i(void)763 static INLINE void jtf_i(void)
764 {
765 UINT8 adr = ROP_ARG(PC);
766 PC += 1;
767 if( CONTROL & TOVF )
768 PC = (PC & 0x700) | adr;
769 CONTROL &= ~TOVF;
770 }
771
772 /***********************************
773 * 0011 0110
774 * JT0 addr
775 ***********************************/
jt0_i(void)776 static INLINE void jt0_i(void)
777 {
778 UINT8 adr = ROP_ARG(PC);
779 PC += 1;
780 if( RP(I8X41_t0) )
781 PC = (PC & 0x700) | adr;
782 }
783
784 /***********************************
785 * 0101 0110
786 * JT1 addr
787 ***********************************/
jt1_i(void)788 static INLINE void jt1_i(void)
789 {
790 UINT8 adr = ROP_ARG(PC);
791 PC += 1;
792 if( !(ENABLE & CNT) )
793 {
794 UINT8 level = RP(I8X41_t1);
795 if( level ) CONTROL |= TEST1;
796 else CONTROL &= ~TEST1;
797 }
798 if( (CONTROL & TEST1) )
799 PC = (PC & 0x700) | adr;
800 }
801
802 /***********************************
803 * 1100 0110
804 * JZ addr
805 ***********************************/
jz_i(void)806 static INLINE void jz_i(void)
807 {
808 UINT8 adr = ROP_ARG(PC);
809 PC += 1;
810 if( !A )
811 PC = (PC & 0x700) | adr;
812 }
813
814 /***********************************
815 * 0010 0011
816 * MOV A,#n
817 ***********************************/
mov_a_i(void)818 static INLINE void mov_a_i(void)
819 {
820 A = ROP(PC);
821 PC += 1;
822 }
823
824 /***********************************
825 * 1100 0111
826 * MOV A,PSW
827 ***********************************/
mov_a_psw(void)828 static INLINE void mov_a_psw(void)
829 {
830 A = PSW;
831 }
832
833 /***********************************
834 * 1111 1rrr
835 * MOV A,Rr
836 ***********************************/
mov_a_r(int r)837 static INLINE void mov_a_r(int r)
838 {
839 A = R(r);
840 }
841
842 /***********************************
843 * 1111 000r
844 * MOV A,Rr
845 ***********************************/
mov_a_rm(int r)846 static INLINE void mov_a_rm(int r)
847 {
848 A = RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
849 }
850
851 /***********************************
852 * 0100 0010
853 * MOV A,T
854 ***********************************/
mov_a_t(void)855 static INLINE void mov_a_t(void)
856 {
857 A = TIMER;
858 }
859
860 /***********************************
861 * 1101 0111
862 * MOV PSW,A
863 ***********************************/
mov_psw_a(void)864 static INLINE void mov_psw_a(void)
865 {
866 PSW = A;
867 }
868
869 /***********************************
870 * 1010 1rrr
871 * MOV Rr,A
872 ***********************************/
mov_r_a(int r)873 static INLINE void mov_r_a(int r)
874 {
875 R(r) = A;
876 }
877
878 /***********************************
879 * 1011 1rrr
880 * MOV Rr,#n
881 ***********************************/
mov_r_i(int r)882 static INLINE void mov_r_i(int r)
883 {
884 UINT8 val = ROP_ARG(PC);
885 PC += 1;
886 R(r) = val;
887 }
888
889 /***********************************
890 * 1010 000r
891 * MOV @Rr,A
892 ***********************************/
mov_rm_a(int r)893 static INLINE void mov_rm_a(int r)
894 {
895 WM( M_IRAM + (R(r) & I8X42_intRAM_MASK), A );
896 }
897
898 /***********************************
899 * 1011 000r
900 * MOV @Rr,#n
901 ***********************************/
mov_rm_i(int r)902 static INLINE void mov_rm_i(int r)
903 {
904 UINT8 val = ROP_ARG(PC);
905 PC += 1;
906 WM( M_IRAM + (R(r) & I8X42_intRAM_MASK), val );
907 }
908
909 /***********************************
910 * 1001 0000
911 * MOV STS,A
912 ***********************************/
mov_sts_a(void)913 static INLINE void mov_sts_a(void)
914 {
915 STATE = (STATE & 0x0f) | (A & 0xf0);
916 }
917
918 /***********************************
919 * 0110 0010
920 * MOV T,A
921 ***********************************/
mov_t_a(void)922 static INLINE void mov_t_a(void)
923 {
924 TIMER = A;
925 }
926
927 /***********************************
928 * 0000 11pp
929 * MOVD A,Pp
930 ***********************************/
movd_a_p(int p)931 static INLINE void movd_a_p(int p)
932 {
933 /* added proper expanded port setup */
934 WP(2, (P2 & 0xf0) | 0x00 | p); /* READ mode */
935 WP(I8X41_ps, 0); /* activate command strobe */
936 A = RP(2) & 0xf;
937 WP(I8X41_ps, 1); /* release command strobe */
938 }
939
940 /***********************************
941 * 0011 11pp
942 * MOVD Pp,A
943 ***********************************/
movd_p_a(int p)944 static INLINE void movd_p_a(int p)
945 {
946 /* added proper expanded port setup */
947 WP(2, (P2 & 0xf0) | 0x04 | p); /* WRITE mode */
948 WP(I8X41_ps, 0); /* activate command strobe */
949 WP(2, A & 0x0f);
950 WP(I8X41_ps, 1); /* release command strobe */
951 }
952
953 /***********************************
954 * 1010 0011
955 * MOVP A,@A
956 ***********************************/
movp_a_am(void)957 static INLINE void movp_a_am(void)
958 {
959 UINT16 addr = (PC & 0x700) | A;
960 A = RM(addr);
961 }
962
963 /***********************************
964 * 1110 0011
965 * MOVP3 A,@A
966 ***********************************/
movp3_a_am(void)967 static INLINE void movp3_a_am(void)
968 {
969 UINT16 addr = 0x300 | A;
970 A = RM(addr);
971 }
972
973 /***********************************
974 * 0000 0000
975 * NOP
976 ***********************************/
nop(void)977 static INLINE void nop(void)
978 {
979 }
980
981 /***********************************
982 * 0100 1rrr
983 * ORL A,Rr
984 ***********************************/
orl_r(int r)985 static INLINE void orl_r(int r)
986 {
987 A = A | R(r);
988 }
989
990 /***********************************
991 * 0100 000r
992 * ORL A,@Rr
993 ***********************************/
orl_rm(int r)994 static INLINE void orl_rm(int r)
995 {
996 A = A | RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
997 }
998
999 /***********************************
1000 * 0100 0011 7654 3210
1001 * ORL A,#n
1002 ***********************************/
orl_i(void)1003 static INLINE void orl_i(void)
1004 {
1005 UINT8 val = ROP_ARG(PC);
1006 PC++;
1007 A = A | val;
1008 }
1009
1010 /***********************************
1011 * 1000 10pp 7654 3210
1012 * ORL Pp,#n
1013 ***********************************/
orl_p_i(int p)1014 static INLINE void orl_p_i(int p)
1015 {
1016 UINT8 val = ROP_ARG(PC);
1017 PC++;
1018 /* changed to latched port scheme */
1019 switch (p)
1020 {
1021 case 00: break; /* invalid port */
1022 case 01: P1 |= val; WP(p, P1); break;
1023 case 02: P2 |= val; WP(p, P2); break;
1024 case 03: break; /* invalid port */
1025 default: break;
1026 }
1027 }
1028
1029 /***********************************
1030 * 1000 11pp 7654 3210
1031 * ORLD Pp,A
1032 ***********************************/
orld_p_a(int p)1033 static INLINE void orld_p_a(int p)
1034 {
1035 /* added proper expanded port setup */
1036 WP(2, (P2 & 0xf0) | 0x08 | p); /* OR mode */
1037 WP(I8X41_ps, 0); /* activate command strobe */
1038 WP(2, A & 0x0f); /* Expander to take care of OR function */
1039 WP(I8X41_ps, 1); /* release command strobe */
1040 }
1041
1042 /***********************************
1043 * 0000 0010
1044 * OUT DBB,A
1045 ***********************************/
out_dbb_a(void)1046 static INLINE void out_dbb_a(void)
1047 {
1048 DBBO = A; /* DBB output buffer */
1049 STATE |= OBF; /* assert the output buffer full flag */
1050 if( ENABLE & FLAGS )
1051 {
1052 P2_HS |= 0x10;
1053 if( STATE & IBF ) P2_HS |= 0x20;
1054 else P2_HS &= 0xdf;
1055 WP(0x02, (P2 & P2_HS) ); /* Assert the DBBO IRQ out on P24 */
1056 }
1057 }
1058
1059 /***********************************
1060 * 0011 10pp
1061 * OUT Pp,A
1062 ***********************************/
out_p_a(int p)1063 static INLINE void out_p_a(int p)
1064 {
1065 /* changed to latched port scheme */
1066 switch (p)
1067 {
1068 case 00: break; /* invalid port */
1069 case 01: WP(p, A); P1 = A; break;
1070 case 02: WP(p, A); P2 = A; break;
1071 case 03: break; /* invalid port */
1072 default: break;
1073 }
1074 }
1075
1076 /***********************************
1077 * 1000 0011
1078 * RET
1079 ***********************************/
ret(void)1080 static INLINE void ret(void)
1081 {
1082 UINT8 msb;
1083 PSW = (PSW & ~SP) | ((PSW - 1) & SP);
1084 msb = RM(M_STACK + (PSW&SP) * 2 + 1);
1085 PC = RM(M_STACK + (PSW&SP) * 2 + 0);
1086 PC |= (msb << 8) & 0x700;
1087 }
1088
1089 /***********************************
1090 * 1001 0011
1091 * RETR
1092 ***********************************/
retr(void)1093 static INLINE void retr(void)
1094 {
1095 UINT8 msb;
1096 PSW = (PSW & ~SP) | ((PSW - 1) & SP);
1097 msb = RM(M_STACK + (PSW&SP) * 2 + 1);
1098 PC = RM(M_STACK + (PSW&SP) * 2 + 0);
1099 PC |= (msb << 8) & 0x700;
1100 PSW = (PSW & 0x0f) | (msb & 0xf0);
1101 CONTROL &= ~IBFI_EXEC;
1102 CONTROL &= ~TIRQ_EXEC;
1103 }
1104
1105 /***********************************
1106 * 1110 0111
1107 * RL A
1108 ***********************************/
rl_a(void)1109 static INLINE void rl_a(void)
1110 {
1111 A = (A << 1) | (A >> 7);
1112 }
1113
1114 /***********************************
1115 * 1111 0111
1116 * RLC A
1117 ***********************************/
rlc_a(void)1118 static INLINE void rlc_a(void)
1119 {
1120 UINT8 c = PSW >> 7;
1121 PSW = (PSW & ~FC) | (A >> 7);
1122 A = (A << 1) | c;
1123 }
1124
1125 /***********************************
1126 * 0111 0111
1127 * RR A
1128 ***********************************/
rr_a(void)1129 static INLINE void rr_a(void)
1130 {
1131 A = (A >> 1) | (A << 7);
1132 }
1133
1134 /***********************************
1135 * 0110 0111
1136 * RRC A
1137 ***********************************/
rrc_a(void)1138 static INLINE void rrc_a(void)
1139 {
1140 UINT8 c = PSW & 0x80;
1141 PSW = (PSW & ~FC) | (A << 7);
1142 A = (A >> 1) | c;
1143 }
1144
1145 /***********************************
1146 * 1100 0101
1147 * SEL RB0
1148 ***********************************/
sel_rb0(void)1149 static INLINE void sel_rb0(void)
1150 {
1151 PSW &= ~BS;
1152 }
1153
1154 /***********************************
1155 * 1101 0101
1156 * SEL RB1
1157 ***********************************/
sel_rb1(void)1158 static INLINE void sel_rb1(void)
1159 {
1160 PSW |= BS;
1161 }
1162
1163 /***********************************
1164 * 0110 0101
1165 * STOP TCNT
1166 ***********************************/
stop_tcnt(void)1167 static INLINE void stop_tcnt(void)
1168 {
1169 ENABLE &= ~(T|CNT);
1170 }
1171
1172 /***********************************
1173 * 0100 0101
1174 * STRT CNT
1175 ***********************************/
strt_cnt(void)1176 static INLINE void strt_cnt(void)
1177 {
1178 ENABLE |= CNT;
1179 ENABLE &= ~T;
1180 }
1181
1182 /***********************************
1183 * 0101 0101
1184 * STRT T
1185 ***********************************/
strt_t(void)1186 static INLINE void strt_t(void)
1187 {
1188 ENABLE |= T;
1189 ENABLE &= ~CNT;
1190 }
1191
1192 /***********************************
1193 * 0100 0111
1194 * SWAP A
1195 ***********************************/
swap_a(void)1196 static INLINE void swap_a(void)
1197 {
1198 A = (A << 4) | (A >> 4);
1199 }
1200
1201 /***********************************
1202 * 0010 1rrr
1203 * XCH A,Rr
1204 ***********************************/
xch_a_r(int r)1205 static INLINE void xch_a_r(int r)
1206 {
1207 UINT8 tmp = R(r);
1208 R(r) = A;
1209 A = tmp;
1210 }
1211
1212 /***********************************
1213 * 0010 000r
1214 * XCH A,@Rr
1215 ***********************************/
xch_a_rm(int r)1216 static INLINE void xch_a_rm(int r)
1217 {
1218 UINT16 addr = M_IRAM + (R(r) & I8X42_intRAM_MASK);
1219 UINT8 tmp = RM(addr);
1220 WM( addr, A );
1221 A = tmp;
1222 }
1223
1224 /***********************************
1225 * 0011 000r
1226 * XCHD A,@Rr
1227 ***********************************/
xchd_a_rm(int r)1228 static INLINE void xchd_a_rm(int r)
1229 {
1230 UINT16 addr = M_IRAM + (R(r) & I8X42_intRAM_MASK);
1231 UINT8 tmp = RM(addr);
1232 WM( addr, (tmp & 0xf0) | (A & 0x0f) );
1233 A = (A & 0xf0) | (tmp & 0x0f);
1234 }
1235
1236 /***********************************
1237 * 1101 1rrr
1238 * XRL A,Rr
1239 ***********************************/
xrl_r(int r)1240 static INLINE void xrl_r(int r)
1241 {
1242 A = A ^ R(r);
1243 }
1244
1245 /***********************************
1246 * 1101 000r
1247 * XRL A,@Rr
1248 ***********************************/
xrl_rm(int r)1249 static INLINE void xrl_rm(int r)
1250 {
1251 A = A ^ RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
1252 }
1253
1254 /***********************************
1255 * 1101 0011 7654 3210
1256 * XRL A,#n
1257 ***********************************/
xrl_i(void)1258 static INLINE void xrl_i(void)
1259 {
1260 UINT8 val = ROP_ARG(PC);
1261 PC++;
1262 A = A ^ val;
1263 }
1264
1265
1266 /***********************************************************************
1267 * Cycle Timings
1268 ***********************************************************************/
1269
1270 static UINT8 i8x41_cycles[] = {
1271 1,1,1,2,2,1,1,1,2,2,2,2,2,2,2,2,
1272 1,1,2,2,2,1,2,1,1,1,1,1,1,1,1,1,
1273 1,1,1,2,2,1,2,1,1,1,1,1,1,1,1,1,
1274 1,1,2,1,2,1,2,1,2,2,2,2,2,2,2,2,
1275 1,1,1,2,2,1,2,1,1,1,1,1,1,1,1,1,
1276 1,1,2,2,2,1,2,1,1,1,1,1,1,1,1,1,
1277 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,
1278 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,
1279 1,1,1,2,2,1,2,1,2,2,2,2,2,2,2,2,
1280 1,1,2,2,1,1,2,1,2,2,2,2,2,2,2,2,
1281 1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,
1282 2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,
1283 1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,
1284 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,
1285 1,1,1,2,2,1,2,1,1,1,1,1,1,1,1,1,
1286 1,1,2,1,2,1,2,1,2,2,2,2,2,2,2,2
1287 };
1288
1289
1290 /****************************************************************************
1291 * Inits CPU emulation
1292 ****************************************************************************/
1293
i8x41_init(void)1294 void i8x41_init(void)
1295 {
1296 int cpu = cpu_getactivecpu();
1297 state_save_register_UINT16("i8x41", cpu, "PPC", &i8x41.ppc, 1);
1298 state_save_register_UINT16("i8x41", cpu, "PC", &i8x41.pc, 1);
1299 state_save_register_UINT8 ("i8x41", cpu, "TIMER", &i8x41.timer, 1);
1300 state_save_register_UINT8 ("i8x41", cpu, "PRESCALER", &i8x41.prescaler,1);
1301 state_save_register_UINT16("i8x41", cpu, "SUBTYPE", &i8x41.subtype, 1);
1302 state_save_register_UINT8 ("i8x41", cpu, "A", &i8x41.a, 1);
1303 state_save_register_UINT8 ("i8x41", cpu, "PSW", &i8x41.psw, 1);
1304 state_save_register_UINT8 ("i8x41", cpu, "STATE", &i8x41.state, 1);
1305 state_save_register_UINT8 ("i8x41", cpu, "ENABLE", &i8x41.enable, 1);
1306 state_save_register_UINT8 ("i8x41", cpu, "CONTROL", &i8x41.control, 1);
1307 state_save_register_UINT8 ("i8x41", cpu, "DBBI", &i8x41.dbbi, 1);
1308 state_save_register_UINT8 ("i8x41", cpu, "DBBO", &i8x41.dbbo, 1);
1309 state_save_register_UINT8 ("i8x41", cpu, "P1", &i8x41.p1, 1);
1310 state_save_register_UINT8 ("i8x41", cpu, "P2", &i8x41.p2, 1);
1311 state_save_register_UINT8 ("i8x41", cpu, "P2_HS", &i8x41.p2_hs, 1);
1312 }
1313
1314
1315 /****************************************************************************
1316 * Reset registers to their initial values
1317 ****************************************************************************/
1318
i8x41_reset(void * param)1319 void i8x41_reset(void *param)
1320 {
1321 memset(&i8x41, 0, sizeof(I8X41));
1322 /* default to 8041 behaviour for DBBI/DBBO and extended commands */
1323 i8x41.subtype = 8041;
1324 /* ugly hack.. excuse my lazyness */
1325 i8x41.ram = memory_region(REGION_CPU1 + cpu_getactivecpu());
1326 ENABLE = IBFI | TCNTI;
1327 DBBI = 0xff;
1328 DBBO = 0xff;
1329 /* Set Ports 1 and 2 to input mode */
1330 P1 = 0xff;
1331 P2 = 0xff;
1332 P2_HS= 0xff;
1333 }
1334
1335
1336 /****************************************************************************
1337 * Shut down CPU emulation
1338 ****************************************************************************/
1339
i8x41_exit(void)1340 void i8x41_exit(void)
1341 {
1342 /* nothing to do */
1343 }
1344
1345
1346 /****************************************************************************
1347 * Execute cycles - returns number of cycles actually run
1348 ****************************************************************************/
1349
i8x41_execute(int cycles)1350 int i8x41_execute(int cycles)
1351 {
1352 int inst_cycles, T1_level;
1353
1354 i8x41_ICount = cycles;
1355
1356 do
1357 {
1358 UINT8 op = cpu_readop(PC);
1359
1360 PPC = PC;
1361
1362 CALL_MAME_DEBUG;
1363
1364 PC += 1;
1365 i8x41_ICount -= i8x41_cycles[op];
1366
1367 switch( op )
1368 {
1369 /* opcode cycles bitmask */
1370 case 0x00: /* 1: 0000 0000 */
1371 nop();
1372 break;
1373 case 0x01: /* 1: 0000 0001 */
1374 illegal();
1375 break;
1376 case 0x02: /* 1: 0000 0010 */
1377 out_dbb_a();
1378 break;
1379 case 0x03: /* 2: 0000 0011 */
1380 add_i();
1381 break;
1382 case 0x04: /* 2: aaa0 0100 */
1383 jmp_i(0x000);
1384 break;
1385 case 0x05: /* 1: 0000 0101 */
1386 en_i();
1387 break;
1388 case 0x06: /* 1: 0000 0110 */
1389 illegal();
1390 break;
1391 case 0x07: /* 1: 0000 0111 */
1392 dec_a();
1393 break;
1394 case 0x08: /* 2: 0000 10pp */
1395 case 0x09: /* 2: 0000 10pp */
1396 case 0x0a: /* 2: 0000 10pp */
1397 case 0x0b: /* 2: 0000 10pp */
1398 in_a_p(op & 3);
1399 break;
1400 case 0x0c: /* 2: 0000 11pp */
1401 case 0x0d: /* 2: 0000 11pp */
1402 case 0x0e: /* 2: 0000 11pp */
1403 case 0x0f: /* 2: 0000 11pp */
1404 movd_a_p(op & 3);
1405 break;
1406 case 0x10: /* 1: 0001 000r */
1407 inc_rm(0);
1408 break;
1409 case 0x11: /* 1: 0001 000r */
1410 inc_rm(1);
1411 break;
1412 case 0x12: /* 2: bbb1 0010 */
1413 jbb_i(0);
1414 break;
1415 case 0x13: /* 2: 0001 0011 */
1416 addc_i();
1417 break;
1418 case 0x14: /* 2: aaa1 0100 */
1419 call_i(0x000);
1420 break;
1421 case 0x15: /* 1: 0001 0101 */
1422 dis_i();
1423 break;
1424 case 0x16: /* 2: 0001 0110 */
1425 jtf_i();
1426 break;
1427 case 0x17: /* 1: 0001 0111 */
1428 inc_a();
1429 break;
1430 case 0x18: /* 1: 0001 1rrr */
1431 case 0x19: /* 1: 0001 1rrr */
1432 case 0x1a: /* 1: 0001 1rrr */
1433 case 0x1b: /* 1: 0001 1rrr */
1434 case 0x1c: /* 1: 0001 1rrr */
1435 case 0x1d: /* 1: 0001 1rrr */
1436 case 0x1e: /* 1: 0001 1rrr */
1437 case 0x1f: /* 1: 0001 1rrr */
1438 inc_r(op & 7);
1439 break;
1440 case 0x20: /* 1: 0010 000r */
1441 xch_a_rm(0);
1442 break;
1443 case 0x21: /* 1: 0010 000r */
1444 xch_a_rm(1);
1445 break;
1446 case 0x22: /* 1: 0010 0010 */
1447 in_a_dbb();
1448 break;
1449 case 0x23: /* 2: 0010 0011 */
1450 mov_a_i();
1451 break;
1452 case 0x24: /* 2: aaa0 0100 */
1453 jmp_i(0x100);
1454 break;
1455 case 0x25: /* 1: 0010 0101 */
1456 en_tcnti();
1457 break;
1458 case 0x26: /* 2: 0010 0110 */
1459 jnt0_i();
1460 break;
1461 case 0x27: /* 1: 0010 0111 */
1462 clr_a();
1463 break;
1464 case 0x28: /* 1: 0010 1rrr */
1465 case 0x29: /* 1: 0010 1rrr */
1466 case 0x2a: /* 1: 0010 1rrr */
1467 case 0x2b: /* 1: 0010 1rrr */
1468 case 0x2c: /* 1: 0010 1rrr */
1469 case 0x2d: /* 1: 0010 1rrr */
1470 case 0x2e: /* 1: 0010 1rrr */
1471 case 0x2f: /* 1: 0010 1rrr */
1472 xch_a_r(op & 7);
1473 break;
1474 case 0x30: /* 1: 0011 000r */
1475 xchd_a_rm(0);
1476 break;
1477 case 0x31: /* 1: 0011 000r */
1478 xchd_a_rm(1);
1479 break;
1480 case 0x32: /* 2: bbb1 0010 */
1481 jbb_i(1);
1482 break;
1483 case 0x33: /* 1: 0011 0101 */
1484 illegal();
1485 break;
1486 case 0x34: /* 2: aaa1 0100 */
1487 call_i(0x100);
1488 break;
1489 case 0x35: /* 1: 0000 0101 */
1490 dis_tcnti();
1491 break;
1492 case 0x36: /* 2: 0011 0110 */
1493 jt0_i();
1494 break;
1495 case 0x37: /* 1: 0011 0111 */
1496 cpl_a();
1497 break;
1498 case 0x38: /* 2: 0011 10pp */
1499 case 0x39: /* 2: 0011 10pp */
1500 case 0x3a: /* 2: 0011 10pp */
1501 case 0x3b: /* 2: 0011 10pp */
1502 out_p_a(op & 3);
1503 break;
1504 case 0x3c: /* 2: 0011 11pp */
1505 case 0x3d: /* 2: 0011 11pp */
1506 case 0x3e: /* 2: 0011 11pp */
1507 case 0x3f: /* 2: 0011 11pp */
1508 movd_p_a(op & 3);
1509 break;
1510 case 0x40: /* 1: 0100 000r */
1511 orl_rm(0);
1512 break;
1513 case 0x41: /* 1: 0100 000r */
1514 orl_rm(1);
1515 break;
1516 case 0x42: /* 1: 0100 0010 */
1517 mov_a_t();
1518 break;
1519 case 0x43: /* 2: 0100 0011 */
1520 orl_i();
1521 break;
1522 case 0x44: /* 2: aaa0 0100 */
1523 jmp_i(0x200);
1524 break;
1525 case 0x45: /* 1: 0100 0101 */
1526 strt_cnt();
1527 break;
1528 case 0x46: /* 2: 0100 0110 */
1529 jnt1_i();
1530 break;
1531 case 0x47: /* 1: 0100 0111 */
1532 swap_a();
1533 break;
1534 case 0x48: /* 1: 0100 1rrr */
1535 case 0x49: /* 1: 0100 1rrr */
1536 case 0x4a: /* 1: 0100 1rrr */
1537 case 0x4b: /* 1: 0100 1rrr */
1538 case 0x4c: /* 1: 0100 1rrr */
1539 case 0x4d: /* 1: 0100 1rrr */
1540 case 0x4e: /* 1: 0100 1rrr */
1541 case 0x4f: /* 1: 0100 1rrr */
1542 orl_r(op & 7);
1543 break;
1544 case 0x50: /* 1: 0101 000r */
1545 anl_rm(0);
1546 break;
1547 case 0x51: /* 1: 0101 000r */
1548 anl_rm(1);
1549 break;
1550 case 0x52: /* 2: bbb1 0010 */
1551 jbb_i(2);
1552 break;
1553 case 0x53: /* 2: 0101 0011 */
1554 anl_i();
1555 break;
1556 case 0x54: /* 2: aaa1 0100 */
1557 call_i(0x200);
1558 break;
1559 case 0x55: /* 1: 0101 0101 */
1560 strt_t();
1561 break;
1562 case 0x56: /* 2: 0101 0110 */
1563 jt1_i();
1564 break;
1565 case 0x57: /* 1: 0101 0111 */
1566 da_a();
1567 break;
1568 case 0x58: /* 1: 0101 1rrr */
1569 case 0x59: /* 1: 0101 1rrr */
1570 case 0x5a: /* 1: 0101 1rrr */
1571 case 0x5b: /* 1: 0101 1rrr */
1572 case 0x5c: /* 1: 0101 1rrr */
1573 case 0x5d: /* 1: 0101 1rrr */
1574 case 0x5e: /* 1: 0101 1rrr */
1575 case 0x5f: /* 1: 0101 1rrr */
1576 anl_r(op & 7);
1577 break;
1578 case 0x60: /* 1: 0110 000r */
1579 add_rm(0);
1580 break;
1581 case 0x61: /* 1: 0110 000r */
1582 add_rm(1);
1583 break;
1584 case 0x62: /* 1: 0110 0010 */
1585 mov_t_a();
1586 break;
1587 case 0x63: /* 1: 0110 0011 */
1588 illegal();
1589 break;
1590 case 0x64: /* 2: aaa0 0100 */
1591 jmp_i(0x300);
1592 break;
1593 case 0x65: /* 1: 0110 0101 */
1594 stop_tcnt();
1595 break;
1596 case 0x66: /* 1: 0110 0110 */
1597 illegal();
1598 break;
1599 case 0x67: /* 1: 0110 0111 */
1600 rrc_a();
1601 break;
1602 case 0x68: /* 1: 0110 1rrr */
1603 case 0x69: /* 1: 0110 1rrr */
1604 case 0x6a: /* 1: 0110 1rrr */
1605 case 0x6b: /* 1: 0110 1rrr */
1606 case 0x6c: /* 1: 0110 1rrr */
1607 case 0x6d: /* 1: 0110 1rrr */
1608 case 0x6e: /* 1: 0110 1rrr */
1609 case 0x6f: /* 1: 0110 1rrr */
1610 add_r(op & 7);
1611 break;
1612 case 0x70: /* 1: 0111 000r */
1613 addc_rm(0);
1614 break;
1615 case 0x71: /* 1: 0111 000r */
1616 addc_rm(1);
1617 break;
1618 case 0x72: /* 2: bbb1 0010 */
1619 jbb_i(3);
1620 break;
1621 case 0x73: /* 1: 0111 0011 */
1622 illegal();
1623 break;
1624 case 0x74: /* 2: aaa1 0100 */
1625 call_i(0x300);
1626 break;
1627 case 0x75: /* 1: 0111 0101 */
1628 illegal();
1629 break;
1630 case 0x76: /* 2: 0111 0110 */
1631 jf1_i();
1632 break;
1633 case 0x77: /* 1: 0111 0111 */
1634 rr_a();
1635 break;
1636 case 0x78: /* 1: 0111 1rrr */
1637 case 0x79: /* 1: 0111 1rrr */
1638 case 0x7a: /* 1: 0111 1rrr */
1639 case 0x7b: /* 1: 0111 1rrr */
1640 case 0x7c: /* 1: 0111 1rrr */
1641 case 0x7d: /* 1: 0111 1rrr */
1642 case 0x7e: /* 1: 0111 1rrr */
1643 case 0x7f: /* 1: 0111 1rrr */
1644 addc_r(op & 7);
1645 break;
1646 case 0x80: /* 1: 1000 0000 */
1647 illegal();
1648 break;
1649 case 0x81: /* 1: 1000 0001 */
1650 illegal();
1651 break;
1652 case 0x82: /* 1: 1000 0010 */
1653 illegal();
1654 break;
1655 case 0x83: /* 2: 1000 0011 */
1656 ret();
1657 break;
1658 case 0x84: /* 2: aaa0 0100 */
1659 jmp_i(0x400);
1660 break;
1661 case 0x85: /* 1: 1000 0101 */
1662 clr_f0();
1663 break;
1664 case 0x86: /* 2: 1000 0110 */
1665 jobf_i();
1666 break;
1667 case 0x87: /* 1: 1000 0111 */
1668 illegal();
1669 break;
1670 case 0x88: /* 2: 1000 10pp */
1671 case 0x89: /* 2: 1000 10pp */
1672 case 0x8a: /* 2: 1000 10pp */
1673 case 0x8b: /* 2: 1000 10pp */
1674 orl_p_i(op & 3);
1675 break;
1676 case 0x8c: /* 2: 1000 11pp */
1677 case 0x8d: /* 2: 1000 11pp */
1678 case 0x8e: /* 2: 1000 11pp */
1679 case 0x8f: /* 2: 1000 11pp */
1680 orld_p_a(op & 7);
1681 break;
1682 case 0x90: /* 1: 1001 0000 */
1683 mov_sts_a();
1684 break;
1685 case 0x91: /* 1: 1001 0001 */
1686 illegal();
1687 break;
1688 case 0x92: /* 2: bbb1 0010 */
1689 jbb_i(4);
1690 break;
1691 case 0x93: /* 2: 1001 0011 */
1692 retr();
1693 break;
1694 case 0x94: /* 1: aaa1 0100 */
1695 call_i(0x400);
1696 break;
1697 case 0x95: /* 1: 1001 0101 */
1698 cpl_f0();
1699 break;
1700 case 0x96: /* 2: 1001 0110 */
1701 jnz_i();
1702 break;
1703 case 0x97: /* 1: 1001 0111 */
1704 clr_c();
1705 break;
1706 case 0x98: /* 2: 1001 10pp , illegal port */
1707 case 0x99: /* 2: 1001 10pp */
1708 case 0x9a: /* 2: 1001 10pp */
1709 case 0x9b: /* 2: 1001 10pp , illegal port */
1710 anl_p_i(op & 3);
1711 break;
1712 case 0x9c: /* 2: 1001 11pp */
1713 case 0x9d: /* 2: 1001 11pp */
1714 case 0x9e: /* 2: 1001 11pp */
1715 case 0x9f: /* 2: 1001 11pp */
1716 anld_p_a(op & 7);
1717 break;
1718 case 0xa0: /* 1: 1010 000r */
1719 mov_rm_a(0);
1720 break;
1721 case 0xa1: /* 1: 1010 000r */
1722 mov_rm_a(1);
1723 break;
1724 case 0xa2: /* 1: 1010 0010 */
1725 illegal();
1726 break;
1727 case 0xa3: /* 2: 1010 0011 */
1728 movp_a_am();
1729 break;
1730 case 0xa4: /* 2: aaa0 0100 */
1731 jmp_i(0x500);
1732 break;
1733 case 0xa5: /* 1: 1010 0101 */
1734 clr_f1();
1735 break;
1736 case 0xa6: /* 1: 1010 0110 */
1737 illegal();
1738 break;
1739 case 0xa7: /* 1: 1010 0111 */
1740 cpl_c();
1741 break;
1742 case 0xa8: /* 1: 1010 1rrr */
1743 case 0xa9: /* 1: 1010 1rrr */
1744 case 0xaa: /* 1: 1010 1rrr */
1745 case 0xab: /* 1: 1010 1rrr */
1746 case 0xac: /* 1: 1010 1rrr */
1747 case 0xad: /* 1: 1010 1rrr */
1748 case 0xae: /* 1: 1010 1rrr */
1749 case 0xaf: /* 1: 1010 1rrr */
1750 mov_r_a(op & 7);
1751 break;
1752 case 0xb0: /* 2: 1011 000r */
1753 mov_rm_i(0);
1754 break;
1755 case 0xb1: /* 2: 1011 000r */
1756 mov_rm_i(1);
1757 break;
1758 case 0xb2: /* 2: bbb1 0010 */
1759 jbb_i(5);
1760 break;
1761 case 0xb3: /* 2: 1011 0011 */
1762 jmpp_a();
1763 break;
1764 case 0xb4: /* 2: aaa1 0100 */
1765 call_i(0x500);
1766 break;
1767 case 0xb5: /* 1: 1011 0101 */
1768 cpl_f1();
1769 break;
1770 case 0xb6: /* 2: 1011 0110 */
1771 jf0_i();
1772 break;
1773 case 0xb7: /* 1: 1011 0111 */
1774 illegal();
1775 break;
1776 case 0xb8: /* 2: 1011 1rrr */
1777 case 0xb9: /* 2: 1011 1rrr */
1778 case 0xba: /* 2: 1011 1rrr */
1779 case 0xbb: /* 2: 1011 1rrr */
1780 case 0xbc: /* 2: 1011 1rrr */
1781 case 0xbd: /* 2: 1011 1rrr */
1782 case 0xbe: /* 2: 1011 1rrr */
1783 case 0xbf: /* 2: 1011 1rrr */
1784 mov_r_i(op & 7);
1785 break;
1786 case 0xc0: /* 1: 1100 0000 */
1787 illegal();
1788 break;
1789 case 0xc1: /* 1: 1100 0001 */
1790 illegal();
1791 break;
1792 case 0xc2: /* 1: 1100 0010 */
1793 illegal();
1794 break;
1795 case 0xc3: /* 1: 1100 0011 */
1796 illegal();
1797 break;
1798 case 0xc4: /* 2: aaa0 0100 */
1799 jmp_i(0x600);
1800 break;
1801 case 0xc5: /* 1: 1100 0101 */
1802 sel_rb0();
1803 break;
1804 case 0xc6: /* 2: 1100 0110 */
1805 jz_i();
1806 break;
1807 case 0xc7: /* 1: 1100 0111 */
1808 mov_a_psw();
1809 break;
1810 case 0xc8: /* 1: 1100 1rrr */
1811 case 0xc9: /* 1: 1100 1rrr */
1812 case 0xca: /* 1: 1100 1rrr */
1813 case 0xcb: /* 1: 1100 1rrr */
1814 case 0xcc: /* 1: 1100 1rrr */
1815 case 0xcd: /* 1: 1100 1rrr */
1816 case 0xcf: /* 1: 1100 1rrr */
1817 dec_r(op & 7);
1818 break;
1819 case 0xd0: /* 1: 1101 000r */
1820 xrl_rm(0);
1821 break;
1822 case 0xd1: /* 1: 1101 000r */
1823 xrl_rm(1);
1824 break;
1825 case 0xd2: /* 2: bbb1 0010 */
1826 jbb_i(6);
1827 break;
1828 case 0xd3: /* 1: 1101 0011 */
1829 xrl_i();
1830 break;
1831 case 0xd4: /* 2: aaa1 0100 */
1832 call_i(0x600);
1833 break;
1834 case 0xd5: /* 1: 1101 0101 */
1835 sel_rb1();
1836 break;
1837 case 0xd6: /* 2: 1101 0110 */
1838 jnibf_i();
1839 break;
1840 case 0xd7: /* 1: 1101 0111 */
1841 mov_psw_a();
1842 break;
1843 case 0xd8: /* 1: 1101 1rrr */
1844 case 0xd9: /* 1: 1101 1rrr */
1845 case 0xda: /* 1: 1101 1rrr */
1846 case 0xdb: /* 1: 1101 1rrr */
1847 case 0xdc: /* 1: 1101 1rrr */
1848 case 0xdd: /* 1: 1101 1rrr */
1849 case 0xde: /* 1: 1101 1rrr */
1850 case 0xdf: /* 1: 1101 1rrr */
1851 xrl_r(op & 7);
1852 break;
1853 case 0xe0: /* 1: 1110 0000 */
1854 illegal();
1855 break;
1856 case 0xe1: /* 1: 1110 0001 */
1857 illegal();
1858 break;
1859 case 0xe2: /* 1: 1110 0010 */
1860 illegal();
1861 break;
1862 case 0xe3: /* 2: 1110 0011 */
1863 movp3_a_am();
1864 break;
1865 case 0xe4: /* 2: aaa0 0100 */
1866 jmp_i(0x700);
1867 break;
1868 case 0xe5: /* 1: 1110 0101 */
1869 en_dma();
1870 break;
1871 case 0xe6: /* 2: 1110 0110 */
1872 jnc_i();
1873 break;
1874 case 0xe7: /* 1: 1110 0111 */
1875 rl_a();
1876 break;
1877 case 0xe8: /* 2: 1110 1rrr */
1878 case 0xe9: /* 2: 1110 1rrr */
1879 case 0xea: /* 2: 1110 1rrr */
1880 case 0xeb: /* 2: 1110 1rrr */
1881 case 0xec: /* 2: 1110 1rrr */
1882 case 0xed: /* 2: 1110 1rrr */
1883 case 0xee: /* 2: 1110 1rrr */
1884 case 0xef: /* 2: 1110 1rrr */
1885 djnz_r_i(op & 7);
1886 break;
1887 case 0xf0: /* 1: 1111 000r */
1888 mov_a_rm(0);
1889 break;
1890 case 0xf1: /* 1: 1111 000r */
1891 mov_a_rm(1);
1892 break;
1893 case 0xf2: /* 2: bbb1 0010 */
1894 jbb_i(7);
1895 break;
1896 case 0xf3: /* 1: 1111 0011 */
1897 illegal();
1898 break;
1899 case 0xf4: /* 2: aaa1 0100 */
1900 call_i(0x700);
1901 break;
1902 case 0xf5: /* 1: 1111 0101 */
1903 en_flags();
1904 break;
1905 case 0xf6: /* 2: 1111 0110 */
1906 jc_i();
1907 break;
1908 case 0xf7: /* 1: 1111 0111 */
1909 rlc_a();
1910 break;
1911 case 0xf8: /* 1: 1111 1rrr */
1912 case 0xf9: /* 1: 1111 1rrr */
1913 case 0xfa: /* 1: 1111 1rrr */
1914 case 0xfb: /* 1: 1111 1rrr */
1915 case 0xfc: /* 1: 1111 1rrr */
1916 case 0xfd: /* 1: 1111 1rrr */
1917 case 0xfe: /* 1: 1111 1rrr */
1918 case 0xff: /* 1: 1111 1rrr */
1919 mov_a_r(op & 7);
1920 break;
1921 }
1922
1923
1924 if( ENABLE & CNT )
1925 {
1926 inst_cycles = i8x41_cycles[op];
1927 for ( ; inst_cycles > 0; inst_cycles-- )
1928 {
1929 T1_level = RP(I8X41_t1);
1930 if( (CONTROL & TEST1) && (T1_level == 0) ) /* Negative Edge */
1931 {
1932 TIMER++;
1933 if (TIMER == 0)
1934 {
1935 CONTROL |= TOVF;
1936 if( ENABLE & TCNTI )
1937 CONTROL |= TIRQ_PEND;
1938 }
1939 }
1940 if( T1_level ) CONTROL |= TEST1;
1941 else CONTROL &= ~TEST1;
1942 }
1943 }
1944
1945 if( ENABLE & T )
1946 {
1947 PRESCALER += i8x41_cycles[op];
1948 /**** timer is prescaled by 32 ****/
1949 if( PRESCALER >= 32 )
1950 {
1951 PRESCALER -= 32;
1952 TIMER++;
1953 if( TIMER == 0 )
1954 {
1955 CONTROL |= TOVF;
1956 if( ENABLE & TCNTI )
1957 CONTROL |= TIRQ_PEND;
1958 }
1959 }
1960 }
1961
1962 if( CONTROL & IRQ_PEND ) /* Are any Interrupts Pending ? */
1963 {
1964 if( 0 == (CONTROL & IRQ_EXEC) ) /* Are any Interrupts being serviced ? */
1965 {
1966 if( (ENABLE & IBFI) && (CONTROL & IBFI_PEND) )
1967 {
1968 PUSH_PC_TO_STACK();
1969 PC = V_IBF;
1970 CONTROL &= ~IBFI_PEND;
1971 CONTROL |= IBFI_EXEC;
1972 i8x41_ICount -= 2;
1973 }
1974 }
1975 if( 0 == (CONTROL & IRQ_EXEC) ) /* Are any Interrupts being serviced ? */
1976 {
1977 if( (ENABLE & TCNTI) && (CONTROL & TIRQ_PEND) )
1978 {
1979 PUSH_PC_TO_STACK();
1980 PC = V_TIMER;
1981 CONTROL &= ~TIRQ_PEND;
1982 CONTROL |= TIRQ_EXEC;
1983 if( ENABLE & T ) PRESCALER += 2; /* 2 states */
1984 i8x41_ICount -= 2; /* 2 states to take interrupt */
1985 }
1986 }
1987 }
1988
1989
1990 } while( i8x41_ICount > 0 );
1991
1992 return cycles - i8x41_ICount;
1993 }
1994
1995
1996 /****************************************************************************
1997 * Get all registers in given buffer
1998 ****************************************************************************/
1999
i8x41_get_context(void * dst)2000 unsigned i8x41_get_context(void *dst)
2001 {
2002 if( dst )
2003 memcpy(dst, &i8x41, sizeof(I8X41));
2004 return sizeof(I8X41);
2005 }
2006
2007
2008 /****************************************************************************
2009 * Set all registers to given values
2010 ****************************************************************************/
2011
i8x41_set_context(void * src)2012 void i8x41_set_context(void *src)
2013 {
2014 if( src )
2015 memcpy(&i8x41, src, sizeof(I8X41));
2016 }
2017
2018 /****************************************************************************
2019 * Return a specific register
2020 ****************************************************************************/
2021
i8x41_get_reg(int regnum)2022 unsigned i8x41_get_reg(int regnum)
2023 {
2024 switch( regnum )
2025 {
2026 case REG_PC:
2027 case I8X41_PC: return PC;
2028 case REG_SP:
2029 case I8X41_SP: return PSW & SP;
2030 case I8X41_PSW: return PSW;
2031 case I8X41_A: return A;
2032 case I8X41_T: return TIMER;
2033 case I8X41_R0: return R(0);
2034 case I8X41_R1: return R(1);
2035 case I8X41_R2: return R(2);
2036 case I8X41_R3: return R(3);
2037 case I8X41_R4: return R(4);
2038 case I8X41_R5: return R(5);
2039 case I8X41_R6: return R(6);
2040 case I8X41_R7: return R(7);
2041 case I8X41_DATA:
2042 // logerror("i8x41 #%d:%03x Reading DATA DBBI %02x. State was %02x, ", cpu_getactivecpu(), PC, DBBO, STATE);
2043 STATE &= ~OBF; /* reset the output buffer full flag */
2044 if( ENABLE & FLAGS)
2045 {
2046 P2_HS &= 0xef;
2047 if( STATE & IBF ) P2_HS |= 0x20;
2048 else P2_HS &= 0xdf;
2049 WP(0x02, (P2 & P2_HS) ); /* Clear the DBBO IRQ out on P24 */
2050 }
2051 // logerror("STATE now %02x\n", STATE);
2052 return DBBO;
2053 case I8X41_DATA_DASM: /* Same as I8X41_DATA, except this is used by the */
2054 /* debugger and does not upset the flag states */
2055 return DBBO;
2056 case I8X41_STAT:
2057 logerror("i8x41 #%d:%03x Reading STAT %02x\n", cpu_getactivecpu(), PC, STATE);
2058 return STATE;
2059 case REG_PREVIOUSPC: return PPC;
2060 default:
2061 if( regnum <= REG_SP_CONTENTS )
2062 {
2063 unsigned offset = (PSW & SP) + (REG_SP_CONTENTS - regnum);
2064 if( offset < 8 )
2065 return RM( M_STACK + offset ) | ( RM( M_STACK + offset + 1 ) << 8 );
2066 }
2067 }
2068 return 0;
2069 }
2070
2071 /****************************************************************************
2072 * Set a specific register
2073 ****************************************************************************/
2074
i8x41_set_reg(int regnum,unsigned val)2075 void i8x41_set_reg (int regnum, unsigned val)
2076 {
2077 switch( regnum )
2078 {
2079 case REG_PC:
2080 case I8X41_PC: PC = val & 0x7ff; break;
2081 case REG_SP:
2082 case I8X41_SP: PSW = (PSW & ~SP) | (val & SP); break;
2083 case I8X41_PSW: PSW = val; break;
2084 case I8X41_A: A = val; break;
2085 case I8X41_T: TIMER = val & 0x1fff; break;
2086 case I8X41_R0: R(0) = val; break;
2087 case I8X41_R1: R(1) = val; break;
2088 case I8X41_R2: R(2) = val; break;
2089 case I8X41_R3: R(3) = val; break;
2090 case I8X41_R4: R(4) = val; break;
2091 case I8X41_R5: R(5) = val; break;
2092 case I8X41_R6: R(6) = val; break;
2093 case I8X41_R7: R(7) = val; break;
2094 case I8X41_DATA:
2095 // logerror("i8x41 #%d:%03x Setting DATA DBBI to %02x. State was %02x ", cpu_getactivecpu(), PC, val,STATE);
2096 DBBI = val;
2097 if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
2098 DBBO = val;
2099 STATE &= ~F1;
2100 STATE |= IBF;
2101 if( ENABLE & IBFI )
2102 CONTROL |= IBFI_PEND;
2103 if( ENABLE & FLAGS)
2104 {
2105 P2_HS |= 0x20;
2106 if( 0 == (STATE & OBF) ) P2_HS |= 0x10;
2107 else P2_HS &= 0xef;
2108 WP(0x02, (P2 & P2_HS) ); /* Assert the DBBI IRQ out on P25 */
2109 }
2110 // logerror("State now %02x\n", STATE);
2111 break;
2112 case I8X41_DATA_DASM: /* Same as I8X41_DATA, except this is used by the */
2113 /* debugger and does not upset the flag states */
2114 DBBI = val;
2115 if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
2116 DBBO = val;
2117 break;
2118 case I8X41_CMND:
2119 // logerror("i8x41 #%d:%03x Setting CMND DBBI to %02x. State was %02x, ", cpu_getactivecpu(), PC, val,STATE);
2120 DBBI = val;
2121 if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
2122 DBBO = val;
2123 STATE |= F1;
2124 STATE |= IBF;
2125 if( ENABLE & IBFI )
2126 CONTROL |= IBFI_PEND;
2127 if( ENABLE & FLAGS)
2128 {
2129 P2_HS |= 0x20;
2130 if( 0 == (STATE & OBF) ) P2_HS |= 0x10;
2131 else P2_HS &= 0xef;
2132 WP(0x02, (P2 & P2_HS) ); /* Assert the DBBI IRQ out on P25 */
2133 }
2134 // logerror("State now %02x\n", STATE);
2135 break;
2136 case I8X41_CMND_DASM: /* Same as I8X41_CMND, except this is used by the */
2137 /* debugger and does not upset the flag states */
2138 DBBI = val;
2139 if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
2140 DBBO = val;
2141 break;
2142 case I8X41_STAT:
2143 logerror("i8x41 #%d:%03x Setting STAT DBBI to %02x\n", cpu_getactivecpu(), PC, val);
2144 /* writing status.. hmm, should we issue interrupts here too? */
2145 STATE = val;
2146 break;
2147 default:
2148 if( regnum <= REG_SP_CONTENTS )
2149 {
2150 unsigned offset = (PSW & SP) + (REG_SP_CONTENTS - regnum);
2151 if( offset < 8 )
2152 {
2153 WM( M_STACK + offset, val & 0xff );
2154 WM( M_STACK + offset + 1, (val >> 8) & 0xff );
2155 }
2156 }
2157 }
2158 }
2159
2160
2161 /****************************************************************************
2162 * Set IRQ line state
2163 ****************************************************************************/
2164
i8x41_set_irq_line(int irqline,int state)2165 void i8x41_set_irq_line(int irqline, int state)
2166 {
2167 switch( irqline )
2168 {
2169 case I8X41_INT_IBF:
2170 if (state != CLEAR_LINE)
2171 {
2172 STATE |= IBF;
2173 if (ENABLE & IBFI)
2174 {
2175 CONTROL |= IBFI_PEND;
2176 }
2177 }
2178 else
2179 {
2180 STATE &= ~IBF;
2181 }
2182 break;
2183
2184 case I8X41_INT_TEST1:
2185 if( state != CLEAR_LINE )
2186 {
2187 CONTROL |= TEST1;
2188 }
2189 else
2190 {
2191 /* high to low transition? */
2192 if( CONTROL & TEST1 )
2193 {
2194 /* counting enabled? */
2195 if( ENABLE & CNT )
2196 {
2197 TIMER++;
2198 if( TIMER == 0 )
2199 {
2200 CONTROL |= TOVF;
2201 CONTROL |= TIRQ_PEND;
2202 }
2203 }
2204 }
2205 CONTROL &= ~TEST1;
2206 }
2207 break;
2208 }
2209 }
2210
i8x41_set_irq_callback(int (* callback)(int irqline))2211 void i8x41_set_irq_callback(int (*callback)(int irqline))
2212 {
2213 i8x41.irq_callback = callback;
2214 }
2215
2216
2217 /****************************************************************************
2218 * Return a formatted string for a register
2219 ****************************************************************************/
2220
i8x41_info(void * context,int regnum)2221 const char *i8x41_info(void *context, int regnum)
2222 {
2223 static char buffer[8][15+1];
2224 static int which = 0;
2225 I8X41 *r = context;
2226
2227 which = (which+1) % 8;
2228 buffer[which][0] = '\0';
2229 if( !context )
2230 r = &i8x41;
2231
2232 switch( regnum )
2233 {
2234 case CPU_INFO_REG+I8X41_PC: sprintf(buffer[which], "PC:%04X", r->pc); break;
2235 case CPU_INFO_REG+I8X41_SP: sprintf(buffer[which], "S:%X", r->psw & SP); break;
2236 case CPU_INFO_REG+I8X41_PSW:sprintf(buffer[which], "PSW:%02X", r->psw); break;
2237 case CPU_INFO_REG+I8X41_A: sprintf(buffer[which], "A:%02X", r->a); break;
2238 case CPU_INFO_REG+I8X41_T: sprintf(buffer[which], "T:%02X.%02X", r->timer, (r->prescaler & 0x1f) ); break;
2239 case CPU_INFO_REG+I8X41_R0: sprintf(buffer[which], "R0:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 0]); break;
2240 case CPU_INFO_REG+I8X41_R1: sprintf(buffer[which], "R1:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 1]); break;
2241 case CPU_INFO_REG+I8X41_R2: sprintf(buffer[which], "R2:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 2]); break;
2242 case CPU_INFO_REG+I8X41_R3: sprintf(buffer[which], "R3:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 3]); break;
2243 case CPU_INFO_REG+I8X41_R4: sprintf(buffer[which], "R4:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 4]); break;
2244 case CPU_INFO_REG+I8X41_R5: sprintf(buffer[which], "R5:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 5]); break;
2245 case CPU_INFO_REG+I8X41_R6: sprintf(buffer[which], "R6:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 6]); break;
2246 case CPU_INFO_REG+I8X41_R7: sprintf(buffer[which], "R7:%02X", i8x41.ram[((r->psw & BS) ? M_BANK1 : M_BANK0) + 7]); break;
2247 case CPU_INFO_REG+I8X41_P1: sprintf(buffer[which], "P1:%02X", i8x41.p1); break;
2248 case CPU_INFO_REG+I8X41_P2: sprintf(buffer[which], "P2:%02X", i8x41.p2); break;
2249 case CPU_INFO_REG+I8X41_DATA_DASM:sprintf(buffer[which], "DBBI:%02X", i8x41.dbbi); break;
2250 case CPU_INFO_REG+I8X41_CMND_DASM:sprintf(buffer[which], "DBBO:%02X", i8x41.dbbo); break;
2251 case CPU_INFO_REG+I8X41_STAT:sprintf(buffer[which], "STAT:%02X", i8x41.state); break;
2252 case CPU_INFO_FLAGS:
2253 sprintf(buffer[which], "%c%c%c%c%c%c%c%c",
2254 r->psw & 0x80 ? 'C':'.',
2255 r->psw & 0x40 ? 'A':'.',
2256 r->psw & 0x20 ? '0':'.',
2257 r->psw & 0x10 ? 'B':'.',
2258 r->psw & 0x08 ? '?':'.',
2259 r->psw & 0x04 ? 's':'.',
2260 r->psw & 0x02 ? 's':'.',
2261 r->psw & 0x01 ? 's':'.');
2262 break;
2263 case CPU_INFO_NAME: return "I8X41";
2264 case CPU_INFO_FAMILY: return "Intel 8x41";
2265 case CPU_INFO_VERSION: return "0.2";
2266 case CPU_INFO_FILE: return __FILE__;
2267 case CPU_INFO_CREDITS: return "Copyright (c) 1999 Juergen Buchmueller, all rights reserved.";
2268 case CPU_INFO_REG_LAYOUT: return (const char*)i8x41_reg_layout;
2269 case CPU_INFO_WIN_LAYOUT: return (const char*)i8x41_win_layout;
2270 }
2271 return buffer[which];
2272 }
2273
i8x41_dasm(char * buffer,unsigned pc)2274 unsigned i8x41_dasm(char *buffer, unsigned pc)
2275 {
2276 #ifdef MAME_DEBUG
2277 return Dasm8x41( buffer, pc );
2278 #else
2279 sprintf( buffer, "$%02X", cpu_readop(pc) );
2280 return 1;
2281 #endif
2282 }
2283