/****************************************************************************
                         Alpha8201 Emulator

                      Copyright (C) 2006 Tatsuyuki Satoh
                   Originally written for the MAME project.

    Notes :

      tested with champbas.c , talbot.c , shougi.c

      This MCU looks too slow speed,
      but fast execution don't work to champbb2, champbbj, talbot.

      some unknown instruction are not emulation (used by shougi).

      Because there was no information, opcode-syntax was created.

    TODO:
        verify with real chip or analyze more.
            -call/ret stack point (8301).
            -A lot of 8301 opcode.
            -memory address 000 specification
            -memory address 001 bit 7-5 specification
            -write value after HALT operation to ODD of vector memory.
            -operation cycle(execution speed).
    History:

060327:
    IXR changes to Breg.
    The addition of Memory Access of Breg and IX0

060326:
    Added ALPHA 8301 I/F and emulation

060324:
    Archtectore Created by compare code no-MCU Z80 code and MCU version code.
    and check  talbot and shougi.c.

****************************************************************************/

/****************************************************************************

-----------------------
package / pin assign
-----------------------
ALPHA 8201 DIP 42

    1     -WR (or -RD)
    2-4 : ? NC
    5-7 : ? GND to shougi , NC to champbas
    8-14: ? NC
    15  : RESET
    16  : GND
    17  : CLK (champbas=768KHz)
    18  : ? NC
    19-21: to VCC
    22-25: DB4-DB7
    26-29: DB0-DB3
    30   : HALT (input)
    31   : ? NC
    32-35: A4-A7
    36-39: A0-A3
    40-41: A8-A9
    42   : -RD (or -WR)

ALPHA 8301 seems to be 8201 upper compatibility IC.
The package of ALPHA8301 is unknown.

-----------------------
Register Set
-----------------------

PC      : 10bit Program Pointer
          A lower 8bits are loaded from the immidate.
          A higher 2bits are loaded from the MB register.

MB      : 2bit memory bank register, load PC[9:8] after branch
          load high to higher 2bit of PC after branch.

RB      : 3bit register bank select register

R0-R7   : internal? RAM register 8bitx8 (x8 bank)

A       : 8bit

IX0/1   : memory indirect 'read' access pointer

IX2     : memory indirect 'write' access pointer

RXB     : unknown , looks index register

LP0/1/2 : loop count register used by DJNZ operation

CF      : carry flag
ZF      : zero flag

-----------------------
Memoy Space
-----------------------

000     : unknown ...
001     : bit4..0 = pointer of current entry , bit7..6 = unknown
002-003 : entrypoint1  vector
004-005 : entrypoint2  vector
006-007 : entrypoint3  vector
008-009 : entrypoint4  vector
00A-00B : entrypoint5  vector
00C-00D : entrypoint6  vector
00E-00F : entrypoint7  vector
010-011 : entrypoint8  vector
012-013 : entrypoint9  vector
014-015 : entrypoint10 vector
016-017 : entrypoint11 vector
018-019 : entrypoint12 vector
01A-01B : entrypoint13 vector
01C-01D : entrypoint14 vector
01E-01F : entrypoint15 vector
020-0FF : bank 0, program / data memory
100-1FF : bank 1, program / data memory
200-2FF : bank 2, program / data memory
300-3FF : bank 3, program / data memory

The even address is the lower byte of the entry address.
The odd-address of entry point is a MB and status.
  Bit 0 and 1 are a memory bank.
  Bit 2 is HALT.At the time of set, it doesn't execute entry address.
  After EXIT operation, Bit2 is set.

-----------------------
Timming
-----------------------

****************************************************************************/

#include "debugger.h"
#include "alph8201.h"

/* instruction cycle count */
#define C1 16
#define C2 32

/* debug option */
#define TRACE_PC 0
#define SHOW_ENTRY_POINT 0
#define SHOW_MESSAGE_CONSOLE 0

/* MAME is unnecessary */
#define HANDLE_HALT_LINE 0

/* Layout of the registers in the debugger */
static UINT8 ALPHA8201_reg_layout[] =
{
	ALPHA8201_PC,
	ALPHA8201_SP,
	ALPHA8201_RB,
	ALPHA8201_MB,
#if 0
	ALPHA8201_CF,
	ALPHA8201_ZF,
#endif
	ALPHA8201_IX0,
	ALPHA8201_IX1,
	ALPHA8201_IX2,
	ALPHA8201_LP0,
	ALPHA8201_LP1,
	ALPHA8201_LP2,
	ALPHA8201_A,
	ALPHA8201_B,
/* */
	ALPHA8201_R0,ALPHA8201_R1,ALPHA8201_R2,ALPHA8201_R3,
	ALPHA8201_R4,ALPHA8201_R5,ALPHA8201_R6,ALPHA8201_R7,
/* */
	0
};

/* Layout of the debugger windows x,y,w,h */
static UINT8 ALPHA8201_win_layout[] = {
	 0, 0,80, 2,	/* register window (top rows) */
	 0, 3,24,19,	/* disassembler window (left colums) */
	25, 3,55, 9,	/* memory #1 window (right, upper middle) */
	25,13,55, 9,	/* memory #2 window (right, lower middle) */
	 0,23,80, 1,	/* command line window (bottom rows) */
};

#define M_RDMEM(A)		ALPHA8201_RDMEM(A)
#define M_WRMEM(A,V)	ALPHA8201_WRMEM(A,V)
#define M_RDOP(A)		ALPHA8201_RDOP(A)
#define M_RDOP_ARG(A)	ALPHA8201_RDOP_ARG(A)

typedef struct
{
	UINT8 RAM[8*8];  /* internal GP register 8 * 8bank       */
	unsigned PREVPC;
	PAIR  retptr;   /* for 8301, return address stack of CALL */
	PAIR  pc;       /* 2bit+8bit program counter              */
	UINT8 regPtr;   /* RB register base                       */
	UINT8 mb;       /* MB memory bank reg. latch after Branch */
	UINT8 cf;       /* C flag                                 */
	UINT8 zf;       /* Z flag                                 */
/* */
	PAIR ix0;		/* 8bit memory read index reg. */
	PAIR ix1;		/* 8bitmemory read index reg.  */
	PAIR ix2;		/* 8bitmemory write index reg. */
	UINT8 lp0;       /* 8bit loop reg.             */
	UINT8 lp1;       /* 8bit loop reg.             */
	UINT8 lp2;       /* 8bit loop reg.             */
	UINT8 A;         /* 8bit accumerator           */
	UINT8 B;         /* 8bit regiser               */
/* */
#if HANDLE_HALT_LINE
	UINT8 halt;     /* halt input line                        */
#endif
} ALPHA8201_Regs;

/* The opcode table now is a combination of cycle counts and function pointers */
typedef struct {
	unsigned cycles;
	void (*function) (void);
}	s_opcode;

static ALPHA8201_Regs R;
int	   ALPHA8201_ICount;
static int    inst_cycles;

#define intRAM	R.RAM
#define regPTR	R.regPtr

