summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/i8x41/i8x41.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/i8x41/i8x41.c')
-rw-r--r--src/emu/cpu/i8x41/i8x41.c2316
1 files changed, 2316 insertions, 0 deletions
diff --git a/src/emu/cpu/i8x41/i8x41.c b/src/emu/cpu/i8x41/i8x41.c
new file mode 100644
index 00000000000..e5642bbabca
--- /dev/null
+++ b/src/emu/cpu/i8x41/i8x41.c
@@ -0,0 +1,2316 @@
+/*****************************************************************************
+ *
+ * i8x41.c
+ * Portable UPI-41/8041/8741/8042/8742 emulator V0.2
+ *
+ * Copyright (c) 1999 Juergen Buchmueller, all rights reserved.
+ *
+ * Copyright (C) 1998,1999,2000 Juergen Buchmueller, all rights reserved.
+ * You can contact me at juergen@mame.net or pullmoll@stop1984.com
+ *
+ * - This source code is released as freeware for non-commercial purposes
+ * as part of the M.A.M.E. (Multiple Arcade Machine Emulator) project.
+ * The licensing terms of MAME apply to this piece of code for the MAME
+ * project and derviative works, as defined by the MAME license. You
+ * may opt to make modifications, improvements or derivative works under
+ * that same conditions, and the MAME project may opt to keep
+ * modifications, improvements or derivatives under their terms exclusively.
+ *
+ * - Alternatively you can choose to apply the terms of the "GPL" (see
+ * below) to this - and only this - piece of code or your derivative works.
+ * Note that in no case your choice can have any impact on any other
+ * source code of the MAME project, or binary, or executable, be it closely
+ * or losely related to this piece of code.
+ *
+ * - At your choice you are also free to remove either licensing terms from
+ * this file and continue to use it under only one of the two licenses. Do this
+ * if you think that licenses are not compatible (enough) for you, or if you
+ * consider either license 'too restrictive' or 'too free'.
+ *
+ * - GPL (GNU General Public License)
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * This work is solely based on the
+ * 'Intel(tm) UPI(tm)-41AH/42AH Users Manual'
+ *
+ *
+ * **** Change Log ****
+ * HJB (19-Dec-2004) changed version to 0.3
+ * - Tried to handle accesses to registers in get_info/set_info
+ * before i8x41.ram is is initialized.
+ * - cosmetics: readability in get_info/set_info, replaced non-ASCII
+ * codes in comments, add 'ex' tabstop definition
+ *
+ * TLP (10-Jan-2003) Changed ver from 0.1 to 0.2
+ * - Changed the internal RAM mask from 3Fh to FFh . The i8x41/i8x42 have
+ * 128/256 bytes of internal RAM respectively.
+ * - Added output port data to the debug register view window.
+ * - Added some missing break commands to the set_reg switch function.
+ * - Changed Ports 1 and 2 to latched types (Quasi-bidirectional).
+ * - Stopped illegal access to Port 0 and 3 (they don't exist).
+ * - Changed ANLD, ORLD and MOVD instructions to act through Port 2 in
+ * nibble mode.
+ * - Copied F0 and moved F1 flags to the STATE flag bits where they belong.
+ * - Corrected the 'addr' field by changing it from UINT8 to UINT16 for:
+ * 'INC @Rr' 'MOV @Rr,A' 'MOV @Rr,#N' 'XCH A,@Rr' 'XCHD A,@Rr'
+ * - Added mask to TIMER when the TEST1 Counter overflows.
+ * - Seperated the prescaler out of the timer/counter, in order to correct
+ * the TEST1 input counter step.
+ * - Moved TEST0 and TEST1 status flags out of the STATE register.
+ * STATE register uses these upper bits for user definable purposes.
+ * - TEST0 and TEST1 input lines are now sampled during the JTx/JNTx
+ * instructions.
+ * - Two methods for updating TEST1 input during counter mode are now
+ * supported depending on the mode of use required.
+ * You can use the Interrupt method, or input port read method.
+ * - TIMER is now only controlled by the timer or counter (not both)
+ * ie, When Starting the Counter, Stop the Timer and viceversa.
+ * - Nested IRQs of any sort are no longer allowed, however IRQs can
+ * become pending while a current interrupt is being serviced.
+ * - IBF Interrupt now has priority over the Timer Interrupt, when they
+ * occur simultaneously.
+ * - Add the external Interrupt FLAGS (Port 24, Port 25).
+ * To Do:
+ * - Add the external DMA FLAGS (Port 26, Port 27). Page 4 and 37
+ *
+ *****************************************************************************/
+
+#include "debugger.h"
+#include "i8x41.h"
+
+typedef struct {
+ UINT16 ppc;
+ UINT16 pc;
+ UINT8 timer;
+ UINT8 prescaler;
+ UINT16 subtype;
+ UINT8 a;
+ UINT8 psw;
+ UINT8 state;
+ UINT8 enable;
+ UINT8 control;
+ UINT8 dbbi;
+ UINT8 dbbo;
+ UINT8 p1;
+ UINT8 p2;
+ UINT8 p2_hs;
+ UINT8 *ram;
+ int (*irq_callback)(int irqline);
+} I8X41;
+
+int i8x41_ICount;
+
+static I8X41 i8x41;
+
+#define RM(a) program_read_byte_8(a)
+#define WM(a,v) program_write_byte_8(a,v)
+#define RP(a) io_read_byte_8(a)
+#define WP(a,v) io_write_byte_8(a,v)
+#define ROP(pc) cpu_readop(pc)
+#define ROP_ARG(pc) cpu_readop_arg(pc)
+
+/* PC vectors */
+#define V_RESET 0x000 /* power on address */
+#define V_IBF 0x003 /* input buffer full interrupt vector */
+#define V_TIMER 0x007 /* timer/counter interrupt vector */
+
+/*
+ * Memory locations
+ * Note:
+ * 000-3ff internal ROM for 8x41 (1K)
+ * 400-7ff (more) internal for 8x42 type (2K)
+ * 800-8ff internal RAM
+ */
+#define M_IRAM 0x800 /* internal RAM is mapped here */
+#define M_BANK0 0x800 /* register bank 0 (8 times 8 bits) */
+#define M_STACK 0x808 /* stack (8 times 16 bits) */
+#define M_BANK1 0x818 /* register bank 1 (8 times 8 bits) */
+#define M_USER 0x820 /* user memory (224 times 8 bits) */
+
+/* PSW flag bits */
+#define FC 0x80 /* carry flag */
+#define FA 0x40 /* auxiliary carry flag */
+#define Ff0 0x20 /* flag 0 - same flag as F0 below */
+#define BS 0x10 /* bank select */
+#define FU 0x08 /* unused */
+#define SP 0x07 /* lower three bits are used as stack pointer */
+
+/* STATE flag bits */
+#define OBF 0x01 /* output buffer full */
+#define IBF 0x02 /* input buffer full */
+#define F0 0x04 /* flag 0 - same flag as Ff0 above */
+#define F1 0x08 /* flag 1 */
+
+/* ENABLE flag bits */
+#define IBFI 0x01 /* input buffer full interrupt */
+#define TCNTI 0x02 /* timer/counter interrupt */
+#define DMA 0x04 /* DMA mode */
+#define FLAGS 0x08 /* FLAGS mode */
+#define T 0x10 /* timer */
+#define CNT 0x20 /* counter */
+
+/* CONTROL flag bits */
+#define IBFI_EXEC 0x01 /* IBFI is currently being serviced */
+#define IBFI_PEND 0x02 /* IBFI is pending */
+#define TIRQ_EXEC 0x04 /* Timer interrupt is currently being serviced */
+#define TIRQ_PEND 0x08 /* Timer interrupt is pending */
+#define TEST1 0x10 /* Test1 line mode */
+#define TOVF 0x20 /* Timer Overflow Flag */
+
+#define IRQ_EXEC 0x05 /* Mask for IRQs being serviced */
+#define IRQ_PEND 0x0a /* Mask for IRQs pending */
+
+
+/* shorter names for the I8x41 structure elements */
+#define PPC i8x41.ppc
+#define PC i8x41.pc
+#define A i8x41.a
+#define PSW i8x41.psw
+#define DBBI i8x41.dbbi
+#define DBBO i8x41.dbbo
+#define R(n) i8x41.ram[((PSW & BS) ? M_BANK1:M_BANK0)+(n)]
+#define STATE i8x41.state
+#define ENABLE i8x41.enable
+#define TIMER i8x41.timer
+#define PRESCALER i8x41.prescaler
+#define P1 i8x41.p1
+#define P2 i8x41.p2
+#define P2_HS i8x41.p2_hs /* Port 2 Hand Shaking */
+#define CONTROL i8x41.control
+
+
+static void set_irq_line(int irqline, int state);
+
+
+/************************************************************************
+ * Shortcuts
+ ************************************************************************/
+
+INLINE void PUSH_PC_TO_STACK(void)
+{
+ WM( M_STACK + (PSW&SP) * 2 + 0, PC & 0xff);
+ WM( M_STACK + (PSW&SP) * 2 + 1, ((PC >> 8) & 0x0f) | (PSW & 0xf0) );
+ PSW = (PSW & ~SP) | ((PSW + 1) & SP);
+}
+
+
+/************************************************************************
+ * Emulate the Instructions
+ ************************************************************************/
+
+/***********************************
+ * illegal opcodes
+ ***********************************/
+INLINE void illegal(void)
+{
+ logerror("i8x41 #%d: illegal opcode at 0x%03x: %02x\n", cpu_getactivecpu(), PC, ROP(PC));
+}
+
+/***********************************
+ * 0110 1rrr * ADD A,Rr
+ ***********************************/
+INLINE void add_r(int r)
+{
+ UINT8 res = A + R(r);
+ if( res < A ) PSW |= FC;
+ if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
+ A = res;
+}
+
+/***********************************
+ * 0110 000r
+ * ADD A,@Rr
+ ***********************************/
+INLINE void add_rm(int r)
+{
+ UINT8 res = A + RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
+ if( res < A ) PSW |= FC;
+ if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
+ A = res;
+}
+
+/***********************************
+ * 0000 0011 7654 3210
+ * ADD A,#n
+ ***********************************/
+INLINE void add_i(void)
+{
+ UINT8 res = A + ROP_ARG(PC);
+ PC++;
+ if( res < A ) PSW |= FC;
+ if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
+ A = res;
+}
+
+/***********************************
+ * 0111 1rrr
+ * ADDC A,Rr
+ ***********************************/
+INLINE void addc_r(int r)
+{
+ UINT8 res = A + R(r) + (PSW >> 7);
+ if( res <= A ) PSW |= FC;
+ if( (res & 0x0f) <= (A & 0x0f) ) PSW |= FA;
+ A = res;
+}
+
+/***********************************
+ * 0111 000r
+ * ADDC A,@Rr
+ ***********************************/
+INLINE void addc_rm(int r)
+{
+ UINT8 res = A + RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) ) + (PSW >> 7);
+ if( res <= A ) PSW |= FC;
+ if( (res & 0x0f) <= (A & 0x0f) ) PSW |= FA;
+ A = res;
+}
+
+/***********************************
+ * 0001 0011 7654 3210
+ * ADDC A,#n
+ ***********************************/
+INLINE void addc_i(void)
+{
+ UINT8 res = A + ROP_ARG(PC);
+ PC++;
+ if( res < A ) PSW |= FC;
+ if( (res & 0x0f) < (A & 0x0f) ) PSW |= FA;
+ A = res;
+}
+
+/***********************************
+ * 0101 1rrr
+ * ANL A,Rr
+ ***********************************/
+INLINE void anl_r(int r)
+{
+ A = A & R(r);
+}
+
+/***********************************
+ * 0101 000r
+ * ANL A,@Rr
+ ***********************************/
+INLINE void anl_rm(int r)
+{
+ A = A & RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
+}
+
+/***********************************
+ * 0101 0011 7654 3210
+ * ANL A,#n
+ ***********************************/
+INLINE void anl_i(void)
+{
+ A = A & ROP_ARG(PC);
+ PC++;
+}
+
+/***********************************
+ * 1001 10pp 7654 3210
+ * ANL Pp,#n
+ ***********************************/
+INLINE void anl_p_i(int p)
+{
+ UINT8 val = ROP_ARG(PC);
+ PC++;
+ /* changed to latched port scheme */
+ switch (p)
+ {
+ case 00: break; /* invalid port */
+ case 01: P1 &= val; WP(p, P1); break;
+ case 02: P2 &= val; WP(p, (P2 & P2_HS) ); break;
+ case 03: break; /* invalid port */
+ default: break;
+ }
+}
+
+/***********************************
+ * 1001 11pp 7654 3210
+ * ANLD Pp,A
+ ***********************************/
+INLINE void anld_p_a(int p)
+{
+ /* added proper expanded port setup */
+ WP(2, (P2 & 0xf0) | 0x0c | p); /* AND mode */
+ WP(I8X41_ps, 0); /* activate command strobe */
+ WP(2, (A & 0x0f)); /* Expander to take care of AND function */
+ WP(I8X41_ps, 1); /* release command strobe */
+}
+
+/***********************************
+ * aaa1 0100 7654 3210
+ * CALL addr
+ ***********************************/
+INLINE void call_i(int page)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC++;
+ PUSH_PC_TO_STACK();
+ PC = page | adr;
+}
+
+/***********************************
+ * 0010 0111
+ * CLR A
+ ***********************************/
+INLINE void clr_a(void)
+{
+ A = 0;
+}
+
+/***********************************
+ * 1001 0111
+ * CLR C
+ ***********************************/
+INLINE void clr_c(void)
+{
+ PSW &= ~FC;
+}
+
+/***********************************
+ * 1000 0101
+ * CLR F0
+ ***********************************/
+INLINE void clr_f0(void)
+{
+ PSW &= ~Ff0;
+ STATE &= ~F0;
+}
+
+/***********************************
+ * 1010 0101
+ * CLR F1
+ ***********************************/
+INLINE void clr_f1(void)
+{
+ STATE &= ~F1;
+}
+
+/***********************************
+ * 0011 0111
+ * CPL A
+ ***********************************/
+INLINE void cpl_a(void)
+{
+ A = ~A;
+}
+
+/***********************************
+ * 1010 0111
+ * CPL C
+ ***********************************/
+INLINE void cpl_c(void)
+{
+ PSW ^= FC;
+}
+
+/***********************************
+ * 1001 0101
+ * CPL F0
+ ***********************************/
+INLINE void cpl_f0(void)
+{
+ PSW ^= Ff0;
+ STATE ^= F0;
+}
+
+/***********************************
+ * 1011 0101
+ * CPL F1
+ ***********************************/
+INLINE void cpl_f1(void)
+{
+ STATE ^= F1;
+}
+
+/***********************************
+ * 0101 0111
+ * DA A
+ ***********************************/
+INLINE void da_a(void)
+{
+ UINT8 res = A + ((PSW & FA) || ((A & 0x0f) > 0x09)) ? 0x06 : 0x00;
+ if( (PSW & FC) || ((res & 0xf0) > 0x90) )
+ res += 0x60;
+ if( res < A )
+ PSW |= FC;
+ else
+ PSW &= ~FC;
+ A = res;
+}
+
+/***********************************
+ * 0000 0111
+ * DEC A
+ ***********************************/
+INLINE void dec_a(void)
+{
+ A -= 1;
+}
+
+/***********************************
+ * 1100 1rrr
+ * DEC Rr
+ ***********************************/
+INLINE void dec_r(int r)
+{
+ R(r) -= 1;
+}
+
+/***********************************
+ * 0001 0101
+ * DIS I
+ ***********************************/
+INLINE void dis_i(void)
+{
+ ENABLE &= ~IBFI; /* disable input buffer full interrupt */
+}
+
+/***********************************
+ * 0011 0101
+ * DIS TCNTI
+ ***********************************/
+INLINE void dis_tcnti(void)
+{
+ ENABLE &= ~TCNTI; /* disable timer/counter interrupt */
+}
+
+/***********************************
+ * 0111 1rrr 7654 3210
+ * DJNZ Rr,addr
+ ***********************************/
+INLINE void djnz_r_i(int r)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC++;
+ R(r) -= 1;
+ if( R(r) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 1110 0101
+ * EN DMA
+ ***********************************/
+INLINE void en_dma(void)
+{
+ ENABLE |= DMA; /* enable DMA handshake lines */
+ P2_HS &= 0xbf;
+ WP(0x02, (P2 & P2_HS) );
+}
+
+/***********************************
+ * 1111 0101
+ * EN FLAGS
+ ***********************************/
+INLINE void en_flags(void)
+{
+ if( 0 == (ENABLE & FLAGS) )
+ {
+ /* Configure upper lines on Port 2 for IRQ handshaking (P24 and P25) */
+
+ ENABLE |= FLAGS;
+ if( STATE & OBF ) P2_HS |= 0x10;
+ else P2_HS &= 0xef;
+ if( STATE & IBF ) P2_HS |= 0x20;
+ else P2_HS &= 0xdf;
+ WP(0x02, (P2 & P2_HS) );
+ }
+}
+
+/***********************************
+ * 0000 0101
+ * EN I
+ ***********************************/
+INLINE void en_i(void)
+{
+ if( 0 == (ENABLE & IBFI) )
+ {
+ ENABLE |= IBFI; /* enable input buffer full interrupt */
+ if( STATE & IBF ) /* already got data in the buffer? */
+ set_irq_line(I8X41_INT_IBF, HOLD_LINE);
+ }
+}
+
+/***********************************
+ * 0010 0101
+ * EN TCNTI
+ ***********************************/
+INLINE void en_tcnti(void)
+{
+ ENABLE |= TCNTI; /* enable timer/counter interrupt */
+}
+
+/***********************************
+ * 0010 0010
+ * IN A,DBB
+ ***********************************/
+INLINE void in_a_dbb(void)
+{
+ if( i8x41.irq_callback )
+ (*i8x41.irq_callback)(I8X41_INT_IBF);
+
+ STATE &= ~IBF; /* clear input buffer full flag */
+ if( ENABLE & FLAGS )
+ {
+ P2_HS &= 0xdf;
+ if( STATE & OBF ) P2_HS |= 0x10;
+ else P2_HS &= 0xef;
+ WP(0x02, (P2 & P2_HS) ); /* Clear the DBBI IRQ out on P25 */
+ }
+ A = DBBI;
+}
+
+/***********************************
+ * 0000 10pp
+ * IN A,Pp
+ ***********************************/
+INLINE void in_a_p(int p)
+{
+ /* changed to latched port scheme */
+ switch( p )
+ {
+ case 00: break; /* invalid port */
+ case 01: A = (RP(p) & P1); break;
+ case 02: A = (RP(p) & P2); break;
+ case 03: break; /* invalid port */
+ default: break;
+ }
+}
+
+/***********************************
+ * 0001 0111
+ * INC A
+ ***********************************/
+INLINE void inc_a(void)
+{
+ A += 1;
+}
+
+/***********************************
+ * 0001 1rrr
+ * INC Rr
+ ***********************************/
+INLINE void inc_r(int r)
+{
+ R(r) += 1;
+}
+
+/***********************************
+ * 0001 000r
+ * INC @ Rr
+ ***********************************/
+INLINE void inc_rm(int r)
+{
+ UINT16 addr = M_IRAM + (R(r) & I8X42_intRAM_MASK);
+ WM( addr, RM(addr) + 1 );
+}
+
+/***********************************
+ * bbb1 0010
+ * JBb addr
+ ***********************************/
+INLINE void jbb_i(int bit)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( A & (1 << bit) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 1111 0110
+ * JC addr
+ ***********************************/
+INLINE void jc_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( PSW & FC )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 1011 0110
+ * JF0 addr
+ ***********************************/
+INLINE void jf0_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( STATE & F0 )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 0111 0110
+ * JF1 addr
+ ***********************************/
+INLINE void jf1_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( STATE & F1 )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * aaa0 0100
+ * JMP addr
+ ***********************************/
+INLINE void jmp_i(int page)
+{
+ /* err.. do we have 10 or 11 PC bits?
+ * CALL is said to use 0aa1 (4 pages)
+ * JMP is said to use aaa0 (8 pages)
+ */
+ UINT8 adr = ROP_ARG(PC);
+ PC = page | adr;
+}
+
+/***********************************
+ * 1011 0011
+ * JMP @ A
+ ***********************************/
+INLINE void jmpp_a(void)
+{
+ UINT16 adr = (PC & 0x700) | A;
+ PC = (PC & 0x700) | RM(adr);
+}
+
+/***********************************
+ * 1110 0110
+ * JNC addr
+ ***********************************/
+INLINE void jnc_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( !(PSW & FC) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 1101 0110
+ * JNIBF addr
+ ***********************************/
+INLINE void jnibf_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( 0 == (STATE & IBF) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 0010 0110
+ * JNT0 addr
+ ***********************************/
+INLINE void jnt0_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( 0 == RP(I8X41_t0) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 0100 0110
+ * JNT1 addr
+ ***********************************/
+INLINE void jnt1_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( !(ENABLE & CNT) )
+ {
+ UINT8 level = RP(I8X41_t1);
+ if( level ) CONTROL |= TEST1;
+ else CONTROL &= ~TEST1;
+ }
+ if( !(CONTROL & TEST1) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 1001 0110
+ * JNZ addr
+ ***********************************/
+INLINE void jnz_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( A )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 1000 0110
+ * JOBF addr
+ ***********************************/
+INLINE void jobf_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( STATE & OBF )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 0001 0110
+ * JTF addr
+ ***********************************/
+INLINE void jtf_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( CONTROL & TOVF )
+ PC = (PC & 0x700) | adr;
+ CONTROL &= ~TOVF;
+}
+
+/***********************************
+ * 0011 0110
+ * JT0 addr
+ ***********************************/
+INLINE void jt0_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( RP(I8X41_t0) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 0101 0110
+ * JT1 addr
+ ***********************************/
+INLINE void jt1_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( !(ENABLE & CNT) )
+ {
+ UINT8 level = RP(I8X41_t1);
+ if( level ) CONTROL |= TEST1;
+ else CONTROL &= ~TEST1;
+ }
+ if( (CONTROL & TEST1) )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 1100 0110
+ * JZ addr
+ ***********************************/
+INLINE void jz_i(void)
+{
+ UINT8 adr = ROP_ARG(PC);
+ PC += 1;
+ if( !A )
+ PC = (PC & 0x700) | adr;
+}
+
+/***********************************
+ * 0010 0011
+ * MOV A,#n
+ ***********************************/
+INLINE void mov_a_i(void)
+{
+ A = ROP(PC);
+ PC += 1;
+}
+
+/***********************************
+ * 1100 0111
+ * MOV A,PSW
+ ***********************************/
+INLINE void mov_a_psw(void)
+{
+ A = PSW;
+}
+
+/***********************************
+ * 1111 1rrr
+ * MOV A,Rr
+ ***********************************/
+INLINE void mov_a_r(int r)
+{
+ A = R(r);
+}
+
+/***********************************
+ * 1111 000r
+ * MOV A,Rr
+ ***********************************/
+INLINE void mov_a_rm(int r)
+{
+ A = RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
+}
+
+/***********************************
+ * 0100 0010
+ * MOV A,T
+ ***********************************/
+INLINE void mov_a_t(void)
+{
+ A = TIMER;
+}
+
+/***********************************
+ * 1101 0111
+ * MOV PSW,A
+ ***********************************/
+INLINE void mov_psw_a(void)
+{
+ PSW = A;
+}
+
+/***********************************
+ * 1010 1rrr
+ * MOV Rr,A
+ ***********************************/
+INLINE void mov_r_a(int r)
+{
+ R(r) = A;
+}
+
+/***********************************
+ * 1011 1rrr
+ * MOV Rr,#n
+ ***********************************/
+INLINE void mov_r_i(int r)
+{
+ UINT8 val = ROP_ARG(PC);
+ PC += 1;
+ R(r) = val;
+}
+
+/***********************************
+ * 1010 000r
+ * MOV @Rr,A
+ ***********************************/
+INLINE void mov_rm_a(int r)
+{
+ WM( M_IRAM + (R(r) & I8X42_intRAM_MASK), A );
+}
+
+/***********************************
+ * 1011 000r
+ * MOV @Rr,#n
+ ***********************************/
+INLINE void mov_rm_i(int r)
+{
+ UINT8 val = ROP_ARG(PC);
+ PC += 1;
+ WM( M_IRAM + (R(r) & I8X42_intRAM_MASK), val );
+}
+
+/***********************************
+ * 1001 0000
+ * MOV STS,A
+ ***********************************/
+INLINE void mov_sts_a(void)
+{
+ STATE = (STATE & 0x0f) | (A & 0xf0);
+}
+
+/***********************************
+ * 0110 0010
+ * MOV T,A
+ ***********************************/
+INLINE void mov_t_a(void)
+{
+ TIMER = A;
+}
+
+/***********************************
+ * 0000 11pp
+ * MOVD A,Pp
+ ***********************************/
+INLINE void movd_a_p(int p)
+{
+ /* added proper expanded port setup */
+ WP(2, (P2 & 0xf0) | 0x00 | p); /* READ mode */
+ WP(I8X41_ps, 0); /* activate command strobe */
+ A = RP(2) & 0xf;
+ WP(I8X41_ps, 1); /* release command strobe */
+}
+
+/***********************************
+ * 0011 11pp
+ * MOVD Pp,A
+ ***********************************/
+INLINE void movd_p_a(int p)
+{
+ /* added proper expanded port setup */
+ WP(2, (P2 & 0xf0) | 0x04 | p); /* WRITE mode */
+ WP(I8X41_ps, 0); /* activate command strobe */
+ WP(2, A & 0x0f);
+ WP(I8X41_ps, 1); /* release command strobe */
+}
+
+/***********************************
+ * 1010 0011
+ * MOVP A,@A
+ ***********************************/
+INLINE void movp_a_am(void)
+{
+ UINT16 addr = (PC & 0x700) | A;
+ A = RM(addr);
+}
+
+/***********************************
+ * 1110 0011
+ * MOVP3 A,@A
+ ***********************************/
+INLINE void movp3_a_am(void)
+{
+ UINT16 addr = 0x300 | A;
+ A = RM(addr);
+}
+
+/***********************************
+ * 0000 0000
+ * NOP
+ ***********************************/
+INLINE void nop(void)
+{
+}
+
+/***********************************
+ * 0100 1rrr
+ * ORL A,Rr
+ ***********************************/
+INLINE void orl_r(int r)
+{
+ A = A | R(r);
+}
+
+/***********************************
+ * 0100 000r
+ * ORL A,@Rr
+ ***********************************/
+INLINE void orl_rm(int r)
+{
+ A = A | RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
+}
+
+/***********************************
+ * 0100 0011 7654 3210
+ * ORL A,#n
+ ***********************************/
+INLINE void orl_i(void)
+{
+ UINT8 val = ROP_ARG(PC);
+ PC++;
+ A = A | val;
+}
+
+/***********************************
+ * 1000 10pp 7654 3210
+ * ORL Pp,#n
+ ***********************************/
+INLINE void orl_p_i(int p)
+{
+ UINT8 val = ROP_ARG(PC);
+ PC++;
+ /* changed to latched port scheme */
+ switch (p)
+ {
+ case 00: break; /* invalid port */
+ case 01: P1 |= val; WP(p, P1); break;
+ case 02: P2 |= val; WP(p, P2); break;
+ case 03: break; /* invalid port */
+ default: break;
+ }
+}
+
+/***********************************
+ * 1000 11pp 7654 3210
+ * ORLD Pp,A
+ ***********************************/
+INLINE void orld_p_a(int p)
+{
+ /* added proper expanded port setup */
+ WP(2, (P2 & 0xf0) | 0x08 | p); /* OR mode */
+ WP(I8X41_ps, 0); /* activate command strobe */
+ WP(2, A & 0x0f); /* Expander to take care of OR function */
+ WP(I8X41_ps, 1); /* release command strobe */
+}
+
+/***********************************
+ * 0000 0010
+ * OUT DBB,A
+ ***********************************/
+INLINE void out_dbb_a(void)
+{
+ DBBO = A; /* DBB output buffer */
+ STATE |= OBF; /* assert the output buffer full flag */
+ if( ENABLE & FLAGS )
+ {
+ P2_HS |= 0x10;
+ if( STATE & IBF ) P2_HS |= 0x20;
+ else P2_HS &= 0xdf;
+ WP(0x02, (P2 & P2_HS) ); /* Assert the DBBO IRQ out on P24 */
+ }
+}
+
+/***********************************
+ * 0011 10pp
+ * OUT Pp,A
+ ***********************************/
+INLINE void out_p_a(int p)
+{
+ /* changed to latched port scheme */
+ switch (p)
+ {
+ case 00: break; /* invalid port */
+ case 01: WP(p, A); P1 = A; break;
+ case 02: WP(p, A); P2 = A; break;
+ case 03: break; /* invalid port */
+ default: break;
+ }
+}
+
+/***********************************
+ * 1000 0011
+ * RET
+ ***********************************/
+INLINE void ret(void)
+{
+ UINT8 msb;
+ PSW = (PSW & ~SP) | ((PSW - 1) & SP);
+ msb = RM(M_STACK + (PSW&SP) * 2 + 1);
+ PC = RM(M_STACK + (PSW&SP) * 2 + 0);
+ PC |= (msb << 8) & 0x700;
+}
+
+/***********************************
+ * 1001 0011
+ * RETR
+ ***********************************/
+INLINE void retr(void)
+{
+ UINT8 msb;
+ PSW = (PSW & ~SP) | ((PSW - 1) & SP);
+ msb = RM(M_STACK + (PSW&SP) * 2 + 1);
+ PC = RM(M_STACK + (PSW&SP) * 2 + 0);
+ PC |= (msb << 8) & 0x700;
+ PSW = (PSW & 0x0f) | (msb & 0xf0);
+ CONTROL &= ~IBFI_EXEC;
+ CONTROL &= ~TIRQ_EXEC;
+}
+
+/***********************************
+ * 1110 0111
+ * RL A
+ ***********************************/
+INLINE void rl_a(void)
+{
+ A = (A << 1) | (A >> 7);
+}
+
+/***********************************
+ * 1111 0111
+ * RLC A
+ ***********************************/
+INLINE void rlc_a(void)
+{
+ UINT8 c = PSW >> 7;
+ PSW = (PSW & ~FC) | (A >> 7);
+ A = (A << 1) | c;
+}
+
+/***********************************
+ * 0111 0111
+ * RR A
+ ***********************************/
+INLINE void rr_a(void)
+{
+ A = (A >> 1) | (A << 7);
+}
+
+/***********************************
+ * 0110 0111
+ * RRC A
+ ***********************************/
+INLINE void rrc_a(void)
+{
+ UINT8 c = PSW & 0x80;
+ PSW = (PSW & ~FC) | (A << 7);
+ A = (A >> 1) | c;
+}
+
+/***********************************
+ * 1100 0101
+ * SEL RB0
+ ***********************************/
+INLINE void sel_rb0(void)
+{
+ PSW &= ~BS;
+}
+
+/***********************************
+ * 1101 0101
+ * SEL RB1
+ ***********************************/
+INLINE void sel_rb1(void)
+{
+ PSW |= BS;
+}
+
+/***********************************
+ * 0110 0101
+ * STOP TCNT
+ ***********************************/
+INLINE void stop_tcnt(void)
+{
+ ENABLE &= ~(T|CNT);
+}
+
+/***********************************
+ * 0100 0101
+ * STRT CNT
+ ***********************************/
+INLINE void strt_cnt(void)
+{
+ ENABLE |= CNT;
+ ENABLE &= ~T;
+}
+
+/***********************************
+ * 0101 0101
+ * STRT T
+ ***********************************/
+INLINE void strt_t(void)
+{
+ ENABLE |= T;
+ ENABLE &= ~CNT;
+}
+
+/***********************************
+ * 0100 0111
+ * SWAP A
+ ***********************************/
+INLINE void swap_a(void)
+{
+ A = (A << 4) | (A >> 4);
+}
+
+/***********************************
+ * 0010 1rrr
+ * XCH A,Rr
+ ***********************************/
+INLINE void xch_a_r(int r)
+{
+ UINT8 tmp = R(r);
+ R(r) = A;
+ A = tmp;
+}
+
+/***********************************
+ * 0010 000r
+ * XCH A,@Rr
+ ***********************************/
+INLINE void xch_a_rm(int r)
+{
+ UINT16 addr = M_IRAM + (R(r) & I8X42_intRAM_MASK);
+ UINT8 tmp = RM(addr);
+ WM( addr, A );
+ A = tmp;
+}
+
+/***********************************
+ * 0011 000r
+ * XCHD A,@Rr
+ ***********************************/
+INLINE void xchd_a_rm(int r)
+{
+ UINT16 addr = M_IRAM + (R(r) & I8X42_intRAM_MASK);
+ UINT8 tmp = RM(addr);
+ WM( addr, (tmp & 0xf0) | (A & 0x0f) );
+ A = (A & 0xf0) | (tmp & 0x0f);
+}
+
+/***********************************
+ * 1101 1rrr
+ * XRL A,Rr
+ ***********************************/
+INLINE void xrl_r(int r)
+{
+ A = A ^ R(r);
+}
+
+/***********************************
+ * 1101 000r
+ * XRL A,@Rr
+ ***********************************/
+INLINE void xrl_rm(int r)
+{
+ A = A ^ RM( M_IRAM + (R(r) & I8X42_intRAM_MASK) );
+}
+
+/***********************************
+ * 1101 0011 7654 3210
+ * XRL A,#n
+ ***********************************/
+INLINE void xrl_i(void)
+{
+ UINT8 val = ROP_ARG(PC);
+ PC++;
+ A = A ^ val;
+}
+
+
+/***********************************************************************
+ * Cycle Timings
+ ***********************************************************************/
+
+static UINT8 i8x41_cycles[] = {
+ 1,1,1,2,2,1,1,1,2,2,2,2,2,2,2,2,
+ 1,1,2,2,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,1,2,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,2,1,2,1,2,1,2,2,2,2,2,2,2,2,
+ 1,1,1,2,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,2,2,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,1,2,2,1,2,1,2,2,2,2,2,2,2,2,
+ 1,1,2,2,1,1,2,1,2,2,2,2,2,2,2,2,
+ 1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,1,2,1,2,2,2,2,2,2,2,2,
+ 1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,2,1,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,1,2,2,1,2,1,1,1,1,1,1,1,1,1,
+ 1,1,2,1,2,1,2,1,2,2,2,2,2,2,2,2
+};
+
+
+/****************************************************************************
+ * Inits CPU emulation
+ ****************************************************************************/
+
+static void i8x41_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ i8x41.irq_callback = irqcallback;
+
+ state_save_register_item("i8x41", index, i8x41.ppc);
+ state_save_register_item("i8x41", index, i8x41.pc);
+ state_save_register_item("i8x41", index, i8x41.timer);
+ state_save_register_item("i8x41", index, i8x41.prescaler);
+ state_save_register_item("i8x41", index, i8x41.subtype);
+ state_save_register_item("i8x41", index, i8x41.a);
+ state_save_register_item("i8x41", index, i8x41.psw);
+ state_save_register_item("i8x41", index, i8x41.state);
+ state_save_register_item("i8x41", index, i8x41.enable);
+ state_save_register_item("i8x41", index, i8x41.control);
+ state_save_register_item("i8x41", index, i8x41.dbbi);
+ state_save_register_item("i8x41", index, i8x41.dbbo);
+ state_save_register_item("i8x41", index, i8x41.p1);
+ state_save_register_item("i8x41", index, i8x41.p2);
+ state_save_register_item("i8x41", index, i8x41.p2_hs);
+}
+
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+
+static void i8x41_reset(void)
+{
+ int (*save_irqcallback)(int) = i8x41.irq_callback;
+ memset(&i8x41, 0, sizeof(I8X41));
+ i8x41.irq_callback = save_irqcallback;
+
+ /* default to 8041 behaviour for DBBI/DBBO and extended commands */
+ i8x41.subtype = 8041;
+ /* ugly hack.. excuse my lazyness */
+ i8x41.ram = memory_region(REGION_CPU1 + cpu_getactivecpu());
+ ENABLE = IBFI | TCNTI;
+ DBBI = 0xff;
+ DBBO = 0xff;
+ /* Set Ports 1 and 2 to input mode */
+ P1 = 0xff;
+ P2 = 0xff;
+ P2_HS= 0xff;
+}
+
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+
+static void i8x41_exit(void)
+{
+ /* nothing to do */
+}
+
+
+/****************************************************************************
+ * Execute cycles - returns number of cycles actually run
+ ****************************************************************************/
+
+static int i8x41_execute(int cycles)
+{
+ int inst_cycles, T1_level;
+
+ i8x41_ICount = cycles;
+
+ do
+ {
+ UINT8 op = cpu_readop(PC);
+
+ PPC = PC;
+
+ CALL_MAME_DEBUG;
+
+ PC += 1;
+ i8x41_ICount -= i8x41_cycles[op];
+
+ switch( op )
+ {
+ /* opcode cycles bitmask */
+ case 0x00: /* 1: 0000 0000 */
+ nop();
+ break;
+ case 0x01: /* 1: 0000 0001 */
+ illegal();
+ break;
+ case 0x02: /* 1: 0000 0010 */
+ out_dbb_a();
+ break;
+ case 0x03: /* 2: 0000 0011 */
+ add_i();
+ break;
+ case 0x04: /* 2: aaa0 0100 */
+ jmp_i(0x000);
+ break;
+ case 0x05: /* 1: 0000 0101 */
+ en_i();
+ break;
+ case 0x06: /* 1: 0000 0110 */
+ illegal();
+ break;
+ case 0x07: /* 1: 0000 0111 */
+ dec_a();
+ break;
+ case 0x08: /* 2: 0000 10pp */
+ case 0x09: /* 2: 0000 10pp */
+ case 0x0a: /* 2: 0000 10pp */
+ case 0x0b: /* 2: 0000 10pp */
+ in_a_p(op & 3);
+ break;
+ case 0x0c: /* 2: 0000 11pp */
+ case 0x0d: /* 2: 0000 11pp */
+ case 0x0e: /* 2: 0000 11pp */
+ case 0x0f: /* 2: 0000 11pp */
+ movd_a_p(op & 3);
+ break;
+ case 0x10: /* 1: 0001 000r */
+ inc_rm(0);
+ break;
+ case 0x11: /* 1: 0001 000r */
+ inc_rm(1);
+ break;
+ case 0x12: /* 2: bbb1 0010 */
+ jbb_i(0);
+ break;
+ case 0x13: /* 2: 0001 0011 */
+ addc_i();
+ break;
+ case 0x14: /* 2: aaa1 0100 */
+ call_i(0x000);
+ break;
+ case 0x15: /* 1: 0001 0101 */
+ dis_i();
+ break;
+ case 0x16: /* 2: 0001 0110 */
+ jtf_i();
+ break;
+ case 0x17: /* 1: 0001 0111 */
+ inc_a();
+ break;
+ case 0x18: /* 1: 0001 1rrr */
+ case 0x19: /* 1: 0001 1rrr */
+ case 0x1a: /* 1: 0001 1rrr */
+ case 0x1b: /* 1: 0001 1rrr */
+ case 0x1c: /* 1: 0001 1rrr */
+ case 0x1d: /* 1: 0001 1rrr */
+ case 0x1e: /* 1: 0001 1rrr */
+ case 0x1f: /* 1: 0001 1rrr */
+ inc_r(op & 7);
+ break;
+ case 0x20: /* 1: 0010 000r */
+ xch_a_rm(0);
+ break;
+ case 0x21: /* 1: 0010 000r */
+ xch_a_rm(1);
+ break;
+ case 0x22: /* 1: 0010 0010 */
+ in_a_dbb();
+ break;
+ case 0x23: /* 2: 0010 0011 */
+ mov_a_i();
+ break;
+ case 0x24: /* 2: aaa0 0100 */
+ jmp_i(0x100);
+ break;
+ case 0x25: /* 1: 0010 0101 */
+ en_tcnti();
+ break;
+ case 0x26: /* 2: 0010 0110 */
+ jnt0_i();
+ break;
+ case 0x27: /* 1: 0010 0111 */
+ clr_a();
+ break;
+ case 0x28: /* 1: 0010 1rrr */
+ case 0x29: /* 1: 0010 1rrr */
+ case 0x2a: /* 1: 0010 1rrr */
+ case 0x2b: /* 1: 0010 1rrr */
+ case 0x2c: /* 1: 0010 1rrr */
+ case 0x2d: /* 1: 0010 1rrr */
+ case 0x2e: /* 1: 0010 1rrr */
+ case 0x2f: /* 1: 0010 1rrr */
+ xch_a_r(op & 7);
+ break;
+ case 0x30: /* 1: 0011 000r */
+ xchd_a_rm(0);
+ break;
+ case 0x31: /* 1: 0011 000r */
+ xchd_a_rm(1);
+ break;
+ case 0x32: /* 2: bbb1 0010 */
+ jbb_i(1);
+ break;
+ case 0x33: /* 1: 0011 0101 */
+ illegal();
+ break;
+ case 0x34: /* 2: aaa1 0100 */
+ call_i(0x100);
+ break;
+ case 0x35: /* 1: 0000 0101 */
+ dis_tcnti();
+ break;
+ case 0x36: /* 2: 0011 0110 */
+ jt0_i();
+ break;
+ case 0x37: /* 1: 0011 0111 */
+ cpl_a();
+ break;
+ case 0x38: /* 2: 0011 10pp */
+ case 0x39: /* 2: 0011 10pp */
+ case 0x3a: /* 2: 0011 10pp */
+ case 0x3b: /* 2: 0011 10pp */
+ out_p_a(op & 3);
+ break;
+ case 0x3c: /* 2: 0011 11pp */
+ case 0x3d: /* 2: 0011 11pp */
+ case 0x3e: /* 2: 0011 11pp */
+ case 0x3f: /* 2: 0011 11pp */
+ movd_p_a(op & 3);
+ break;
+ case 0x40: /* 1: 0100 000r */
+ orl_rm(0);
+ break;
+ case 0x41: /* 1: 0100 000r */
+ orl_rm(1);
+ break;
+ case 0x42: /* 1: 0100 0010 */
+ mov_a_t();
+ break;
+ case 0x43: /* 2: 0100 0011 */
+ orl_i();
+ break;
+ case 0x44: /* 2: aaa0 0100 */
+ jmp_i(0x200);
+ break;
+ case 0x45: /* 1: 0100 0101 */
+ strt_cnt();
+ break;
+ case 0x46: /* 2: 0100 0110 */
+ jnt1_i();
+ break;
+ case 0x47: /* 1: 0100 0111 */
+ swap_a();
+ break;
+ case 0x48: /* 1: 0100 1rrr */
+ case 0x49: /* 1: 0100 1rrr */
+ case 0x4a: /* 1: 0100 1rrr */
+ case 0x4b: /* 1: 0100 1rrr */
+ case 0x4c: /* 1: 0100 1rrr */
+ case 0x4d: /* 1: 0100 1rrr */
+ case 0x4e: /* 1: 0100 1rrr */
+ case 0x4f: /* 1: 0100 1rrr */
+ orl_r(op & 7);
+ break;
+ case 0x50: /* 1: 0101 000r */
+ anl_rm(0);
+ break;
+ case 0x51: /* 1: 0101 000r */
+ anl_rm(1);
+ break;
+ case 0x52: /* 2: bbb1 0010 */
+ jbb_i(2);
+ break;
+ case 0x53: /* 2: 0101 0011 */
+ anl_i();
+ break;
+ case 0x54: /* 2: aaa1 0100 */
+ call_i(0x200);
+ break;
+ case 0x55: /* 1: 0101 0101 */
+ strt_t();
+ break;
+ case 0x56: /* 2: 0101 0110 */
+ jt1_i();
+ break;
+ case 0x57: /* 1: 0101 0111 */
+ da_a();
+ break;
+ case 0x58: /* 1: 0101 1rrr */
+ case 0x59: /* 1: 0101 1rrr */
+ case 0x5a: /* 1: 0101 1rrr */
+ case 0x5b: /* 1: 0101 1rrr */
+ case 0x5c: /* 1: 0101 1rrr */
+ case 0x5d: /* 1: 0101 1rrr */
+ case 0x5e: /* 1: 0101 1rrr */
+ case 0x5f: /* 1: 0101 1rrr */
+ anl_r(op & 7);
+ break;
+ case 0x60: /* 1: 0110 000r */
+ add_rm(0);
+ break;
+ case 0x61: /* 1: 0110 000r */
+ add_rm(1);
+ break;
+ case 0x62: /* 1: 0110 0010 */
+ mov_t_a();
+ break;
+ case 0x63: /* 1: 0110 0011 */
+ illegal();
+ break;
+ case 0x64: /* 2: aaa0 0100 */
+ jmp_i(0x300);
+ break;
+ case 0x65: /* 1: 0110 0101 */
+ stop_tcnt();
+ break;
+ case 0x66: /* 1: 0110 0110 */
+ illegal();
+ break;
+ case 0x67: /* 1: 0110 0111 */
+ rrc_a();
+ break;
+ case 0x68: /* 1: 0110 1rrr */
+ case 0x69: /* 1: 0110 1rrr */
+ case 0x6a: /* 1: 0110 1rrr */
+ case 0x6b: /* 1: 0110 1rrr */
+ case 0x6c: /* 1: 0110 1rrr */
+ case 0x6d: /* 1: 0110 1rrr */
+ case 0x6e: /* 1: 0110 1rrr */
+ case 0x6f: /* 1: 0110 1rrr */
+ add_r(op & 7);
+ break;
+ case 0x70: /* 1: 0111 000r */
+ addc_rm(0);
+ break;
+ case 0x71: /* 1: 0111 000r */
+ addc_rm(1);
+ break;
+ case 0x72: /* 2: bbb1 0010 */
+ jbb_i(3);
+ break;
+ case 0x73: /* 1: 0111 0011 */
+ illegal();
+ break;
+ case 0x74: /* 2: aaa1 0100 */
+ call_i(0x300);
+ break;
+ case 0x75: /* 1: 0111 0101 */
+ illegal();
+ break;
+ case 0x76: /* 2: 0111 0110 */
+ jf1_i();
+ break;
+ case 0x77: /* 1: 0111 0111 */
+ rr_a();
+ break;
+ case 0x78: /* 1: 0111 1rrr */
+ case 0x79: /* 1: 0111 1rrr */
+ case 0x7a: /* 1: 0111 1rrr */
+ case 0x7b: /* 1: 0111 1rrr */
+ case 0x7c: /* 1: 0111 1rrr */
+ case 0x7d: /* 1: 0111 1rrr */
+ case 0x7e: /* 1: 0111 1rrr */
+ case 0x7f: /* 1: 0111 1rrr */
+ addc_r(op & 7);
+ break;
+ case 0x80: /* 1: 1000 0000 */
+ illegal();
+ break;
+ case 0x81: /* 1: 1000 0001 */
+ illegal();
+ break;
+ case 0x82: /* 1: 1000 0010 */
+ illegal();
+ break;
+ case 0x83: /* 2: 1000 0011 */
+ ret();
+ break;
+ case 0x84: /* 2: aaa0 0100 */
+ jmp_i(0x400);
+ break;
+ case 0x85: /* 1: 1000 0101 */
+ clr_f0();
+ break;
+ case 0x86: /* 2: 1000 0110 */
+ jobf_i();
+ break;
+ case 0x87: /* 1: 1000 0111 */
+ illegal();
+ break;
+ case 0x88: /* 2: 1000 10pp */
+ case 0x89: /* 2: 1000 10pp */
+ case 0x8a: /* 2: 1000 10pp */
+ case 0x8b: /* 2: 1000 10pp */
+ orl_p_i(op & 3);
+ break;
+ case 0x8c: /* 2: 1000 11pp */
+ case 0x8d: /* 2: 1000 11pp */
+ case 0x8e: /* 2: 1000 11pp */
+ case 0x8f: /* 2: 1000 11pp */
+ orld_p_a(op & 7);
+ break;
+ case 0x90: /* 1: 1001 0000 */
+ mov_sts_a();
+ break;
+ case 0x91: /* 1: 1001 0001 */
+ illegal();
+ break;
+ case 0x92: /* 2: bbb1 0010 */
+ jbb_i(4);
+ break;
+ case 0x93: /* 2: 1001 0011 */
+ retr();
+ break;
+ case 0x94: /* 1: aaa1 0100 */
+ call_i(0x400);
+ break;
+ case 0x95: /* 1: 1001 0101 */
+ cpl_f0();
+ break;
+ case 0x96: /* 2: 1001 0110 */
+ jnz_i();
+ break;
+ case 0x97: /* 1: 1001 0111 */
+ clr_c();
+ break;
+ case 0x98: /* 2: 1001 10pp , illegal port */
+ case 0x99: /* 2: 1001 10pp */
+ case 0x9a: /* 2: 1001 10pp */
+ case 0x9b: /* 2: 1001 10pp , illegal port */
+ anl_p_i(op & 3);
+ break;
+ case 0x9c: /* 2: 1001 11pp */
+ case 0x9d: /* 2: 1001 11pp */
+ case 0x9e: /* 2: 1001 11pp */
+ case 0x9f: /* 2: 1001 11pp */
+ anld_p_a(op & 7);
+ break;
+ case 0xa0: /* 1: 1010 000r */
+ mov_rm_a(0);
+ break;
+ case 0xa1: /* 1: 1010 000r */
+ mov_rm_a(1);
+ break;
+ case 0xa2: /* 1: 1010 0010 */
+ illegal();
+ break;
+ case 0xa3: /* 2: 1010 0011 */
+ movp_a_am();
+ break;
+ case 0xa4: /* 2: aaa0 0100 */
+ jmp_i(0x500);
+ break;
+ case 0xa5: /* 1: 1010 0101 */
+ clr_f1();
+ break;
+ case 0xa6: /* 1: 1010 0110 */
+ illegal();
+ break;
+ case 0xa7: /* 1: 1010 0111 */
+ cpl_c();
+ break;
+ case 0xa8: /* 1: 1010 1rrr */
+ case 0xa9: /* 1: 1010 1rrr */
+ case 0xaa: /* 1: 1010 1rrr */
+ case 0xab: /* 1: 1010 1rrr */
+ case 0xac: /* 1: 1010 1rrr */
+ case 0xad: /* 1: 1010 1rrr */
+ case 0xae: /* 1: 1010 1rrr */
+ case 0xaf: /* 1: 1010 1rrr */
+ mov_r_a(op & 7);
+ break;
+ case 0xb0: /* 2: 1011 000r */
+ mov_rm_i(0);
+ break;
+ case 0xb1: /* 2: 1011 000r */
+ mov_rm_i(1);
+ break;
+ case 0xb2: /* 2: bbb1 0010 */
+ jbb_i(5);
+ break;
+ case 0xb3: /* 2: 1011 0011 */
+ jmpp_a();
+ break;
+ case 0xb4: /* 2: aaa1 0100 */
+ call_i(0x500);
+ break;
+ case 0xb5: /* 1: 1011 0101 */
+ cpl_f1();
+ break;
+ case 0xb6: /* 2: 1011 0110 */
+ jf0_i();
+ break;
+ case 0xb7: /* 1: 1011 0111 */
+ illegal();
+ break;
+ case 0xb8: /* 2: 1011 1rrr */
+ case 0xb9: /* 2: 1011 1rrr */
+ case 0xba: /* 2: 1011 1rrr */
+ case 0xbb: /* 2: 1011 1rrr */
+ case 0xbc: /* 2: 1011 1rrr */
+ case 0xbd: /* 2: 1011 1rrr */
+ case 0xbe: /* 2: 1011 1rrr */
+ case 0xbf: /* 2: 1011 1rrr */
+ mov_r_i(op & 7);
+ break;
+ case 0xc0: /* 1: 1100 0000 */
+ illegal();
+ break;
+ case 0xc1: /* 1: 1100 0001 */
+ illegal();
+ break;
+ case 0xc2: /* 1: 1100 0010 */
+ illegal();
+ break;
+ case 0xc3: /* 1: 1100 0011 */
+ illegal();
+ break;
+ case 0xc4: /* 2: aaa0 0100 */
+ jmp_i(0x600);
+ break;
+ case 0xc5: /* 1: 1100 0101 */
+ sel_rb0();
+ break;
+ case 0xc6: /* 2: 1100 0110 */
+ jz_i();
+ break;
+ case 0xc7: /* 1: 1100 0111 */
+ mov_a_psw();
+ break;
+ case 0xc8: /* 1: 1100 1rrr */
+ case 0xc9: /* 1: 1100 1rrr */
+ case 0xca: /* 1: 1100 1rrr */
+ case 0xcb: /* 1: 1100 1rrr */
+ case 0xcc: /* 1: 1100 1rrr */
+ case 0xcd: /* 1: 1100 1rrr */
+ case 0xcf: /* 1: 1100 1rrr */
+ dec_r(op & 7);
+ break;
+ case 0xd0: /* 1: 1101 000r */
+ xrl_rm(0);
+ break;
+ case 0xd1: /* 1: 1101 000r */
+ xrl_rm(1);
+ break;
+ case 0xd2: /* 2: bbb1 0010 */
+ jbb_i(6);
+ break;
+ case 0xd3: /* 1: 1101 0011 */
+ xrl_i();
+ break;
+ case 0xd4: /* 2: aaa1 0100 */
+ call_i(0x600);
+ break;
+ case 0xd5: /* 1: 1101 0101 */
+ sel_rb1();
+ break;
+ case 0xd6: /* 2: 1101 0110 */
+ jnibf_i();
+ break;
+ case 0xd7: /* 1: 1101 0111 */
+ mov_psw_a();
+ break;
+ case 0xd8: /* 1: 1101 1rrr */
+ case 0xd9: /* 1: 1101 1rrr */
+ case 0xda: /* 1: 1101 1rrr */
+ case 0xdb: /* 1: 1101 1rrr */
+ case 0xdc: /* 1: 1101 1rrr */
+ case 0xdd: /* 1: 1101 1rrr */
+ case 0xde: /* 1: 1101 1rrr */
+ case 0xdf: /* 1: 1101 1rrr */
+ xrl_r(op & 7);
+ break;
+ case 0xe0: /* 1: 1110 0000 */
+ illegal();
+ break;
+ case 0xe1: /* 1: 1110 0001 */
+ illegal();
+ break;
+ case 0xe2: /* 1: 1110 0010 */
+ illegal();
+ break;
+ case 0xe3: /* 2: 1110 0011 */
+ movp3_a_am();
+ break;
+ case 0xe4: /* 2: aaa0 0100 */
+ jmp_i(0x700);
+ break;
+ case 0xe5: /* 1: 1110 0101 */
+ en_dma();
+ break;
+ case 0xe6: /* 2: 1110 0110 */
+ jnc_i();
+ break;
+ case 0xe7: /* 1: 1110 0111 */
+ rl_a();
+ break;
+ case 0xe8: /* 2: 1110 1rrr */
+ case 0xe9: /* 2: 1110 1rrr */
+ case 0xea: /* 2: 1110 1rrr */
+ case 0xeb: /* 2: 1110 1rrr */
+ case 0xec: /* 2: 1110 1rrr */
+ case 0xed: /* 2: 1110 1rrr */
+ case 0xee: /* 2: 1110 1rrr */
+ case 0xef: /* 2: 1110 1rrr */
+ djnz_r_i(op & 7);
+ break;
+ case 0xf0: /* 1: 1111 000r */
+ mov_a_rm(0);
+ break;
+ case 0xf1: /* 1: 1111 000r */
+ mov_a_rm(1);
+ break;
+ case 0xf2: /* 2: bbb1 0010 */
+ jbb_i(7);
+ break;
+ case 0xf3: /* 1: 1111 0011 */
+ illegal();
+ break;
+ case 0xf4: /* 2: aaa1 0100 */
+ call_i(0x700);
+ break;
+ case 0xf5: /* 1: 1111 0101 */
+ en_flags();
+ break;
+ case 0xf6: /* 2: 1111 0110 */
+ jc_i();
+ break;
+ case 0xf7: /* 1: 1111 0111 */
+ rlc_a();
+ break;
+ case 0xf8: /* 1: 1111 1rrr */
+ case 0xf9: /* 1: 1111 1rrr */
+ case 0xfa: /* 1: 1111 1rrr */
+ case 0xfb: /* 1: 1111 1rrr */
+ case 0xfc: /* 1: 1111 1rrr */
+ case 0xfd: /* 1: 1111 1rrr */
+ case 0xfe: /* 1: 1111 1rrr */
+ case 0xff: /* 1: 1111 1rrr */
+ mov_a_r(op & 7);
+ break;
+ }
+
+
+ if( ENABLE & CNT )
+ {
+ inst_cycles = i8x41_cycles[op];
+ for ( ; inst_cycles > 0; inst_cycles-- )
+ {
+ T1_level = RP(I8X41_t1);
+ if( (CONTROL & TEST1) && (T1_level == 0) ) /* Negative Edge */
+ {
+ TIMER++;
+ if (TIMER == 0)
+ {
+ CONTROL |= TOVF;
+ if( ENABLE & TCNTI )
+ CONTROL |= TIRQ_PEND;
+ }
+ }
+ if( T1_level ) CONTROL |= TEST1;
+ else CONTROL &= ~TEST1;
+ }
+ }
+
+ if( ENABLE & T )
+ {
+ PRESCALER += i8x41_cycles[op];
+ /**** timer is prescaled by 32 ****/
+ if( PRESCALER >= 32 )
+ {
+ PRESCALER -= 32;
+ TIMER++;
+ if( TIMER == 0 )
+ {
+ CONTROL |= TOVF;
+ if( ENABLE & TCNTI )
+ CONTROL |= TIRQ_PEND;
+ }
+ }
+ }
+
+ if( CONTROL & IRQ_PEND ) /* Are any Interrupts Pending ? */
+ {
+ if( 0 == (CONTROL & IRQ_EXEC) ) /* Are any Interrupts being serviced ? */
+ {
+ if( (ENABLE & IBFI) && (CONTROL & IBFI_PEND) )
+ {
+ PUSH_PC_TO_STACK();
+ PC = V_IBF;
+ CONTROL &= ~IBFI_PEND;
+ CONTROL |= IBFI_EXEC;
+ i8x41_ICount -= 2;
+ }
+ }
+ if( 0 == (CONTROL & IRQ_EXEC) ) /* Are any Interrupts being serviced ? */
+ {
+ if( (ENABLE & TCNTI) && (CONTROL & TIRQ_PEND) )
+ {
+ PUSH_PC_TO_STACK();
+ PC = V_TIMER;
+ CONTROL &= ~TIRQ_PEND;
+ CONTROL |= TIRQ_EXEC;
+ if( ENABLE & T ) PRESCALER += 2; /* 2 states */
+ i8x41_ICount -= 2; /* 2 states to take interrupt */
+ }
+ }
+ }
+
+
+ } while( i8x41_ICount > 0 );
+
+ return cycles - i8x41_ICount;
+}
+
+
+/****************************************************************************
+ * Get all registers in given buffer
+ ****************************************************************************/
+
+static void i8x41_get_context(void *dst)
+{
+ if( dst )
+ memcpy(dst, &i8x41, sizeof(I8X41));
+}
+
+
+/****************************************************************************
+ * Set all registers to given values
+ ****************************************************************************/
+
+static void i8x41_set_context(void *src)
+{
+ if( src )
+ memcpy(&i8x41, src, sizeof(I8X41));
+}
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+
+static void set_irq_line(int irqline, int state)
+{
+ switch( irqline )
+ {
+ case I8X41_INT_IBF:
+ if (state != CLEAR_LINE)
+ {
+ STATE |= IBF;
+ if (ENABLE & IBFI)
+ {
+ CONTROL |= IBFI_PEND;
+ }
+ }
+ else
+ {
+ STATE &= ~IBF;
+ }
+ break;
+
+ case I8X41_INT_TEST1:
+ if( state != CLEAR_LINE )
+ {
+ CONTROL |= TEST1;
+ }
+ else
+ {
+ /* high to low transition? */
+ if( CONTROL & TEST1 )
+ {
+ /* counting enabled? */
+ if( ENABLE & CNT )
+ {
+ TIMER++;
+ if( TIMER == 0 )
+ {
+ CONTROL |= TOVF;
+ CONTROL |= TIRQ_PEND;
+ }
+ }
+ }
+ CONTROL &= ~TEST1;
+ }
+ break;
+ }
+}
+
+
+/**************************************************************************
+ * Register accesses catching uninitialized i8x41.ram pointer
+ **************************************************************************/
+#define GETR(n) (NULL == i8x41.ram ? 0 : \
+ i8x41.ram[((PSW & BS) ? M_BANK1:M_BANK0)+(n)])
+
+#define SETR(n,v) do { \
+ if (NULL != i8x41.ram) { \
+ i8x41.ram[((PSW & BS) ? M_BANK1:M_BANK0)+(n)] = (v); \
+ } \
+} while (0)
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static void i8x41_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + I8X41_INT_IBF: set_irq_line(I8X41_INT_IBF, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + I8X41_INT_TEST1: set_irq_line(I8X41_INT_TEST1, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I8X41_PC: PC = info->i & 0x7ff; break;
+
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + I8X41_SP: PSW = (PSW & ~SP) | (info->i & SP); break;
+
+ case CPUINFO_INT_REGISTER + I8X41_PSW: PSW = info->i; break;
+ case CPUINFO_INT_REGISTER + I8X41_A: A = info->i; break;
+ case CPUINFO_INT_REGISTER + I8X41_T: TIMER = info->i & 0x1fff; break;
+ case CPUINFO_INT_REGISTER + I8X41_R0: SETR(0, info->i); break;
+ case CPUINFO_INT_REGISTER + I8X41_R1: SETR(1, info->i); break;
+ case CPUINFO_INT_REGISTER + I8X41_R2: SETR(2, info->i); break;
+ case CPUINFO_INT_REGISTER + I8X41_R3: SETR(3, info->i); break;
+ case CPUINFO_INT_REGISTER + I8X41_R4: SETR(4, info->i); break;
+ case CPUINFO_INT_REGISTER + I8X41_R5: SETR(5, info->i); break;
+ case CPUINFO_INT_REGISTER + I8X41_R6: SETR(6, info->i); break;
+ case CPUINFO_INT_REGISTER + I8X41_R7: SETR(7, info->i); break;
+
+ case CPUINFO_INT_REGISTER + I8X41_DATA:
+ DBBI = info->i;
+ if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
+ DBBO = info->i;
+ STATE &= ~F1;
+ STATE |= IBF;
+ if( ENABLE & IBFI )
+ CONTROL |= IBFI_PEND;
+ if( ENABLE & FLAGS)
+ {
+ P2_HS |= 0x20;
+ if( 0 == (STATE & OBF) ) P2_HS |= 0x10;
+ else P2_HS &= 0xef;
+ WP(0x02, (P2 & P2_HS) ); /* Assert the DBBI IRQ out on P25 */
+ }
+ break;
+
+ case CPUINFO_INT_REGISTER + I8X41_DATA_DASM:
+ /* Same as I8X41_DATA, except this is used by the */
+ /* debugger and does not upset the flag states */
+ DBBI = info->i;
+ if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
+ DBBO = info->i;
+ break;
+
+ case CPUINFO_INT_REGISTER + I8X41_CMND:
+ DBBI = info->i;
+ if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
+ DBBO = info->i;
+ STATE |= F1;
+ STATE |= IBF;
+ if( ENABLE & IBFI )
+ CONTROL |= IBFI_PEND;
+ if( ENABLE & FLAGS)
+ {
+ P2_HS |= 0x20;
+ if( 0 == (STATE & OBF) ) P2_HS |= 0x10;
+ else P2_HS &= 0xef;
+ WP(0x02, (P2 & P2_HS) ); /* Assert the DBBI IRQ out on P25 */
+ }
+ break;
+
+ case CPUINFO_INT_REGISTER + I8X41_CMND_DASM:
+ /* Same as I8X41_CMND, except this is used by the */
+ /* debugger and does not upset the flag states */
+ DBBI = info->i;
+ if( i8x41.subtype == 8041 ) /* plain 8041 had no split input/output DBB buffers */
+ DBBO = info->i;
+ break;
+
+ case CPUINFO_INT_REGISTER + I8X41_STAT:
+ logerror("i8x41 #%d:%03x Setting STAT DBBI to %02x\n", cpu_getactivecpu(), PC, (UINT8)info->i);
+ /* writing status.. hmm, should we issue interrupts here too? */
+ STATE = info->i;
+ break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void i8x41_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i8x41); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = I8X41_CLOCK_DIVIDER; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 2; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + I8X41_INT_IBF: info->i = (STATE & IBF) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + I8X41_INT_TEST1: info->i = (STATE & TEST1) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + I8X41_PC: info->i = PC; break;
+
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + I8X41_SP: info->i = PSW & SP; break;
+
+ case CPUINFO_INT_REGISTER + I8X41_PSW: info->i = PSW; break;
+ case CPUINFO_INT_REGISTER + I8X41_A: info->i = A; break;
+ case CPUINFO_INT_REGISTER + I8X41_T: info->i = TIMER; break;
+ case CPUINFO_INT_REGISTER + I8X41_R0: info->i = GETR(0); break;
+ case CPUINFO_INT_REGISTER + I8X41_R1: info->i = GETR(1); break;
+ case CPUINFO_INT_REGISTER + I8X41_R2: info->i = GETR(2); break;
+ case CPUINFO_INT_REGISTER + I8X41_R3: info->i = GETR(3); break;
+ case CPUINFO_INT_REGISTER + I8X41_R4: info->i = GETR(4); break;
+ case CPUINFO_INT_REGISTER + I8X41_R5: info->i = GETR(5); break;
+ case CPUINFO_INT_REGISTER + I8X41_R6: info->i = GETR(6); break;
+ case CPUINFO_INT_REGISTER + I8X41_R7: info->i = GETR(7); break;
+
+ case CPUINFO_INT_REGISTER + I8X41_DATA:
+ STATE &= ~OBF; /* reset the output buffer full flag */
+ if( ENABLE & FLAGS)
+ {
+ P2_HS &= 0xef;
+ if( STATE & IBF ) P2_HS |= 0x20;
+ else P2_HS &= 0xdf;
+ WP(0x02, (P2 & P2_HS) ); /* Clear the DBBO IRQ out on P24 */
+ }
+ info->i = DBBO;
+ break;
+
+ case CPUINFO_INT_REGISTER + I8X41_DATA_DASM:
+ /* Same as I8X41_DATA, except this is used by the */
+ /* debugger and does not upset the flag states */
+ info->i = DBBO;
+ break;
+
+ case CPUINFO_INT_REGISTER + I8X41_STAT:
+ logerror("i8x41 #%d:%03x Reading STAT %02x\n", cpu_getactivecpu(), PC, STATE);
+ info->i = STATE;
+ break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = i8x41_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = i8x41_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = i8x41_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = i8x41_init; break;
+ case CPUINFO_PTR_RESET: info->reset = i8x41_reset; break;
+ case CPUINFO_PTR_EXIT: info->exit = i8x41_exit; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = i8x41_execute; break;
+ case CPUINFO_PTR_BURN: info->burn = NULL; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = i8x41_dasm; break;
+#endif /* MAME_DEBUG */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &i8x41_ICount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "I8X41"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Intel 8x41"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.3"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright (c) 1999 Juergen Buchmueller, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ i8x41.psw & 0x80 ? 'C':'.',
+ i8x41.psw & 0x40 ? 'A':'.',
+ i8x41.psw & 0x20 ? '0':'.',
+ i8x41.psw & 0x10 ? 'B':'.',
+ i8x41.psw & 0x08 ? '?':'.',
+ i8x41.psw & 0x04 ? 's':'.',
+ i8x41.psw & 0x02 ? 's':'.',
+ i8x41.psw & 0x01 ? 's':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + I8X41_PC: sprintf(info->s, "PC:%04X", i8x41.pc); break;
+ case CPUINFO_STR_REGISTER + I8X41_SP: sprintf(info->s, "S:%X", i8x41.psw & SP); break;
+ case CPUINFO_STR_REGISTER + I8X41_PSW: sprintf(info->s, "PSW:%02X", i8x41.psw); break;
+ case CPUINFO_STR_REGISTER + I8X41_A: sprintf(info->s, "A:%02X", i8x41.a); break;
+ case CPUINFO_STR_REGISTER + I8X41_T: sprintf(info->s, "T:%02X.%02X", i8x41.timer, (i8x41.prescaler & 0x1f) ); break;
+ case CPUINFO_STR_REGISTER + I8X41_R0: sprintf(info->s, "R0:%02X", GETR(0)); break;
+ case CPUINFO_STR_REGISTER + I8X41_R1: sprintf(info->s, "R1:%02X", GETR(1)); break;
+ case CPUINFO_STR_REGISTER + I8X41_R2: sprintf(info->s, "R2:%02X", GETR(2)); break;
+ case CPUINFO_STR_REGISTER + I8X41_R3: sprintf(info->s, "R3:%02X", GETR(3)); break;
+ case CPUINFO_STR_REGISTER + I8X41_R4: sprintf(info->s, "R4:%02X", GETR(4)); break;
+ case CPUINFO_STR_REGISTER + I8X41_R5: sprintf(info->s, "R5:%02X", GETR(5)); break;
+ case CPUINFO_STR_REGISTER + I8X41_R6: sprintf(info->s, "R6:%02X", GETR(6)); break;
+ case CPUINFO_STR_REGISTER + I8X41_R7: sprintf(info->s, "R7:%02X", GETR(7)); break;
+ case CPUINFO_STR_REGISTER + I8X41_P1: sprintf(info->s, "P1:%02X", i8x41.p1); break;
+ case CPUINFO_STR_REGISTER + I8X41_P2: sprintf(info->s, "P2:%02X", i8x41.p2); break;
+ case CPUINFO_STR_REGISTER + I8X41_DATA_DASM: sprintf(info->s, "DBBI:%02X", i8x41.dbbi); break;
+ case CPUINFO_STR_REGISTER + I8X41_CMND_DASM: sprintf(info->s, "DBBO:%02X", i8x41.dbbo); break;
+ case CPUINFO_STR_REGISTER + I8X41_STAT: sprintf(info->s, "STAT:%02X", i8x41.state); break;
+ }
+}