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