#define PC	R.pc.w.l
#define PCL	 R.pc.b.l
#define R0	intRAM[regPTR  ]
#define R1	intRAM[regPTR+1]
#define R2	intRAM[regPTR+2]
#define R3	intRAM[regPTR+3]
#define R4	intRAM[regPTR+4]
#define R5	intRAM[regPTR+5]
#define R6	intRAM[regPTR+6]
#define R7	intRAM[regPTR+7]
#define ZF	R.zf
#define CF	R.cf
#define IX0	R.ix0.b.l
#define IX1	R.ix1.b.l
#define IX2	R.ix2.b.l
#define BIX0	R.ix0.w.l
#define BIX1	R.ix1.w.l
#define BIX2	R.ix2.w.l
#define LP0	R.lp0
#define LP1	R.lp1
#define LP2	R.lp2

/* Get next opcode argument and increment program counter */
INLINE unsigned M_RDMEM_OPCODE (void)
{
	unsigned retval;
	retval=M_RDOP_ARG(PC);
	PCL++;
	return retval;
}

INLINE void M_ADD(UINT8 dat)
{
	UINT16 temp = R.A + dat;
	R.A = temp & 0xff;
	ZF = (R.A==0);
	CF = temp>>8;
}

INLINE void M_SUB(UINT8 dat)
{
	CF = (R.A<dat);
	R.A -= dat;
	ZF = (R.A==0);
}

INLINE void M_ADDB(UINT8 dat)
{
	UINT16 temp = R.B + dat;
	R.B = temp & 0xff;
	ZF = (R.B==0);
	CF = temp>>8;
}

INLINE void M_SUBB(UINT8 dat)
{
	CF = (R.B<dat);
	R.B -= dat;
	ZF = (R.B==0);
}

INLINE void M_AND(UINT8 dat)
{
	R.A &= dat;
	ZF = (R.A==0);
	CF = 0;
}

INLINE void M_OR(UINT8 dat)
{
	R.A |= dat;
	ZF = (R.A==0);
	CF = 0;
}

INLINE void M_JMP(UINT8 dat)
{
	PCL = dat;
	/* update pc page */
	R.pc.b.h  = R.ix0.b.h = R.ix1.b.h = R.ix2.b.h = R.mb & 3;
	change_pc(PC);
}

INLINE void M_UNDEFINED(void)
{
	logerror("ALPHA8201:  PC = %03x,  Unimplemented opcode = %02x\n", PC-1, M_RDMEM(PC-1));
#if SHOW_MESSAGE_CONSOLE
	printf("ALPHA8201:  PC = %03x,  Unimplemented opcode = %02x\n", PC-1, M_RDMEM(PC-1));
#endif
}

INLINE void M_UNDEFINED2(void)
{
	UINT8 op  = M_RDOP(PC-1);
	UINT8 imm = M_RDMEM_OPCODE();
	logerror("ALPHA8201:  PC = %03x,  Unimplemented opcode = %02x,%02x\n", PC-2, op,imm);
#if SHOW_MESSAGE_CONSOLE
	printf("ALPHA8201:  PC = %03x,  Unimplemented opcode = %02x,%02x\n", PC-2, op,imm);
#endif
}

static void undefined(void)	{ M_UNDEFINED(); }
static void undefined2(void)	{ M_UNDEFINED2(); }

static void need_verify(const char *s)
{
	UINT8 op  = M_RDOP(PC-1);
	logerror("ALPHA8201:  PC = %03x, unknown opcode = %02x is '%s' ??\n",PC-1, op,s);
#if SHOW_MESSAGE_CONSOLE
	printf("ALPHA8201:  PC = %03x, unknown opcode = %02x is '%s' ??\n",PC-1, op,s);
#endif
}

static void nop(void)		 { }
static void rlca(void)		 { CF = (R.A>>7)&1; R.A = (R.A<<1) | (R.A>>7); ZF = (R.A==0); }
static void rrca(void)		 { CF = R.A &1;     R.A = (R.A>>1) | (R.A<<7); ZF = (R.A==0); }
static void inc_b(void)	 	 { M_ADDB(1); }
static void dec_b(void)	 	 { M_SUBB(1); };
static void inc_a(void)		 { M_ADD(1); }
static void dec_a(void)		 { M_SUB(1); }
static void cpl(void)		 { R.A = R.A^0xff; ZF = (R.A==0); };

static void ld_a_ix0_0(void) { R.A = M_RDMEM(BIX0+0); }
static void ld_a_ix0_1(void) { R.A = M_RDMEM(BIX0+1); }
static void ld_a_ix0_2(void) { R.A = M_RDMEM(BIX0+2); }
static void ld_a_ix0_3(void) { R.A = M_RDMEM(BIX0+3); }
static void ld_a_ix0_4(void) { R.A = M_RDMEM(BIX0+4); }
static void ld_a_ix0_5(void) { R.A = M_RDMEM(BIX0+5); }
static void ld_a_ix0_6(void) { R.A = M_RDMEM(BIX0+6); }
static void ld_a_ix0_7(void) { R.A = M_RDMEM(BIX0+7); }

static void ld_a_ix1_0(void) { R.A = M_RDMEM(BIX1+0); }
static void ld_a_ix1_1(void) { R.A = M_RDMEM(BIX1+1); }
static void ld_a_ix1_2(void) { R.A = M_RDMEM(BIX1+2); }
static void ld_a_ix1_3(void) { R.A = M_RDMEM(BIX1+3); }
static void ld_a_ix1_4(void) { R.A = M_RDMEM(BIX1+4); }
static void ld_a_ix1_5(void) { R.A = M_RDMEM(BIX1+5); }
static void ld_a_ix1_6(void) { R.A = M_RDMEM(BIX1+6); }
static void ld_a_ix1_7(void) { R.A = M_RDMEM(BIX1+7); }

static void ld_ix2_0_a(void) { M_WRMEM(BIX2+0,R.A); }
static void ld_ix2_1_a(void) { M_WRMEM(BIX2+1,R.A); }
static void ld_ix2_2_a(void) { M_WRMEM(BIX2+2,R.A); }
static void ld_ix2_3_a(void) { M_WRMEM(BIX2+3,R.A); }
static void ld_ix2_4_a(void) { M_WRMEM(BIX2+4,R.A); }
static void ld_ix2_5_a(void) { M_WRMEM(BIX2+5,R.A); }
static void ld_ix2_6_a(void) { M_WRMEM(BIX2+6,R.A); }
static void ld_ix2_7_a(void) { M_WRMEM(BIX2+7,R.A); }

static void ld_ix0_0_b(void) { M_WRMEM(BIX0+0,R.B); }
static void ld_ix0_1_b(void) { M_WRMEM(BIX0+0,R.B); }
static void ld_ix0_2_b(void) { M_WRMEM(BIX0+0,R.B); }
static void ld_ix0_3_b(void) { M_WRMEM(BIX0+0,R.B); }
static void ld_ix0_4_b(void) { M_WRMEM(BIX0+0,R.B); }
static void ld_ix0_5_b(void) { M_WRMEM(BIX0+0,R.B); }
static void ld_ix0_6_b(void) { M_WRMEM(BIX0+0,R.B); }
static void ld_ix0_7_b(void) { M_WRMEM(BIX0+0,R.B); }

static void ld_ix1_0_b(void) { M_WRMEM(BIX1+0,R.B); need_verify("LD   (IX1+0),B"); }
static void ld_ix1_1_b(void) { M_WRMEM(BIX1+1,R.B); need_verify("LD   (IX1+1),B"); }
static void ld_ix1_2_b(void) { M_WRMEM(BIX1+2,R.B); need_verify("LD   (IX1+2),B"); }
static void ld_ix1_3_b(void) { M_WRMEM(BIX1+3,R.B); need_verify("LD   (IX1+3),B"); }
static void ld_ix1_4_b(void) { M_WRMEM(BIX1+4,R.B); need_verify("LD   (IX1+4),B"); }
static void ld_ix1_5_b(void) { M_WRMEM(BIX1+5,R.B); need_verify("LD   (IX1+5),B"); }
static void ld_ix1_6_b(void) { M_WRMEM(BIX1+6,R.B); need_verify("LD   (IX1+6),B"); }
static void ld_ix1_7_b(void) { M_WRMEM(BIX1+7,R.B); need_verify("LD   (IX1+7),B"); }

static void ld_b_ix2_0(void) { R.B = M_RDMEM(BIX2+0); need_verify("LD   B,(IX2+0)");  }
static void ld_b_ix2_1(void) { R.B = M_RDMEM(BIX2+1); need_verify("LD   B,(IX2+1)");  }
static void ld_b_ix2_2(void) { R.B = M_RDMEM(BIX2+2); need_verify("LD   B,(IX2+2)");  }
static void ld_b_ix2_3(void) { R.B = M_RDMEM(BIX2+3); need_verify("LD   B,(IX2+3)");  }
static void ld_b_ix2_4(void) { R.B = M_RDMEM(BIX2+4); need_verify("LD   B,(IX2+4)");  }
static void ld_b_ix2_5(void) { R.B = M_RDMEM(BIX2+5); need_verify("LD   B,(IX2+5)");  }
static void ld_b_ix2_6(void) { R.B = M_RDMEM(BIX2+6); need_verify("LD   B,(IX2+6)");  }
static void ld_b_ix2_7(void) { R.B = M_RDMEM(BIX2+7); need_verify("LD   B,(IX2+7)");  }

static void bit_r0_0(void)	 { R.zf = R0&(1<<0)?0:1; }
static void bit_r0_1(void)	 { R.zf = R0&(1<<1)?0:1; }
static void bit_r0_2(void)	 { R.zf = R0&(1<<2)?0:1; }
static void bit_r0_3(void)	 { R.zf = R0&(1<<3)?0:1; }
static void bit_r0_4(void)	 { R.zf = R0&(1<<4)?0:1; }
static void bit_r0_5(void)	 { R.zf = R0&(1<<5)?0:1; }
static void bit_r0_6(void)	 { R.zf = R0&(1<<6)?0:1; }
static void bit_r0_7(void)	 { R.zf = R0&(1<<7)?0:1; }

static void ld_a_n(void)	 { R.A = M_RDMEM_OPCODE(); }
static void ld_a_r0(void)	 { R.A = R0; }
static void ld_a_r1(void)	 { R.A = R1; }
static void ld_a_r2(void)	 { R.A = R2; }
static void ld_a_r3(void)	 { R.A = R3; }
static void ld_a_r4(void)	 { R.A = R4; }
static void ld_a_r5(void)	 { R.A = R5; }
static void ld_a_r6(void)	 { R.A = R6; }
static void ld_a_r7(void)	 { R.A = R7; }

static void ld_r0_a(void)	 { R0 = R.A; }
static void ld_r1_a(void)	 { R1 = R.A; }
static void ld_r2_a(void)	 { R2 = R.A; }
static void ld_r3_a(void)	 { R3 = R.A; }
static void ld_r4_a(void)	 { R4 = R.A; }
static void ld_r5_a(void)	 { R5 = R.A; }
static void ld_r6_a(void)	 { R6 = R.A; }
static void ld_r7_a(void)	 { R7 = R.A; }

static void add_a_n(void)	 { M_ADD(M_RDMEM_OPCODE()); }
static void add_a_r0(void)	 { M_ADD(R0); }
static void add_a_r1(void)	 { M_ADD(R1); }
static void add_a_r2(void)	 { M_ADD(R2); }
static void add_a_r3(void)	 { M_ADD(R3); }
static void add_a_r4(void)	 { M_ADD(R4); }
static void add_a_r5(void)	 { M_ADD(R5); }
static void add_a_r6(void)	 { M_ADD(R6); }
static void add_a_r7(void)	 { M_ADD(R7); }

static void sub_a_n(void)	 { M_SUB(M_RDMEM_OPCODE()); }
static void sub_a_r0(void)	 { M_SUB(R0); }
static void sub_a_r1(void)	 { M_SUB(R1); }
static void sub_a_r2(void)	 { M_SUB(R2); }
static void sub_a_r3(void)	 { M_SUB(R3); }
static void sub_a_r4(void)	 { M_SUB(R4); }
static void sub_a_r5(void)	 { M_SUB(R5); }
static void sub_a_r6(void)	 { M_SUB(R6); }
static void sub_a_r7(void)	 { M_SUB(R7); }

static void and_a_n(void)	 { M_AND(M_RDMEM_OPCODE()); }
static void and_a_r0(void)	 { M_AND(R0); }
static void and_a_r1(void)	 { M_AND(R1); }
static void and_a_r2(void)	 { M_AND(R2); }
static void and_a_r3(void)	 { M_AND(R3); }
static void and_a_r4(void)	 { M_AND(R4); }
static void and_a_r5(void)	 { M_AND(R5); }
static void and_a_r6(void)	 { M_AND(R6); }
static void and_a_r7(void)	 { M_AND(R7); }

static void or_a_n(void)	 { M_OR(M_RDMEM_OPCODE()); }
static void or_a_r0(void)	 { M_OR(R0); }
static void or_a_r1(void)	 { M_OR(R1); }
static void or_a_r2(void)	 { M_OR(R2); }
static void or_a_r3(void)	 { M_OR(R3); }
static void or_a_r4(void)	 { M_OR(R4); }
static void or_a_r5(void)	 { M_OR(R5); }
static void or_a_r6(void)	 { M_OR(R6); }
static void or_a_r7(void)	 { M_OR(R7); }

static void add_ix0_0(void)	 {}
static void add_ix0_1(void)	 { IX0 += 1; }
static void add_ix0_2(void)	 { IX0 += 2; }
static void add_ix0_3(void)	 { IX0 += 3; }
static void add_ix0_4(void)	 { IX0 += 4; }
static void add_ix0_5(void)	 { IX0 += 5; }
static void add_ix0_6(void)	 { IX0 += 6; }
static void add_ix0_7(void)	 { IX0 += 7; }
static void add_ix0_8(void)	 { IX0 += 8; }
static void add_ix0_9(void)	 { IX0 += 9; }
static void add_ix0_a(void)	 { IX0 += 10; }
static void add_ix0_b(void)	 { IX0 += 11; }
static void add_ix0_c(void)	 { IX0 += 12; }
static void add_ix0_d(void)	 { IX0 += 13; }
static void add_ix0_e(void)	 { IX0 += 14; }
static void add_ix0_f(void)	 { IX0 += 15; }

static void add_ix1_0(void)	 {}
static void add_ix1_1(void)	 { IX1 += 1; }
static void add_ix1_2(void)	 { IX1 += 2; }
static void add_ix1_3(void)	 { IX1 += 3; }
static void add_ix1_4(void)	 { IX1 += 4; }
static void add_ix1_5(void)	 { IX1 += 5; }
static void add_ix1_6(void)	 { IX1 += 6; }
static void add_ix1_7(void)	 { IX1 += 7; }
static void add_ix1_8(void)	 { IX1 += 8; }
static void add_ix1_9(void)	 { IX1 += 9; }
static void add_ix1_a(void)	 { IX1 += 10; }
static void add_ix1_b(void)	 { IX1 += 11; }
static void add_ix1_c(void)	 { IX1 += 12; }
static void add_ix1_d(void)	 { IX1 += 13; }
static void add_ix1_e(void)	 { IX1 += 14; }
static void add_ix1_f(void)	 { IX1 += 15; }

static void add_ix2_0(void)	 {}
static void add_ix2_1(void)	 { IX2 += 1; }
static void add_ix2_2(void)	 { IX2 += 2; }
static void add_ix2_3(void)	 { IX2 += 3; }
static void add_ix2_4(void)	 { IX2 += 4; }
static void add_ix2_5(void)	 { IX2 += 5; }
static void add_ix2_6(void)	 { IX2 += 6; }
static void add_ix2_7(void)	 { IX2 += 7; }
static void add_ix2_8(void)	 { IX2 += 8; }
static void add_ix2_9(void)	 { IX2 += 9; }
static void add_ix2_a(void)	 { IX2 += 10; }
static void add_ix2_b(void)	 { IX2 += 11; }
static void add_ix2_c(void)	 { IX2 += 12; }
static void add_ix2_d(void)	 { IX2 += 13; }
static void add_ix2_e(void)	 { IX2 += 14; }
static void add_ix2_f(void)	 { IX2 += 15; }

static void ld_base_0(void)	 { regPTR = 0<<3; }
static void ld_base_1(void)	 { regPTR = 1<<3; }
static void ld_base_2(void)	 { regPTR = 2<<3; }
static void ld_base_3(void)	 { regPTR = 3<<3; }
static void ld_base_4(void)	 { regPTR = 4<<3; }
static void ld_base_5(void)	 { regPTR = 5<<3; }
static void ld_base_6(void)	 { regPTR = 6<<3; }
static void ld_base_7(void)	 { regPTR = 7<<3; }

static void ld_bank_0(void)	 { R.mb = 0; }
static void ld_bank_1(void)	 { R.mb = 1; }
static void ld_bank_2(void)	 { R.mb = 2; }
static void ld_bank_3(void)	 { R.mb = 3; }

static void halt(void)
{
	UINT8 pcptr = M_RDMEM(0x001) & 0x1f;
	M_WRMEM(pcptr,0x08); /* mark entry point ODD to HALT */
	R.mb |= 0x08;        /* mark internal HALT state */
}

static void ld_ix0_n(void)	 { IX0 = M_RDMEM_OPCODE(); }
static void ld_ix1_n(void)	 { IX1 = M_RDMEM_OPCODE(); }
static void ld_ix2_n(void)	 { IX2 = M_RDMEM_OPCODE(); }
static void ld_lp0_n(void)	 { LP0 = M_RDMEM_OPCODE(); }
static void ld_lp1_n(void)	 { LP1 = M_RDMEM_OPCODE(); }
static void ld_lp2_n(void)	 { LP2 = M_RDMEM_OPCODE(); }
static void ld_b_n(void)	 { R.B = M_RDMEM_OPCODE(); }

static void djnz_lp0(void)	{ UINT8 i=M_RDMEM_OPCODE(); LP0--; if (LP0 != 0) M_JMP(i); }
static void djnz_lp1(void)	{ UINT8 i=M_RDMEM_OPCODE(); LP1--; if (LP1 != 0) M_JMP(i); }
static void djnz_lp2(void)	{ UINT8 i=M_RDMEM_OPCODE(); LP2--; if (LP2 != 0) M_JMP(i); }
static void jnz(void)	{ UINT8 i=M_RDMEM_OPCODE(); if (!R.zf) M_JMP(i); }
static void jc(void)	{ UINT8 i=M_RDMEM_OPCODE(); if ( R.cf) M_JMP(i); }
static void jz(void)	{ UINT8 i=M_RDMEM_OPCODE(); if ( R.zf) M_JMP(i); }
static void jmp(void)	{ M_JMP( M_RDMEM_OPCODE() ); }

#if (HAS_ALPHA8201)
static const s_opcode opcode_8201[256]=
{
	{C1, nop        },{C1,rrca      },{C1, rlca      },{C1,inc_b     },{C1, dec_b    },{C1, inc_a    },{C1, dec_a    },{C1, cpl      },
	{C2,ld_a_ix0_0  },{C2,ld_a_ix0_1},{C2, ld_a_ix0_2},{C2,ld_a_ix0_3},{C2,ld_a_ix0_4},{C2,ld_a_ix0_5},{C2,ld_a_ix0_6},{C2,ld_a_ix0_7},
	{C2,ld_a_ix1_0  },{C2,ld_a_ix1_1},{C2, ld_a_ix1_2},{C2,ld_a_ix1_3},{C2,ld_a_ix1_4},{C2,ld_a_ix1_5},{C2,ld_a_ix1_6},{C2,ld_a_ix1_7},
	{C2,ld_ix2_0_a  },{C2,ld_ix2_1_a},{C2, ld_ix2_2_a},{C2,ld_ix2_3_a},{C2,ld_ix2_4_a},{C2,ld_ix2_5_a},{C2,ld_ix2_6_a},{C2,ld_ix2_7_a},
/* 20 */
	{C2,ld_ix0_0_b  },{C2,ld_ix0_1_b},{C2, ld_ix0_2_b},{C2,ld_ix0_3_b},{C2,ld_ix0_4_b},{C2,ld_ix0_5_b},{C2,ld_ix0_6_b},{C2,ld_ix0_7_b},
	{C2,ld_ix1_0_b  },{C2,ld_ix1_1_b},{C2, ld_ix1_2_b},{C2,ld_ix1_3_b},{C2,ld_ix1_4_b},{C2,ld_ix1_5_b},{C2,ld_ix1_6_b},{C2,ld_ix1_7_b},
	{C2,ld_b_ix2_0  },{C2,ld_b_ix2_1},{C2, ld_b_ix2_2},{C2,ld_b_ix2_3},{C2,ld_b_ix2_4},{C2,ld_b_ix2_5},{C2,ld_b_ix2_6},{C2,ld_b_ix2_7},
	{C2,bit_r0_0    },{C2,bit_r0_1  },{C2, bit_r0_2 },{C2, bit_r0_3 },{C2, bit_r0_4 },{C2, bit_r0_5 },{C2, bit_r0_6 },{C2, bit_r0_7 },
/* 40 : 8201 */
	{C2, ld_a_r0    },{C2, ld_r0_a	},{C2, ld_a_r1	},{C2, ld_r1_a	},{C2, ld_a_r2	},{C2, ld_r2_a	},{C2, ld_a_r3	},{C2, ld_r3_a	},
	{C2, ld_a_r4    },{C2, ld_r4_a	},{C2, ld_a_r5	},{C2, ld_r5_a	},{C2, ld_a_r6	},{C2, ld_r6_a	},{C2, ld_a_r7	},{C2, ld_r7_a	},
	{C1, add_a_r0   },{C1, sub_a_r0	},{C1, add_a_r1	},{C1, sub_a_r1	},{C1, add_a_r2	},{C1, sub_a_r2	},{C1, add_a_r3	},{C1, sub_a_r3	},
	{C1, add_a_r4   },{C1, sub_a_r4	},{C1, add_a_r5	},{C1, sub_a_r5	},{C1, add_a_r6	},{C1, sub_a_r6	},{C1, add_a_r7	},{C1, sub_a_r7	},
	{C1, and_a_r0   },{C1, or_a_r0	},{C1, and_a_r1	},{C1, or_a_r1	},{C1, and_a_r2	},{C1, or_a_r2	},{C1, and_a_r3	},{C1, or_a_r3	},
	{C1, and_a_r4	},{C1, or_a_r4	},{C1, and_a_r5	},{C1, or_a_r5	},{C1, and_a_r6	},{C1, or_a_r6	},{C1, and_a_r7	},{C1, or_a_r7	},
	{C1, add_ix0_0	},{C1, add_ix0_1},{C1, add_ix0_2},{C1, add_ix0_3},{C1, add_ix0_4},{C1, add_ix0_5},{C1, add_ix0_6},{C1, add_ix0_7},
	{C1, add_ix0_8	},{C1, add_ix0_9},{C1, add_ix0_a},{C1, add_ix0_b},{C1, add_ix0_c},{C1, add_ix0_d},{C1, add_ix0_e},{C1, add_ix0_f},
/* 80 : 8201 */
	{C1, add_ix1_0	},{C1, add_ix1_1},{C1, add_ix1_2},{C1, add_ix1_3},{C1, add_ix1_4},{C1, add_ix1_5},{C1, add_ix1_6},{C1, add_ix1_7},
	{C1, add_ix1_8	},{C1, add_ix1_9},{C1, add_ix1_a},{C1, add_ix1_b},{C1, add_ix1_c},{C1, add_ix1_d},{C1, add_ix1_e},{C1, add_ix1_f},
	{C1, add_ix2_0	},{C1, add_ix2_1},{C1, add_ix2_2},{C1, add_ix2_3},{C1, add_ix2_4},{C1, add_ix2_5},{C1, add_ix2_6},{C1, add_ix2_7},
	{C1, add_ix2_8	},{C1, add_ix2_9},{C1, add_ix2_a},{C1, add_ix2_b},{C1, add_ix2_c},{C1, add_ix2_d},{C1, add_ix2_e},{C1, add_ix2_f},
	{C1, ld_base_0	},{C1, ld_base_1},{C1, ld_base_2},{C1, ld_base_3},{C1, ld_base_4},{C1, ld_base_5},{C1, ld_base_6},{C1, ld_base_7},
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, ld_bank_0	},{C1, ld_bank_1},{C1, ld_bank_2},{C1, ld_bank_3},{C2, halt		},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
/* c0 : 8201 */
	{C2, ld_ix0_n	},{C2, ld_ix1_n	},{C2, ld_ix2_n	},{C2, ld_a_n	},{C2, ld_lp0_n	},{C2, ld_lp1_n	},{C2, ld_lp2_n	},{C2, ld_b_n	},
	{C2, add_a_n	},{C2, sub_a_n	},{C2, and_a_n	},{C2, or_a_n	},{C2, djnz_lp0	},{C2, djnz_lp1	},{C2, djnz_lp2	},{C2, jnz		},
	{C2, jc			},{C2, jz		},{C2, jmp		},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2, undefined2},
	{C2, undefined2	},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2, undefined2},
/* E0 : 8201*/
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined }
};
#endif

#if (HAS_ALPHA8301)

/* ALPHA 8301 : added instruction */
static void dec_ix0(void)  { IX0--; } /* OK */

static void ld_a_b(void)  { R.A = R.B; }
static void ld_b_a(void)  { R.B = R.A; }

static void ld_ix0_a(void)    { IX0 = R.A; } /* maybe OK */
static void ld_ix1_a(void)    { IX1 = R.A; need_verify("LD   IX1,A"); } /* not found */
static void ld_ix2_a(void)    { IX2 = R.A; } /* maybe OK */

static void ld_ix2_ix0(void)  { IX2 = IX0; } /* OK */

/* used by exctscc2 initialize routine */
/* A=2 , D5 01 , D4 00 -> R=5 */
/* A=5 , D4 01 -> R=2         */
/*
300: DA 02   CMP  A,$02  ; A is 2
302: CF 00   JNZ  $00
304: A7      LD   RB,7
305: 41      LD   R0,A
306: 4F      LD   R7,A
307: D5 01 --------------
309: D4 00 --------------
30B: DA 05   CMP  A,$05   ; A must be set 5
30D: CF 00   JNZ  $00
30F: D4 01 --------------
311: DA 02   CMP  A,$02   ; A must be set 5
313: CF 00   JNZ  $00
315: FD      clr  a ?
*/
static void op_d4(void) { undefined2(); }
static void op_d5(void) { undefined2(); }

/* used by exctsccr/exctscc2 ROM check sum routine (382-3cf) */
/* ZF = 0 in op_f8 are patch for bypass exctsccr and exctscc2 check sum error */
static void op_f6(void) { logerror("ALPHA-8301 Unknown OP-code PC = %03x, opcode = 0xf6: alu ?,a ??\n",PC-1); }
static void op_f8(void) { ZF = 1; logerror("ALPHA-8301 Unknown OP-code PC = %03x, opcode = 0xf8: alu ?,a ??\n",PC-1); }
static void op_f9(void) { logerror("ALPHA-8301 Unknown OP-code PC = %03x, opcode = 0xf9: alu a,? ??\n",PC-1); }

static void add_a_cf(void) { R.A += CF; CF = 0; ZF = (R.A==0); } /* OK */
static void tst_a(void)	 { ZF = (R.A==0); }                          /* maybe OK */
static void clr_a(void)	 { R.A = 0; ZF = (R.A==0); }                 /* maybe OK */
static void cmp_a_n(void)	{ UINT8 i=M_RDMEM_OPCODE();  ZF = (R.A==i); CF = (R.A<i); }
static void call(void) { UINT8 i=M_RDMEM_OPCODE(); R.retptr.w.l = PC; M_JMP(i); }; /* OK , but stack is unknown */
static void ld_a_ix0_a(void) { R.A = M_RDMEM(BIX0+R.A); }              /* maybe OK */
static void ret(void) { R.mb = R.retptr.b.h; M_JMP( R.retptr.b.l ); }; /* OK , but stack is unknown */

static const s_opcode opcode_8301[256]=
{
	{C1, nop        },{C1,rrca      },{C1, rlca      },{C1,inc_b     },{C1, dec_b    },{C1, inc_a    },{C1, dec_a    },{C1, cpl      },
	{C2,ld_a_ix0_0  },{C2,ld_a_ix0_1},{C2, ld_a_ix0_2},{C2,ld_a_ix0_3},{C2,ld_a_ix0_4},{C2,ld_a_ix0_5},{C2,ld_a_ix0_6},{C2,ld_a_ix0_7},
	{C2,ld_a_ix1_0  },{C2,ld_a_ix1_1},{C2, ld_a_ix1_2},{C2,ld_a_ix1_3},{C2,ld_a_ix1_4},{C2,ld_a_ix1_5},{C2,ld_a_ix1_6},{C2,ld_a_ix1_7},
	{C2,ld_ix2_0_a  },{C2,ld_ix2_1_a},{C2, ld_ix2_2_a},{C2,ld_ix2_3_a},{C2,ld_ix2_4_a},{C2,ld_ix2_5_a},{C2,ld_ix2_6_a},{C2,ld_ix2_7_a},
/* 20 : 8301 */
	{C2,ld_ix0_0_b  },{C2,ld_ix0_1_b},{C2, ld_ix0_2_b},{C2,ld_ix0_3_b},{C2,ld_ix0_4_b},{C2,ld_ix0_5_b},{C2,ld_ix0_6_b},{C2,ld_ix0_7_b},
	{C2,ld_ix1_0_b  },{C2,ld_ix1_1_b},{C2, ld_ix1_2_b},{C2,ld_ix1_3_b},{C2,ld_ix1_4_b},{C2,ld_ix1_5_b},{C2,ld_ix1_6_b},{C2,ld_ix1_7_b},
	{C2,ld_b_ix2_0  },{C2,ld_b_ix2_1},{C2, ld_b_ix2_2},{C2,ld_b_ix2_3},{C2,ld_b_ix2_4},{C2,ld_b_ix2_5},{C2,ld_b_ix2_6},{C2,ld_b_ix2_7},
	{C2,bit_r0_0    },{C2,bit_r0_1  },{C2, bit_r0_2 },{C2, bit_r0_3 },{C2, bit_r0_4 },{C2, bit_r0_5 },{C2, bit_r0_6 },{C2, bit_r0_7 },
/* 40 : 8301 */
	{C2, ld_a_r0    },{C2, ld_r0_a	},{C2, ld_a_r1	},{C2, ld_r1_a	},{C2, ld_a_r2	},{C2, ld_r2_a	},{C2, ld_a_r3	},{C2, ld_r3_a	},
	{C2, ld_a_r4    },{C2, ld_r4_a	},{C2, ld_a_r5	},{C2, ld_r5_a	},{C2, ld_a_r6	},{C2, ld_r6_a	},{C2, ld_a_r7	},{C2, ld_r7_a	},
	{C1, add_a_r0   },{C1, sub_a_r0	},{C1, add_a_r1	},{C1, sub_a_r1	},{C1, add_a_r2	},{C1, sub_a_r2	},{C1, add_a_r3	},{C1, sub_a_r3	},
	{C1, add_a_r4   },{C1, sub_a_r4	},{C1, add_a_r5	},{C1, sub_a_r5	},{C1, add_a_r6	},{C1, sub_a_r6	},{C1, add_a_r7	},{C1, sub_a_r7	},
/* 60 : 8301 */
	{C1, and_a_r0   },{C1, or_a_r0	},{C1, and_a_r1	},{C1, or_a_r1	},{C1, and_a_r2	},{C1, or_a_r2	},{C1, and_a_r3	},{C1, or_a_r3	},
	{C1, and_a_r4	},{C1, or_a_r4	},{C1, and_a_r5	},{C1, or_a_r5	},{C1, and_a_r6	},{C1, or_a_r6	},{C1, and_a_r7	},{C1, or_a_r7	},
	{C1, add_ix0_0	},{C1, add_ix0_1},{C1, add_ix0_2},{C1, add_ix0_3},{C1, add_ix0_4},{C1, add_ix0_5},{C1, add_ix0_6},{C1, add_ix0_7},
	{C1, add_ix0_8	},{C1, add_ix0_9},{C1, add_ix0_a},{C1, add_ix0_b},{C1, add_ix0_c},{C1, add_ix0_d},{C1, add_ix0_e},{C1, add_ix0_f},
/* 80 : 8301 */
	{C1, add_ix1_0	},{C1, add_ix1_1},{C1, add_ix1_2},{C1, add_ix1_3},{C1, add_ix1_4},{C1, add_ix1_5},{C1, add_ix1_6},{C1, add_ix1_7},
	{C1, add_ix1_8	},{C1, add_ix1_9},{C1, add_ix1_a},{C1, add_ix1_b},{C1, add_ix1_c},{C1, add_ix1_d},{C1, add_ix1_e},{C1, add_ix1_f},
	{C1, add_ix2_0	},{C1, add_ix2_1},{C1, add_ix2_2},{C1, add_ix2_3},{C1, add_ix2_4},{C1, add_ix2_5},{C1, add_ix2_6},{C1, add_ix2_7},
	{C1, add_ix2_8	},{C1, add_ix2_9},{C1, add_ix2_a},{C1, add_ix2_b},{C1, add_ix2_c},{C1, add_ix2_d},{C1, add_ix2_e},{C1, add_ix2_f},
/* A0 : 8301 */
	{C1, ld_base_0	},{C1, ld_base_1},{C1, ld_base_2},{C1, ld_base_3},{C1, ld_base_4},{C1, ld_base_5},{C1, ld_base_6},{C1, ld_base_7},
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, ld_bank_0	},{C1, ld_bank_1},{C1, ld_bank_2},{C1, ld_bank_3},{C2, halt		},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, undefined	},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
/* c0 : 8301 */
	{C2, ld_ix0_n	},{C2, ld_ix1_n	},{C2, ld_ix2_n	},{C2, ld_a_n	},{C2, ld_lp0_n	},{C2, ld_lp1_n	},{C2, ld_lp2_n	},{C2, ld_b_n	},
	{C2, add_a_n	},{C2, sub_a_n	},{C2, and_a_n	},{C2, or_a_n	},{C2, djnz_lp0	},{C2, djnz_lp1	},{C2, djnz_lp2	},{C2, jnz		},
	{C2, jc			},{C2, jz		},{C2, jmp		},{C2,undefined2},{C2, op_d4    },{C2, op_d5    },{C2,undefined2},{C2, undefined2},
	{C2, undefined2	},{C2,undefined2},{C2,cmp_a_n	},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2,undefined2},{C2, call},
/* E0 : 8301 */
	{C1, dec_ix0	},{C1, undefined},{C1, undefined},{C1, ld_a_b   },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, ld_ix0_a	},{C1, ld_ix1_a },{C1, ld_ix2_a },{C1, ld_b_a   },{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},
	{C1, undefined	},{C1,ld_ix2_ix0},{C1, undefined},{C1, undefined},{C1, undefined},{C1, undefined},{C1, op_f6    },{C1, undefined},
	{C1, op_f8		},{C1, op_f9    },{C1, add_a_cf },{C1, undefined},{C1, tst_a    },{C1, clr_a	},{C1,ld_a_ix0_a},{C1, ret }
};
#endif

/****************************************************************************
 * Initialize emulation
 ****************************************************************************/
static void ALPHA8201_init (int index, int clock, const void *config, int (*irqcallback)(int))
{
	state_save_register_item_array("ALPHA8201", index, R.RAM);
	state_save_register_item("ALPHA8201", index, R.PREVPC);
	state_save_register_item("ALPHA8201", index, PC);
	state_save_register_item("ALPHA8201", index, regPTR);
	state_save_register_item("ALPHA8201", index, R.zf);
	state_save_register_item("ALPHA8201", index, R.cf);
	state_save_register_item("ALPHA8201", index, R.mb);
#if HANDLE_HALT_LINE
	state_save_register_item("ALPHA8201", index, R.halt);
#endif
	state_save_register_item("ALPHA8201", index, IX0);
	state_save_register_item("ALPHA8201", index, IX1);
	state_save_register_item("ALPHA8201", index, IX2);
	state_save_register_item("ALPHA8201", index, LP0);
	state_save_register_item("ALPHA8201", index, LP1);
	state_save_register_item("ALPHA8201", index, LP2);
	state_save_register_item("ALPHA8201", index, R.A);
	state_save_register_item("ALPHA8201", index, R.B);
}
/****************************************************************************
 * Reset registers to their initial values
 ****************************************************************************/
static void ALPHA8201_reset (void)
{
	PC     = 0;
	regPTR = 0;
	ZF     = 0;
	CF     = 0;
	R.mb   = 0;
	BIX0   = 0;
	BIX1   = 0;
	BIX2   = 0;
	LP0    = 0;
	LP1    = 0;
	LP2    = 0;
	R.A    = 0;
	R.B   = 0;
#if HANDLE_HALT_LINE
	R.halt = 0;
#endif
/*  memset(R.RAM, 0, sizeof(R.RAM)); */
}

/****************************************************************************
 * Shut down CPU emulation
 ****************************************************************************/
static void ALPHA8201_exit (void)
{
	/* nothing to do ? */
}

/****************************************************************************
 * Execute cycles CPU cycles. Return number of cycles really executed
 ****************************************************************************/

static int alpha8xxx_execute(const s_opcode *op_map,int cycles)
{
	unsigned opcode;
	UINT8 pcptr;

	ALPHA8201_ICount = cycles;

#if HANDLE_HALT_LINE
	if(R.halt)
		return cycles;
#endif

	/* setup address bank & fall safe */
	R.ix0.b.h =
	R.ix1.b.h =
	R.ix2.b.h = (R.pc.b.h &= 3);

	/* reset start hack */
	if(PC<0x20)
		R.mb |= 0x08;

	do
	{
		if(R.mb & 0x08)
		{
			pcptr = M_RDMEM(0x001) & 0x1f; /* pointer of entry point */
			ALPHA8201_ICount -= C1;

			/* entry point scan phase */
			if( (pcptr&1) == 0)
			{
				/* EVEN , get PC low */
				R.pc.b.l = M_RDMEM(pcptr);
/*printf("ALPHA8201 load PCL ENTRY=%02X PCL=%02X\n",pcptr, R.pc.b.l); */
				ALPHA8201_ICount -= C1;
				M_WRMEM(0x001,pcptr+1);
				continue;
			}

			/* ODD , check HALT flag */
			R.mb   = M_RDMEM(pcptr) & (0x08|0x03);
			ALPHA8201_ICount -= C1;

			/* not entryaddress 000,001 */
			if(pcptr<2) R.mb |= 0x08;

			if(R.mb & 0x08)
			{
				/* HALTED current entry point . next one */
				pcptr = (pcptr+1)&0x1f;
				M_WRMEM(0x001,pcptr);
				ALPHA8201_ICount -= C1;
				continue;
			}

			/* goto run phase */
			M_JMP(R.pc.b.l);

#if SHOW_ENTRY_POINT
logerror("ALPHA8201 START ENTRY=%02X PC=%03X\n",pcptr,PC);
printf("ALPHA8201 START ENTRY=%02X PC=%03X\n",pcptr,PC);
#endif
		}

		/* run */
		R.PREVPC = PC;
		CALL_MAME_DEBUG;
		opcode =M_RDOP(PC);
#if TRACE_PC
printf("ALPHA8201:  PC = %03x,  opcode = %02x\n", PC, opcode);
#endif
		PCL++;
		inst_cycles = op_map[opcode].cycles;
		(*(op_map[opcode].function))();
		ALPHA8201_ICount -= inst_cycles;
	} while (ALPHA8201_ICount>0);

	return cycles - ALPHA8201_ICount;
}

#if (HAS_ALPHA8201)
static int ALPHA8201_execute(int cycles) { return alpha8xxx_execute(opcode_8201,cycles); }
#endif

#if (HAS_ALPHA8301)
static int ALPHA8301_execute(int cycles) { return alpha8xxx_execute(opcode_8301,cycles); }
#endif

/****************************************************************************
 * Get all registers in given buffer
 ****************************************************************************/
static void ALPHA8201_get_context (void *dst)
{
	if( dst )
		*(ALPHA8201_Regs*)dst = R;
}

/****************************************************************************
 * Set all registers to given values
 ****************************************************************************/
static void ALPHA8201_set_context (void *src)
{
	if( src )
		R = *(ALPHA8201_Regs*)src;
}

static offs_t ALPHA8201_dasm(char *buffer, offs_t pc)
{
#ifdef	MAME_DEBUG
	return Dasm8201(buffer,pc);
#else
	sprintf( buffer, "$%02X", cpu_readop(pc) );
	return 1;
#endif
}

/****************************************************************************
 * Set IRQ line state
 ****************************************************************************/
static void set_irq_line(int irqline, int state)
{
#if HANDLE_HALT_LINE
	if(irqline == INPUT_LINE_HALT)
	{
		R.halt = (state==ASSERT_LINE) ? 1 : 0;
/* printf("ALPHA8201 HALT %d\n",R.halt); */
		change_pc(PC);
	}
#endif
}

/**************************************************************************
 * Generic set_info
 **************************************************************************/

static void ALPHA8201_set_info(UINT32 state, union cpuinfo *info)
{
	switch (state)
	{
#if HANDLE_HALT_LINE
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_HALT:	set_irq_line(INPUT_LINE_HALT, info->i);	break;
#endif
		case CPUINFO_INT_PC:
		case CPUINFO_INT_REGISTER + ALPHA8201_PC:			PC = info->i;							break;
		case CPUINFO_INT_SP:
		case CPUINFO_INT_REGISTER + ALPHA8201_SP:			M_WRMEM(0x001,info->i);					break;
		case CPUINFO_INT_REGISTER + ALPHA8201_RB:			regPTR = (info->i & 7)<<3;				break;
		case CPUINFO_INT_REGISTER + ALPHA8201_MB:			R.mb = info->i & 0x03;					break;
#if 0
		case CPUINFO_INT_REGISTER + ALPHA8201_ZF:			R.zf= info->i & 0x01;					break;
		case CPUINFO_INT_REGISTER + ALPHA8201_CF:			R.cf= info->i & 0x01;					break;
#endif
		case CPUINFO_INT_REGISTER + ALPHA8201_IX0:			IX0 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_IX1:			IX1 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_IX2:			IX2 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_LP0:			LP0 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_LP1:			LP1 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_LP2:			LP2 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_A:			R.A = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_B:			R.B = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R0:			R0 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R1:			R1 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R2:			R2 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R3:			R3 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R4:			R4 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R5:			R5 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R6:			R6 = info->i;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R7:			R7 = info->i;							break;
	}
}



/**************************************************************************
 * Generic get_info
 **************************************************************************/

/* 8201 and 8301 */
static void alpha8xxx_get_info(UINT32 state, union cpuinfo *info)
{
	switch (state)
	{
		/* --- the following bits of info are returned as 64-bit signed integers --- */
		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(R);					break;
		case CPUINFO_INT_INPUT_LINES:					info->i = 0;							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 = 1;							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 = 16;							break;

		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 8;					break;
		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 10;					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 = 6;					break;
		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
#if HANDLE_HALT_LINE
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_HALT:		info->i = R.halt ? ASSERT_LINE : CLEAR_LINE; break;
#endif
		case CPUINFO_INT_PREVIOUSPC:						info->i = R.PREVPC;						break;
		case CPUINFO_INT_PC:
		case CPUINFO_INT_REGISTER + ALPHA8201_PC:			info->i = PC & 0x3ff;					break;
		case CPUINFO_INT_SP:
		case CPUINFO_INT_REGISTER + ALPHA8201_SP:			info->i = M_RDMEM(0x001);				break;
		case CPUINFO_INT_REGISTER + ALPHA8201_RB:			info->i = regPTR;						break;
		case CPUINFO_INT_REGISTER + ALPHA8201_MB:			info->i = R.mb;						break;
		case CPUINFO_INT_REGISTER + ALPHA8201_ZF:			info->i = ZF;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_CF:			info->i = CF;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_IX0:			info->i = IX0;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_IX1:			info->i = IX1;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_IX2:			info->i = IX2;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_LP0:			info->i = LP0;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_LP1:			info->i = LP1;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_LP2:			info->i = LP2;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_A:			info->i = R.A;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_B:			info->i = R.B;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R0:			info->i = R0;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R1:			info->i = R1;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R2:			info->i = R2;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R3:			info->i = R3;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R4:			info->i = R4;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R5:			info->i = R5;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R6:			info->i = R6;							break;
		case CPUINFO_INT_REGISTER + ALPHA8201_R7:			info->i = R7;							break;

		/* --- the following bits of info are returned as pointers to data or functions --- */
		case CPUINFO_PTR_SET_INFO:						info->setinfo = ALPHA8201_set_info;		break;
		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = ALPHA8201_get_context;	break;
		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = ALPHA8201_set_context;	break;
		case CPUINFO_PTR_INIT:							info->init = ALPHA8201_init;				break;
		case CPUINFO_PTR_RESET:							info->reset = ALPHA8201_reset;				break;
		case CPUINFO_PTR_EXIT:							info->exit = ALPHA8201_exit;				break;
		case CPUINFO_PTR_EXECUTE:						info->execute = ALPHA8201_execute;			break;
		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = ALPHA8201_dasm;			break;
		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &ALPHA8201_ICount;			break;
		case CPUINFO_PTR_REGISTER_LAYOUT:				info->p = ALPHA8201_reg_layout;				break;
		case CPUINFO_PTR_WINDOW_LAYOUT:					info->p = ALPHA8201_win_layout;				break;

		/* --- the following bits of info are returned as NULL-terminated strings --- */
		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s = cpuintrf_temp_str(), "AlphaDenshi MCU"); break;
		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s = cpuintrf_temp_str(), "0.1"); break;
		case CPUINFO_STR_CORE_FILE:						strcpy(info->s = cpuintrf_temp_str(), __FILE__); break;
		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s = cpuintrf_temp_str(), "Copyright (C) 2006 by Tatsuyuki Satoh"); break;
		case CPUINFO_STR_FLAGS:							sprintf(info->s = cpuintrf_temp_str(), "%c%c", CF?'C':'.',ZF?'Z':'.'); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_PC:		sprintf(info->s = cpuintrf_temp_str(), "PC:%03X", PC); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_SP:		sprintf(info->s = cpuintrf_temp_str(), "SP:%02X", M_RDMEM(0x001) ); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_RB:		sprintf(info->s = cpuintrf_temp_str(), "RB:%02X", regPTR>>3); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_MB:		sprintf(info->s = cpuintrf_temp_str(), "MB:%X", R.mb); break;
#if 0
		case CPUINFO_STR_REGISTER + ALPHA8201_ZF:		sprintf(info->s = cpuintrf_temp_str(), "ZF:%X", R.zf); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_CF:		sprintf(info->s = cpuintrf_temp_str(), "CF:%X", R.cf); break;
#endif
		case CPUINFO_STR_REGISTER + ALPHA8201_IX0:		sprintf(info->s = cpuintrf_temp_str(), "IX0:%02X", IX0); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_IX1:		sprintf(info->s = cpuintrf_temp_str(), "IX1:%02X", IX1); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_IX2:		sprintf(info->s = cpuintrf_temp_str(), "IX2:%02X", IX2); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_LP0:		sprintf(info->s = cpuintrf_temp_str(), "LP0:%02X", LP0); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_LP1:		sprintf(info->s = cpuintrf_temp_str(), "LP1:%02X", LP1); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_LP2:		sprintf(info->s = cpuintrf_temp_str(), "LP2:%02X", LP2); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_A:		sprintf(info->s = cpuintrf_temp_str(), "A:%02X", R.A); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_B:		sprintf(info->s = cpuintrf_temp_str(), "B:%02X", R.B); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R0:		sprintf(info->s = cpuintrf_temp_str(), "R0:%02X", R0); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R1:		sprintf(info->s = cpuintrf_temp_str(), "R1:%02X", R1); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R2:		sprintf(info->s = cpuintrf_temp_str(), "R2:%02X", R2); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R3:		sprintf(info->s = cpuintrf_temp_str(), "R3:%02X", R3); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R4:		sprintf(info->s = cpuintrf_temp_str(), "R4:%02X", R4); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R5:		sprintf(info->s = cpuintrf_temp_str(), "R5:%02X", R5); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R6:		sprintf(info->s = cpuintrf_temp_str(), "R6:%02X", R6); break;
		case CPUINFO_STR_REGISTER + ALPHA8201_R7:		sprintf(info->s = cpuintrf_temp_str(), "R7:%02X", R7); break;
	}
}
#if (HAS_ALPHA8201)
void alpha8201_get_info(UINT32 state, union cpuinfo *info)
{
	switch (state)
	{
	case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "ALPHA-8201");	break;
	case CPUINFO_PTR_EXECUTE:						info->execute = ALPHA8201_execute;						break;
	default:
		/* 8201 / 8301 */
		alpha8xxx_get_info(state,info);
	}
}
#endif

#if (HAS_ALPHA8301)
void alpha8301_get_info(UINT32 state, union cpuinfo *info)
{
	switch (state)
	{
	case CPUINFO_STR_NAME:							strcpy(info->s = cpuintrf_temp_str(), "ALPHA-8301");	break;
	case CPUINFO_PTR_EXECUTE:						info->execute = ALPHA8301_execute;						break;
	default:
		/* 8201 / 8301 */
		alpha8xxx_get_info(state,info);
	}
}
#endif
