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

    Toshiba TLCS-90 Series MCU's

    emulation by Luca Elia, based on the Z80 core by Juergen Buchmueller

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

#include "burnint.h"
#include "tlcs90_intf.h"
#include <stddef.h>

#define T90_IOBASE	0xffc0

typedef void (*timer_callback)(INT32);

extern UINT8 tlcs90_program_read_byte(UINT32 address);
extern void tlcs90_program_write_byte(UINT32 address, UINT8 data);
extern UINT8 tlcs90_io_read_byte(UINT16 port);
extern void tlcs90_io_write_byte(UINT16 port, UINT8 data);

enum e_ir
{
	T90_P0=T90_IOBASE,  T90_P1,     T90_P01CR_IRFL, T90_IRFH,   T90_P2,     T90_P2CR,   T90_P3,     T90_P3CR,
	T90_P4,             T90_P4CR,   T90_P5,         T90_SMMOD,  T90_P6,     T90_P7,     T90_P67CR,  T90_SMCR,
	T90_P8,             T90_P8CR,   T90_WDMOD,      T90_WDCR,   T90_TREG0,  T90_TREG1,  T90_TREG2,  T90_TREG3,
	T90_TCLK,           T90_TFFCR,  T90_TMOD,       T90_TRUN,   T90_CAP1L,  T90_CAP1H,  T90_CAP2L,  T90_CAL2H,
	T90_TREG4L,         T90_TREG4H, T90_TREG5L,     T90_TREG5H, T90_T4MOD,  T90_T4FFCR, T90_INTEL,  T90_INTEH,
	T90_DMAEH,          T90_SCMOD,  T90_SCCR,       T90_SCBUF,  T90_BX,     T90_BY,     T90_ADREG,  T90_ADMOD
};

#ifdef INLINE
 #undef INLINE
#endif
#define INLINE	static

enum _e_op {    UNKNOWN,    NOP,    EX,     EXX,    LD,     LDW,    LDA,    LDI,    LDIR,   LDD,    LDDR,   CPI,    CPIR,   CPD,    CPDR,   PUSH,   POP,    JP,     JR,     CALL,   CALLR,      RET,    RETI,   HALT,   DI,     EI,     SWI,    DAA,    CPL,    NEG,    LDAR,   RCF,    SCF,    CCF,    TSET,   BIT,    SET,    RES,    INC,    DEC,    INCX,   DECX,   INCW,   DECW,   ADD,    ADC,    SUB,    SBC,    AND,    XOR,    OR,     CP,     RLC,    RRC,    RL,     RR,     SLA,    SRA,    SLL,    SRL,    RLD,    RRD,    DJNZ,   MUL,    DIV     };
typedef UINT8 e_op;
static const char *const op_names[] =   {   "??",       "nop",  "ex",   "exx",  "ld",   "ldw",  "lda",  "ldi",  "ldir", "ldd",  "lddr", "cpi",  "cpir", "cpd",  "cpdr", "push", "pop",  "jp",   "jr",   "call", "callr",    "ret",  "reti", "halt", "di",   "ei",   "swi",  "daa",  "cpl",  "neg",  "ldar", "rcf",  "scf",  "ccf",  "tset", "bit",  "set",  "res",  "inc",  "dec",  "incx", "decx", "incw", "decw", "add",  "adc",  "sub",  "sbc",  "and",  "xor",  "or",   "cp",   "rlc",  "rrc",  "rl",   "rr",   "sla",  "sra",  "sll",  "srl",  "rld",  "rrd",  "djnz", "mul",  "div"   };

enum e_mode {
	MODE_NONE,  MODE_BIT8,  MODE_CC,
	MODE_I8,    MODE_D8,    MODE_R8,
	MODE_I16,   MODE_D16,   MODE_R16,
	MODE_MI16,  MODE_MR16,  MODE_MR16D8,    MODE_MR16R8,
	MODE_R16D8, MODE_R16R8
};

typedef UINT16 e_r;

struct t90_Regs
{
	PAIR        prvpc,pc,sp,af,bc,de,hl,ix,iy;
	PAIR        af2,bc2,de2,hl2;
	UINT8       halt, after_EI;
	UINT16      irq_state, irq_mask;

	INT32       icount;
	INT32       extra_cycles;       // extra cycles for interrupts
	UINT8       internal_registers[48];
	UINT32      ixbase,iybase;

	// Timers: 4 x 8-bit + 1 x 16-bit
	INT32       timer_enable[4+1];
	double      timer_periods[4+1];
	double      timer_periods_full[4+1];

	UINT8       timer_value[4];
	UINT16      timer4_value;
	double      timer_period;

	// Work registers
	e_op        op;

	e_mode      mode1;
	e_r         r1,r1b;

	e_mode      mode2;
	e_r         r2,r2b;

	INT32       cyc_t,cyc_f;

	UINT32      addr;

	UINT32	    total_cycles;
	INT32       nCycles;
	INT32       run_end;

	timer_callback	timer_cb[4+1];
};

static struct t90_Regs tlcs90_data[1];

enum    {
		T90_B,  T90_C,  T90_D,  T90_E,  T90_H,  T90_L,  T90_A,
		T90_BC, T90_DE, T90_HL, T90_XX, T90_IX, T90_IY, T90_SP,
		T90_AF, T90_PC
};

// Regs

#define B   0
#define C   1
#define D   2
#define E   3
#define H   4
#define L   5
#define A   6

#define BC  0
#define DE  1
#define HL  2
//          3
#define IX  4
#define IY  5
#define SP  6

#define AF  7
#define AF2 8
#define PC  9

#define F   cpustate->af.b.l

static const char *const r8_names[] =   {   "b",    "c",    "d",    "e",    "h",    "l",    "a"                             };
static const char *const r16_names[]    =   {   "bc",   "de",   "hl",   "??",   "ix",   "iy",   "sp",   "af",   "af'",  "pc"    };

// Condition Codes

#define FLS 0x0
#define LT  0x1
#define LE  0x2
#define ULE 0x3
#define OV  0x4
#define PE  0x4
#define MI  0x5
#define Z   0x6
#define EQ  0x6
#define CR  0x7
#define ULT 0x7
#define T   0x8
#define GE  0x9
#define GT  0xa
#define UGT 0xb
#define NOV 0xc
#define PO  0xc
#define PL  0xd
#define NZ  0xe
#define NE  0xe
#define NC  0xf
#define UGE 0xf

#define CF  0x01
#define NF  0x02
#define PF  0x04
#define VF  PF
#define XCF 0x08
#define HF  0x10
#define IF  0x20
#define ZF  0x40
#define SF  0x80

static UINT8 SZ[256];       /* zero and sign flags */
static UINT8 SZ_BIT[256];   /* zero, sign and parity/overflow (=zero) flags for BIT opcode */
static UINT8 SZP[256];      /* zero, sign and parity flags */
static UINT8 SZHV_inc[256]; /* zero, sign, half carry and overflow flags INC r8 */
static UINT8 SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r8 */

static const char *const cc_names[] =   {   "f",    "lt",   "le",   "ule",  "ov",   "mi",   "z",    "c",    "",     "ge",   "gt",   "ugt",  "nov",  "pl",   "nz",   "nc"    };

// Opcodes

#define OP_16 0x80


#define OP(   X,CT )        cpustate->op = X;       cpustate->cyc_t = (CT*2);
#define OP16( X,CT )        OP( (X)|OP_16,CT )

#define OPCC(   X,CF,CT )   OP( X, CT ) cpustate->cyc_f = (CF*2);
#define OPCC16( X,CF,CT )   OPCC( (X)|OP_16,CF,CT )

#define BIT8( N,I )         cpustate->mode##N = MODE_BIT8;  cpustate->r##N = I;
#define I8( N,I )           cpustate->mode##N = MODE_I8;        cpustate->r##N = I;
#define D8( N,I )           cpustate->mode##N = MODE_D8;        cpustate->r##N = I;
#define I16( N,I )          cpustate->mode##N = MODE_I16;       cpustate->r##N = I;
#define D16( N,I )          cpustate->mode##N = MODE_D16;       cpustate->r##N = I;
#define R8( N,R )           cpustate->mode##N = MODE_R8;        cpustate->r##N = R;
#define R16( N,R )          cpustate->mode##N = MODE_R16;       cpustate->r##N = R;
#define Q16( N,R )          cpustate->mode##N = MODE_R16;       cpustate->r##N = R; if (cpustate->r##N == SP) cpustate->r##N = AF;
#define MI16( N,I )         cpustate->mode##N = MODE_MI16;  cpustate->r##N = I;
#define MR16( N,R )         cpustate->mode##N = MODE_MR16;  cpustate->r##N = R;
#define MR16D8( N,R,I )     cpustate->mode##N = MODE_MR16D8;    cpustate->r##N = R; cpustate->r##N##b = I;
#define MR16R8( N,R,g )     cpustate->mode##N = MODE_MR16R8;    cpustate->r##N = R; cpustate->r##N##b = g;
#define NONE( N )           cpustate->mode##N = MODE_NONE;
#define CC( N,cc )          cpustate->mode##N = MODE_CC;        cpustate->r##N = cc;
#define R16D8( N,R,I )      cpustate->mode##N = MODE_R16D8; cpustate->r##N = R; cpustate->r##N##b = I;
#define R16R8( N,R,g )      cpustate->mode##N = MODE_R16R8; cpustate->r##N = R; cpustate->r##N##b = g;

INLINE UINT8  RM8 (t90_Regs *, UINT32 a)    { return tlcs90_program_read_byte( a ); }
INLINE UINT16 RM16(t90_Regs *cpustate, UINT32 a)    { return RM8(cpustate,a) | (RM8( cpustate, (a+1) & 0xffff ) << 8); }

INLINE void WM8 (t90_Regs *, UINT32 a, UINT8  v)    { tlcs90_program_write_byte( a, v ); }
INLINE void WM16(t90_Regs *cpustate, UINT32 a, UINT16 v)    { WM8(cpustate,a,v);    WM8( cpustate, (a+1) & 0xffff, v >> 8); }

INLINE UINT8  RX8 (t90_Regs *, UINT32 a, UINT32 base)   { return tlcs90_program_read_byte( base | a ); }
INLINE UINT16 RX16(t90_Regs *cpustate, UINT32 a, UINT32 base)   { return RX8(cpustate,a,base) | (RX8( cpustate, (a+1) & 0xffff, base ) << 8); }

INLINE void WX8 (t90_Regs *, UINT32 a, UINT8  v, UINT32 base)   { tlcs90_program_write_byte( base | a, v ); }
INLINE void WX16(t90_Regs *cpustate, UINT32 a, UINT16 v, UINT32 base)   { WX8(cpustate,a,v,base);   WX8( cpustate, (a+1) & 0xffff, v >> 8, base); }

INLINE UINT8  READ8(t90_Regs *cpustate) { UINT8 b0 = RM8( cpustate, cpustate->addr++ ); cpustate->addr &= 0xffff; return b0; }
INLINE UINT16 READ16(t90_Regs *cpustate)    { UINT8 b0 = READ8(cpustate); return b0 | (READ8(cpustate) << 8); }

static void decode(t90_Regs *cpustate)
{
	UINT8  b0, b1, b2, b3;
	UINT16 imm16;

	b0 = READ8(cpustate);

	switch ( b0 )
	{
		case 0x00:
			OP( NOP,2 )         NONE( 1 )                   NONE( 2 )                       return;     // NOP

		case 0x01:
			OP( HALT,4 )        NONE( 1 )                   NONE( 2 )                       return;     // HALT
		case 0x02:
			OP( DI,2 )          NONE( 1 )                   NONE( 2 )                       return;     // DI
		case 0x03:
			OP( EI,2 )          NONE( 1 )                   NONE( 2 )                       return;     // EI

		case 0x07:
			OPCC( INCX,6,10 )   MI16( 1, 0xFF00|READ8(cpustate) )   NONE( 2 )                       return;     // INCX ($FF00+n)

		case 0x08:
			OP( EX,2 )          R16( 1, DE )                R16( 2, HL )                    return;     // EX DE,HL
		case 0x09:
			OP( EX,2 )          R16( 1, AF )                R16( 2, AF2 )                   return;     // EX AF,AF'
		case 0x0a:
			OP( EXX,2 )         NONE( 1 )                   NONE( 2 )                       return;     // EXX

		case 0x0b:
			OP( DAA,4 )         R8( 1, A )                  NONE( 2 )                       return;     // DAA A

		case 0x0c:
			OP( RCF,2 )         NONE( 1 )                   NONE( 2 )                       return;     // RCF
		case 0x0d:
			OP( SCF,2 )         NONE( 1 )                   NONE( 2 )                       return;     // SCF
		case 0x0e:
			OP( CCF,2 )         NONE( 1 )                   NONE( 2 )                       return;     // CCF

		case 0x0f:
			OPCC( DECX,6,10 )   MI16( 1, 0xFF00|READ8(cpustate) )   NONE( 2 )                       return;     // DECX ($FF00+n)

		case 0x10:
			OP( CPL,2 )         R8( 1, A )                  NONE( 2 )                       return;     // CPL A
		case 0x11:
			OP( NEG,2 )         R8( 1, A )                  NONE( 2 )                       return;     // NEG A

		case 0x12:                                                                                      // MUL HL,n
		case 0x13:                                                                                      // DIV HL,n
			OP( MUL+b0-0x12,16) R16( 1, HL )                I8( 2, READ8(cpustate) )                return;

		case 0x14:  case 0x15:  case 0x16:
			OP16( ADD,6 )       R16( 1, IX+b0-0x14 )        I16( 2, READ16(cpustate) )              return;     // ADD ix,mn

		case 0x17:
			OP( LDAR,8 )        R16( 1, HL )                D16( 2, READ16(cpustate) )              return;     // LDAR HL,+cd

		case 0x18:
			OP( DJNZ,10 )       D8( 1, READ8(cpustate) )            NONE( 2 )                       return;     // DJNZ +d
		case 0x19:
			OP16( DJNZ,10 )     R16( 1, BC )                D8( 2, READ8(cpustate) )                return;     // DJNZ BC,+d

		case 0x1a:
			OPCC( JP,8,8 )      CC( 1, T )                  I16( 2, READ16(cpustate) )              return;     // JP T,mn
		case 0x1b:
			OPCC16( JR,10,10 )  CC( 1, T )                  D16( 2, READ16(cpustate) )              return;     // JR T,+cd

		case 0x1c:
			OPCC( CALL,14,14 )  CC( 1, T )                  I16( 2, READ16(cpustate) )              return;     // CALL T,mn
		case 0x1d:
			OP( CALLR,16 )      D16( 1, READ16(cpustate) )          NONE( 2 )                       return;     // CALLR +cd

		case 0x1e:
			OPCC( RET,10,10 )   CC( 1, T )                  NONE( 2 )                       return;     // RET T
		case 0x1f:
			OP( RETI,14 )       NONE( 1 )                   NONE( 2 )                       return;     // RETI

		case 0x20:  case 0x21:  case 0x22:  case 0x23:  case 0x24:  case 0x25:  case 0x26:
			OP( LD,2 )          R8( 1, A )                  R8( 2, b0 - 0x20 )              return;     // LD A,r

		case 0x27:
			OP( LD,8 )          R8( 1, A )                  MI16( 2, 0xFF00|READ8(cpustate) )       return;     // LD A,($FF00+n)

		case 0x28:  case 0x29:  case 0x2a:  case 0x2b:  case 0x2c:  case 0x2d:  case 0x2e:
			OP( LD,2 )          R8( 1, b0 - 0x28 )          R8( 2, A )                      return;     // LD r,A

		case 0x2f:
			OP( LD,8 )          MI16( 1, 0xFF00|READ8(cpustate) )   R8( 2, A )                      return;     // LD ($FF00+n), A

		case 0x30:  case 0x31:  case 0x32:  case 0x33:  case 0x34:  case 0x35:  case 0x36:
			OP( LD,4 )          R8( 1, b0 - 0x30 )          I8( 2, READ8(cpustate) )                return;     // LD r,n

		case 0x37:
			OP( LD,10 )         MI16( 1, 0xFF00|READ8(cpustate) )   I8( 2, READ8(cpustate) )                return;     // LD ($FF00+w),n

		case 0x38:  case 0x39:  case 0x3a:  /*case 0x3b:*/  case 0x3c:  case 0x3d:  case 0x3e:
			OP16( LD,6 )        R16( 1, b0 - 0x38 )         I16( 2, READ16(cpustate) )              return;     // LD rr,nn

		case 0x3f:
			OP( LDW,14 )        MI16( 1, 0xFF00|READ8(cpustate) )   I16( 2, READ16(cpustate) )              return;     // LDW ($FF00+w),mn

		case 0x40:  case 0x41:  case 0x42:  /*case 0x43:*/  case 0x44:  case 0x45:  case 0x46:
			OP16( LD,4 )        R16( 1, HL )                R16( 2, b0 - 0x40 )             return;     // LD HL,rr

		case 0x47:
			OP16( LD,10 )       R16( 1, HL )                MI16( 2, 0xFF00|READ8(cpustate) )       return;     // LD HL,($FF00+n)

		case 0x48:  case 0x49:  case 0x4a:  /*case 0x4b:*/  case 0x4c:  case 0x4d:  case 0x4e:
			OP16( LD,4 )        R16( 1, b0 - 0x48 )         R16( 2, HL )                    return;     // LD rr,HL

		case 0x4f:
			OP16( LD,10 )       MI16( 1, 0xFF00|READ8(cpustate) )   R16( 2, HL )                    return;     // LD ($FF00+n), HL

		case 0x50:  case 0x51:  case 0x52:  /*case 0x53:*/  case 0x54:  case 0x55:  case 0x56:
			OP( PUSH,8 )        Q16( 1, b0 - 0x50 )         NONE( 2 )                       return;     // PUSH qq
		case 0x58:  case 0x59:  case 0x5a:  /*case 0x5b:*/  case 0x5c:  case 0x5d:  case 0x5e:
			OP( POP,10 )        Q16( 1, b0 - 0x58 )         NONE( 2 )                       return;     // POP qq

		case 0x60:                                                                                      // ADD A,($FF00+n)
		case 0x61:                                                                                      // ADC A,($FF00+n)
		case 0x62:                                                                                      // SUB A,($FF00+n)
		case 0x63:                                                                                      // SBC A,($FF00+n)
		case 0x64:                                                                                      // AND A,($FF00+n)
		case 0x65:                                                                                      // XOR A,($FF00+n)
		case 0x66:                                                                                      // OR  A,($FF00+n)
		case 0x67:                                                                                      // CP  A,($FF00+n)
			OP( ADD+b0-0x60,8 ) R8( 1, A )                  MI16( 2, 0xFF00|READ8(cpustate) )       return;

		case 0x68:                                                                                      // ADD A,n
		case 0x69:                                                                                      // ADC A,n
		case 0x6a:                                                                                      // SUB A,n
		case 0x6b:                                                                                      // SBC A,n
		case 0x6c:                                                                                      // AND A,n
		case 0x6d:                                                                                      // XOR A,n
		case 0x6e:                                                                                      // OR  A,n
		case 0x6f:                                                                                      // CP  A,n
			OP( ADD+b0-0x68,4 ) R8( 1, A )                  I8( 2, READ8(cpustate) )                return;

		case 0x70:                                                                                      // ADD HL,($FF00+n)
		case 0x71:                                                                                      // ADC HL,($FF00+n)
		case 0x72:                                                                                      // SUB HL,($FF00+n)
		case 0x73:                                                                                      // SBC HL,($FF00+n)
		case 0x74:                                                                                      // AND HL,($FF00+n)
		case 0x75:                                                                                      // XOR HL,($FF00+n)
		case 0x76:                                                                                      // OR  HL,($FF00+n)
		case 0x77:                                                                                      // CP  HL,($FF00+n)
			OP16( ADD+b0-0x70,10 )  R16( 1, HL )            MI16( 2, 0xFF00|READ8(cpustate) )       return;

		case 0x78:                                                                                      // ADD HL,mn
		case 0x79:                                                                                      // ADC HL,mn
		case 0x7a:                                                                                      // SUB HL,mn
		case 0x7b:                                                                                      // SBC HL,mn
		case 0x7c:                                                                                      // AND HL,mn
		case 0x7d:                                                                                      // XOR HL,mn
		case 0x7e:                                                                                      // OR  HL,mn
		case 0x7f:                                                                                      // CP  HL,mn
			OP16( ADD+b0-0x78,6 )   R16( 1, HL )            I16( 2, READ16(cpustate) )              return;

		case 0x80:  case 0x81:  case 0x82:  case 0x83:  case 0x84:  case 0x85:  case 0x86:
			OP( INC,2 )         R8( 1, b0 - 0x80 )          NONE( 2 )                       return;     // INC r
		case 0x87:
			OP( INC,10 )        MI16( 1, 0xFF00|READ8(cpustate) )   NONE( 2 )                       return;     // INC ($FF00+n)

		case 0x88:  case 0x89:  case 0x8a:  case 0x8b:  case 0x8c:  case 0x8d:  case 0x8e:
			OP( DEC,2 )         R8( 1, b0 - 0x88 )          NONE( 2 )                       return;     // DEC r
		case 0x8f:
			OP( DEC,10 )        MI16( 1, 0xFF00|READ8(cpustate) )   NONE( 2 )                       return;     // DEC ($FF00+n)

		case 0x90:  case 0x91:  case 0x92:  /*case 0x93:*/  case 0x94:  case 0x95:  case 0x96:
			OP16( INC,4 )       R16( 1, b0 - 0x90 )         NONE( 2 )                       return;     // INC rr
		case 0x97:
			OP( INCW,14 )       MI16( 1, 0xFF00|READ8(cpustate) )   NONE( 2 )                       return;     // INCW ($FF00+n)
		case 0x98:  case 0x99:  case 0x9a:  /*case 0x9b:*/  case 0x9c:  case 0x9d:  case 0x9e:
			OP16( DEC,4 )       R16( 1, b0 - 0x98 )         NONE( 2 )                       return;     // DEC rr
		case 0x9f:
			OP( DECW,14 )       MI16( 1, 0xFF00|READ8(cpustate) )   NONE( 2 )                       return;     // DECW ($FF00+n)

		case 0xa0:                                                                                      // RLC A
		case 0xa1:                                                                                      // RRC A
		case 0xa2:                                                                                      // RL  A
		case 0xa3:                                                                                      // RR  A
		case 0xa4:                                                                                      // SLA A
		case 0xa5:                                                                                      // SRA A
		case 0xa6:                                                                                      // SLL A
		case 0xa7:                                                                                      // SRL A
			OP( RLC+b0-0xa0,2 ) R8( 1, A )                  NONE( 2 )                       return;

		case 0xa8:  case 0xa9:  case 0xaa:  case 0xab:  case 0xac:  case 0xad:  case 0xae:  case 0xaf:
			OP( BIT,8 )         BIT8( 1, b0 - 0xa8 )        MI16( 2, 0xFF00|READ8(cpustate) )       return;     // BIT b,($FF00+n)
		case 0xb0:  case 0xb1:  case 0xb2:  case 0xb3:  case 0xb4:  case 0xb5:  case 0xb6:  case 0xb7:
			OP( RES,12 )        BIT8( 1, b0 - 0xb0 )        MI16( 2, 0xFF00|READ8(cpustate) )       return;     // RES b,($FF00+n)
		case 0xb8:  case 0xb9:  case 0xba:  case 0xbb:  case 0xbc:  case 0xbd:  case 0xbe:  case 0xbf:
			OP( SET,12 )        BIT8( 1, b0 - 0xb8 )        MI16( 2, 0xFF00|READ8(cpustate) )       return;     // SET b,($FF00+n)

		case 0xc0:  case 0xc1:  case 0xc2:  case 0xc3:  case 0xc4:  case 0xc5:  case 0xc6:  case 0xc7:
		case 0xc8:  case 0xc9:  case 0xca:  case 0xcb:  case 0xcc:  case 0xcd:  case 0xce:  case 0xcf:
			OPCC( JR,4,8 )      CC( 1, b0 - 0xc0 )          D8( 2, READ8(cpustate) )                return;     // JR cc,+d

		case 0xe0:  case 0xe1:  case 0xe2:  /*case 0xe3:*/  case 0xe4:  case 0xe5:  case 0xe6:
			b1 = READ8(cpustate);
			switch ( b1 )   {
				case 0x10:                                                                              // RLD (gg)
				case 0x11:                                                                              // RRD (gg)
					OP( RLD+b1-0x10,12 )    MR16( 1, b0 - 0xe0 )    NONE( 2 )               return;

				case 0x12:                                                                              // MUL HL,(gg)
				case 0x13:                                                                              // DIV HL,(gg)
					OP( MUL+b1-0x12,18 )    R16( 1, HL )            MR16( 2, b0 - 0xe0 )    return;

				case 0x14:  case 0x15:  case 0x16:
					OP16( ADD,8 )           R16( 1, IX+b1-0x14 )    MR16( 2, b0 - 0xe0 )    return;     // ADD ix,(gg)

				case 0x28:  case 0x29:  case 0x2a:  case 0x2b:  case 0x2c:  case 0x2d:  case 0x2e:
					OP( LD,6 )              R8( 1, b1 - 0x28 )      MR16( 2, b0 - 0xe0 )    return;     // LD r,(gg)
				case 0x48:  case 0x49:  case 0x4a:  /*case 0x4b:*/  case 0x4c:  case 0x4d:  case 0x4e:
					OP16( LD,8 )            R16( 1, b1 - 0x48 )     MR16( 2, b0 - 0xe0 )    return;     // LD rr,(gg)

				case 0x50:  case 0x51:  case 0x52:  /*case 0x53:*/  case 0x54:  case 0x55:  case 0x56:
					OP( EX,14 )             MR16( 1, b0 - 0xe0 )    R16( 2, b1 - 0x50 )     return;     // EX (gg),rr

				case 0x60:                                                                              // ADD A,(gg)
				case 0x61:                                                                              // ADC A,(gg)
				case 0x62:                                                                              // SUB A,(gg)
				case 0x63:                                                                              // SBC A,(gg)
				case 0x64:                                                                              // AND A,(gg)
				case 0x65:                                                                              // XOR A,(gg)
				case 0x66:                                                                              // OR  A,(gg)
				case 0x67:                                                                              // CP  A,(gg)
					OP( ADD+b1-0x60,6 )     R8( 1, A )              MR16( 2, b0 - 0xe0 )    return;

				case 0x70:                                                                              // ADD HL,(gg)
				case 0x71:                                                                              // ADC HL,(gg)
				case 0x72:                                                                              // SUB HL,(gg)
				case 0x73:                                                                              // SBC HL,(gg)
				case 0x74:                                                                              // AND HL,(gg)
				case 0x75:                                                                              // XOR HL,(gg)
				case 0x76:                                                                              // OR  HL,(gg)
				case 0x77:                                                                              // CP  HL,(gg)
					OP16( ADD+b1-0x70,8 )   R16( 1, HL )            MR16( 2, b0 - 0xe0 )    return;

				case 0x87:
					OP( INC,8 )             MR16( 1, b0 - 0xe0 )    NONE( 2 )               return;     // INC (gg)
				case 0x8f:
					OP( DEC,8 )             MR16( 1, b0 - 0xe0 )    NONE( 2 )               return;     // DEC (gg)

				case 0x97:
					OP( INCW,12 )           MR16( 1, b0 - 0xe0 )    NONE( 2 )               return;     // INCW (gg)
				case 0x9f:
					OP( DECW,12 )           MR16( 1, b0 - 0xe0 )    NONE( 2 )               return;     // DECW (gg)

				case 0xa0:                                                                              // RLC (gg)
				case 0xa1:                                                                              // RRC (gg)
				case 0xa2:                                                                              // RL  (gg)
				case 0xa3:                                                                              // RR  (gg)
				case 0xa4:                                                                              // SLA (gg)
				case 0xa5:                                                                              // SRA (gg)
				case 0xa6:                                                                              // SLL (gg)
				case 0xa7:                                                                              // SRL (gg)
					OP( RLC+b1-0xa0,8 )     MR16( 1, b0 - 0xe0 )    NONE( 2 )               return;

				case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:
					OP( TSET,12 )           BIT8( 1, b1 - 0x18 )    MR16( 2, b0 - 0xe0 )    return;     // TSET b,(gg)
				case 0xa8:  case 0xa9:  case 0xaa:  case 0xab:  case 0xac:  case 0xad:  case 0xae:  case 0xaf:
					OP( BIT,6 )             BIT8( 1, b1 - 0xa8 )    MR16( 2, b0 - 0xe0 )    return;     // BIT b,(gg)
				case 0xb0:  case 0xb1:  case 0xb2:  case 0xb3:  case 0xb4:  case 0xb5:  case 0xb6:  case 0xb7:
					OP( RES,10 )            BIT8( 1, b1 - 0xb0 )    MR16( 2, b0 - 0xe0 )    return;     // RES b,(gg)
				case 0xb8:  case 0xb9:  case 0xba:  case 0xbb:  case 0xbc:  case 0xbd:  case 0xbe:  case 0xbf:
					OP( SET,10 )            BIT8( 1, b1 - 0xb8 )    MR16( 2, b0 - 0xe0 )    return;     // SET b,(gg)
			}   break;
		case 0xe3:
			imm16 = READ16(cpustate);
			b3 = READ8(cpustate);
			switch ( b3 )   {
				case 0x10:                                                                              // RLD (mn)
				case 0x11:                                                                              // RRD (mn)
					OP( RLD+b3-0x10,16 )    MI16( 1, imm16 )        NONE( 2 )               return;

				case 0x12:                                                                              // MUL HL,(mn)
				case 0x13:                                                                              // DIV HL,(mn)
					OP( MUL+b3-0x12,22 )    R16( 1, HL )            MI16( 2, imm16 )        return;

				case 0x14:  case 0x15:  case 0x16:
					OP16( ADD,12 )          R16( 1, IX+b3-0x14 )    MI16( 2, imm16 )        return;     // ADD ix,(mn)

				case 0x28:  case 0x29:  case 0x2a:  case 0x2b:  case 0x2c:  case 0x2d:  case 0x2e:
					OP( LD,10 )             R8( 1, b3 - 0x28 )      MI16( 2, imm16 )        return;     // LD r,(mn)
				case 0x48:  case 0x49:  case 0x4a:  /*case 0x4b:*/  case 0x4c:  case 0x4d:  case 0x4e:
					OP16( LD,12 )           R16( 1, b3 - 0x48 )     MI16( 2, imm16 )        return;     // LD rr,(mn)

				case 0x50:  case 0x51:  case 0x52:  /*case 0x53:*/  case 0x54:  case 0x55:  case 0x56:
					OP( EX,18 )             MI16( 1, imm16 )        R16( 2, b3 - 0x50 )     return;     // EX (mn),rr

				case 0x60:                                                                              // ADD A,(mn)
				case 0x61:                                                                              // ADC A,(mn)
				case 0x62:                                                                              // SUB A,(mn)
				case 0x63:                                                                              // SBC A,(mn)
				case 0x64:                                                                              // AND A,(mn)
				case 0x65:                                                                              // XOR A,(mn)
				case 0x66:                                                                              // OR  A,(mn)
				case 0x67:                                                                              // CP  A,(mn)
					OP( ADD+b3-0x60,10 )    R8( 1, A )              MI16( 2, imm16 )        return;

				case 0x70:                                                                              // ADD HL,(mn)
				case 0x71:                                                                              // ADC HL,(mn)
				case 0x72:                                                                              // SUB HL,(mn)
				case 0x73:                                                                              // SBC HL,(mn)
				case 0x74:                                                                              // AND HL,(mn)
				case 0x75:                                                                              // XOR HL,(mn)
				case 0x76:                                                                              // OR  HL,(mn)
				case 0x77:                                                                              // CP  HL,(mn)
					OP16( ADD+b3-0x70,12 )  R16( 1, HL )            MI16( 2, imm16 )        return;

				case 0x87:
					OP( INC,12 )            MI16( 1, imm16 )        NONE( 2 )               return;     // INC (mn)
				case 0x8f:
					OP( DEC,12 )            MI16( 1, imm16 )        NONE( 2 )               return;     // DEC (mn)

				case 0x97:
					OP( INCW,16 )           MI16( 1, imm16 )        NONE( 2 )               return;     // INCW (mn)
				case 0x9f:
					OP( DECW,16 )           MI16( 1, imm16 )        NONE( 2 )               return;     // DECW (mn)

				case 0xa0:                                                                              // RLC (mn)
				case 0xa1:                                                                              // RRC (mn)
				case 0xa2:                                                                              // RL  (mn)
				case 0xa3:                                                                              // RR  (mn)
				case 0xa4:                                                                              // SLA (mn)
				case 0xa5:                                                                              // SRA (mn)
				case 0xa6:                                                                              // SLL (mn)
				case 0xa7:                                                                              // SRL (mn)
					OP( RLC+b3-0xa0,12 )    MI16( 1, imm16 )        NONE( 2 )               return;

				case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:
					OP( TSET,16 )           BIT8( 1, b3 - 0x18 )    MI16( 2, imm16 )        return;     // TSET b,(mn)
				case 0xa8:  case 0xa9:  case 0xaa:  case 0xab:  case 0xac:  case 0xad:  case 0xae:  case 0xaf:
					OP( BIT,10 )            BIT8( 1, b3 - 0xa8 )    MI16( 2, imm16 )        return;     // BIT b,(mn)
				case 0xb0:  case 0xb1:  case 0xb2:  case 0xb3:  case 0xb4:  case 0xb5:  case 0xb6:  case 0xb7:
					OP( RES,14 )            BIT8( 1, b3 - 0xb0 )    MI16( 2, imm16 )        return;     // RES b,(mn)
				case 0xb8:  case 0xb9:  case 0xba:  case 0xbb:  case 0xbc:  case 0xbd:  case 0xbe:  case 0xbf:
					OP( SET,14 )            BIT8( 1, b3 - 0xb8 )    MI16( 2, imm16 )        return;     // SET b,(mn)
			}   break;

		case 0xe7:
			b1 = READ8(cpustate);
			b2 = READ8(cpustate);
			switch ( b2 )   {
				case 0x10:                                                                              // RLD ($FF00+n)
				case 0x11:                                                                              // RRD ($FF00+n)
					OP( RLD+b2-0x10,14 )    MI16( 1, 0xFF00|b1 )    NONE( 2 )               return;

				case 0x12:                                                                              // MUL HL,($FF00+n)
				case 0x13:                                                                              // DIV HL,($FF00+n)
					OP( MUL+b2-0x12,20 )    R16( 1, HL )            MI16( 2, 0xFF00|b1 )    return;

				case 0x14:  case 0x15:  case 0x16:
					OP16( ADD,10 )          R16( 1, IX+b2-0x14 )    MI16( 2, 0xFF00|b1 )    return;     // ADD ix,($FF00+n)

				case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:
					OP( TSET,14 )           BIT8( 1, b2 - 0x18 )    MI16( 2, 0xFF00|b1 )    return;     // TSET b,($FF00+n)
				case 0x28:  case 0x29:  case 0x2a:  case 0x2b:  case 0x2c:  case 0x2d:  case 0x2e:
					OP( LD,8 )              R8( 1, b2 - 0x28 )      MI16( 2, 0xFF00|b1 )    return;     // LD r,($FF00+n)
				case 0x48:  case 0x49:  case 0x4a:  /*case 0x4b:*/  case 0x4c:  case 0x4d:  case 0x4e:
					OP16( LD,10 )           R16( 1, b2 - 0x48 )     MI16( 2, 0xFF00|b1 )    return;     // LD rr,($FF00+n)

				case 0x50:  case 0x51:  case 0x52:  /*case 0x53:*/  case 0x54:  case 0x55:  case 0x56:
					OP( EX,16 )             MI16( 1, 0xFF00|b1 )    R16( 2, b2 - 0x50 )     return;     // EX ($FF00+n),rr

				case 0xa0:                                                                              // RLC ($FF00+n)
				case 0xa1:                                                                              // RRC ($FF00+n)
				case 0xa2:                                                                              // RL  ($FF00+n)
				case 0xa3:                                                                              // RR  ($FF00+n)
				case 0xa4:                                                                              // SLA ($FF00+n)
				case 0xa5:                                                                              // SRA ($FF00+n)
				case 0xa6:                                                                              // SLL ($FF00+n)
				case 0xa7:                                                                              // SRL ($FF00+n)
					OP( RLC+b2-0xa0,10 )    MI16( 1, 0xFF00|b1 )    NONE( 2 )               return;
			}   break;

		case 0xe8:  case 0xe9:  case 0xea:  /*case 0xeb:*/  case 0xec:  case 0xed:  case 0xee:
			b1 = READ8(cpustate);
			switch ( b1 )   {
				case 0x20:  case 0x21:  case 0x22:  case 0x23:  case 0x24:  case 0x25:  case 0x26:
					OP( LD,6 )              MR16( 1, b0 - 0xe8 )    R8( 2, b1 - 0x20 )      return;     // LD (gg),r
				case 0x37:
					OP( LD,8 )              MR16( 1, b0 - 0xe8 )    I8( 2, READ8(cpustate) )        return;     // LD (gg),n
				case 0x3f:
					OP( LDW,12 )            MR16( 1, b0 - 0xe8 )    I16( 2, READ16(cpustate) )      return;     // LDW (gg),mn
				case 0x40:  case 0x41:  case 0x42:  /*case 0x43:*/  case 0x44:  case 0x45:  case 0x46:
					OP16( LD,8 )            MR16( 1, b0 - 0xe8 )    R16( 2, b1 - 0x40 )     return;     // LD (gg),rr

				case 0x68:                                                                              // ADD (gg),n
				case 0x69:                                                                              // ADC (gg),n
				case 0x6a:                                                                              // SUB (gg),n
				case 0x6b:                                                                              // SBC (gg),n
				case 0x6c:                                                                              // AND (gg),n
				case 0x6d:                                                                              // XOR (gg),n
				case 0x6e:                                                                              // OR  (gg),n
					OP( ADD+b1-0x68,10 )    MR16( 1, b0 - 0xe8 )    I8( 2, READ8(cpustate) )        return;
				case 0x6f:                                                                              // CP  (gg),n
					OP( CP,8 )              MR16( 1, b0 - 0xe8 )    I8( 2, READ8(cpustate) )        return;

				case 0xc0:  case 0xc1:  case 0xc2:  case 0xc3:  case 0xc4:  case 0xc5:  case 0xc6:  case 0xc7:
				case 0xc8:  case 0xc9:  case 0xca:  case 0xcb:  case 0xcc:  case 0xcd:  case 0xce:  case 0xcf:
					OPCC( JP,6,8 )          CC( 1, b1 - 0xc0 )      R16( 2, b0 - 0xe8 )     return;     // JP [cc,]gg
				case 0xd0:  case 0xd1:  case 0xd2:  case 0xd3:  case 0xd4:  case 0xd5:  case 0xd6:  case 0xd7:
				case 0xd8:  case 0xd9:  case 0xda:  case 0xdb:  case 0xdc:  case 0xdd:  case 0xde:  case 0xdf:
					OPCC( CALL,6,14 )       CC( 1, b1 - 0xd0 )      R16( 2, b0 - 0xe8 )     return;     // CALL [cc,]gg
			}   break;
		case 0xeb:
			imm16 = READ16(cpustate);
			b3 = READ8(cpustate);
			switch ( b3 )   {
				case 0x20:  case 0x21:  case 0x22:  case 0x23:  case 0x24:  case 0x25:  case 0x26:
					OP( LD,10 )             MI16( 1, imm16 )        R8( 2, b3 - 0x20 )      return;     // LD (mn),r
				case 0x37:
					OP( LD,12 )             MI16( 1, imm16 )        I8( 2, READ8(cpustate) )        return;     // LD (vw),n
				case 0x3f:
					OP( LDW,16 )            MI16( 1, imm16 )        I16( 2, READ16(cpustate) )      return;     // LDW (vw),mn
				case 0x40:  case 0x41:  case 0x42:  /*case 0x43:*/  case 0x44:  case 0x45:  case 0x46:
					OP16( LD,12 )           MI16( 1, imm16 )        R16( 2, b3 - 0x40 )     return;     // LD (mn),rr

				case 0x68:                                                                              // ADD (vw),n
				case 0x69:                                                                              // ADC (vw),n
				case 0x6a:                                                                              // SUB (vw),n
				case 0x6b:                                                                              // SBC (vw),n
				case 0x6c:                                                                              // AND (vw),n
				case 0x6d:                                                                              // XOR (vw),n
				case 0x6e:                                                                              // OR  (vw),n
					OP( ADD+b3-0x68,14 )    MI16( 1, imm16 )        I8( 2, READ8(cpustate) )        return;
				case 0x6f:                                                                              // CP  (vw),n
					OP( ADD+b3-0x68,12 )    MI16( 1, imm16 )        I8( 2, READ8(cpustate) )        return;

				case 0xc0:  case 0xc1:  case 0xc2:  case 0xc3:  case 0xc4:  case 0xc5:  case 0xc6:  case 0xc7:
				case 0xc8:  case 0xc9:  case 0xca:  case 0xcb:  case 0xcc:  case 0xcd:  case 0xce:  case 0xcf:
					OPCC( JP,10,12 )        CC( 1, b3 - 0xc0 )      I16( 2, imm16 )         return;     // JP cc,mn
				case 0xd0:  case 0xd1:  case 0xd2:  case 0xd3:  case 0xd4:  case 0xd5:  case 0xd6:  case 0xd7:
				case 0xd8:  case 0xd9:  case 0xda:  case 0xdb:  case 0xdc:  case 0xdd:  case 0xde:  case 0xdf:
					OPCC( CALL,10,18 )      CC( 1, b3 - 0xd0 )      I16( 2, imm16 )         return;     // CALL cc,mn
			}   break;

		case 0xef:
			b1 = READ8(cpustate);
			b2 = READ8(cpustate);
			switch ( b2 )   {
				case 0x20:  case 0x21:  case 0x22:  case 0x23:  case 0x24:  case 0x25:  case 0x26:
					OP( LD,8 )              MI16( 1, 0xFF00|b1 )    R8( 2, b2 - 0x20 )      return;     // LD ($FF00+n),r
				case 0x40:  case 0x41:  case 0x42:  /*case 0x43:*/  case 0x44:  case 0x45:  case 0x46:
					OP16( LD,10 )           MI16( 1, 0xFF00|b1 )    R16( 2, b2 - 0x40 )     return;     // LD ($FF00+n),rr

				case 0x68:                                                                              // ADD ($FF00+w),n
				case 0x69:                                                                              // ADC ($FF00+w),n
				case 0x6a:                                                                              // SUB ($FF00+w),n
				case 0x6b:                                                                              // SBC ($FF00+w),n
				case 0x6c:                                                                              // AND ($FF00+w),n
				case 0x6d:                                                                              // XOR ($FF00+w),n
				case 0x6e:                                                                              // OR  ($FF00+w),n
					OP( ADD+b2-0x68,12 )    MI16( 1, 0xFF00|b1 )    I8( 2, READ8(cpustate) )        return;
				case 0x6f:                                                                              // CP  ($FF00+w),n
					OP( ADD+b2-0x68,10 )    MI16( 1, 0xFF00|b1 )    I8( 2, READ8(cpustate) )        return;
			}   break;

		case 0xf0:  case 0xf1:  case 0xf2:
			b1 = READ8(cpustate);
			b2 = READ8(cpustate);
			switch ( b2 )   {
				case 0x10:                                                                              // RLD (ix+d)
				case 0x11:                                                                              // RRD (ix+d)
					OP( RLD+b2-0x10,16 )    MR16D8( 1, IX + b0 - 0xf0, b1 )     NONE( 2 )   return;

				case 0x12:                                                                              // MUL HL,(ix+d)
				case 0x13:                                                                              // DIV HL,(ix+d)
					OP( MUL+b2-0x12,22 )    R16( 1, HL )    MR16D8( 2, IX + b0 - 0xf0, b1 ) return;

				case 0x14:  case 0x15:  case 0x16:
					OP16( ADD,12 )  R16( 1, IX+b2-0x14 )    MR16D8( 2, IX + b0 - 0xf0, b1 ) return;     // ADD ix,(jx+d)

				case 0x28:  case 0x29:  case 0x2a:  case 0x2b:  case 0x2c:  case 0x2d:  case 0x2e:
					OP( LD,10 )     R8( 1, b2 - 0x28 )  MR16D8( 2, IX + b0 - 0xf0, b1 )     return;     // LD r,(ix+d)
				case 0x48:  case 0x49:  case 0x4a:  /*case 0x4b:*/  case 0x4c:  case 0x4d:  case 0x4e:
					OP16( LD,12 )   R16( 1, b2 - 0x48 ) MR16D8( 2, IX + b0 - 0xf0, b1 )     return;     // LD rr,(ix+d)

				case 0x50:  case 0x51:  case 0x52:  /*case 0x53:*/  case 0x54:  case 0x55:  case 0x56:
					OP( EX,18 )     MR16D8( 1, IX + b0 - 0xf0, b1 ) R16( 2, b2 - 0x50 )     return;     // EX (ix+d),rr

				case 0x60:                                                                              // ADD A,(ix+d)
				case 0x61:                                                                              // ADC A,(ix+d)
				case 0x62:                                                                              // SUB A,(ix+d)
				case 0x63:                                                                              // SBC A,(ix+d)
				case 0x64:                                                                              // AND A,(ix+d)
				case 0x65:                                                                              // XOR A,(ix+d)
				case 0x66:                                                                              // OR  A,(ix+d)
				case 0x67:                                                                              // CP  A,(ix+d)
					OP( ADD+b2-0x60,10 )    R8( 1, A )  MR16D8( 2, IX + b0 - 0xf0, b1 )     return;

				case 0x70:                                                                              // ADD HL,(ix+d)
				case 0x71:                                                                              // ADC HL,(ix+d)
				case 0x72:                                                                              // SUB HL,(ix+d)
				case 0x73:                                                                              // SBC HL,(ix+d)
				case 0x74:                                                                              // AND HL,(ix+d)
				case 0x75:                                                                              // XOR HL,(ix+d)
				case 0x76:                                                                              // OR  HL,(ix+d)
				case 0x77:                                                                              // CP  HL,(ix+d)
					OP16( ADD+b2-0x70,12 )  R16( 1, HL )    MR16D8( 2, IX + b0 - 0xf0, b1 ) return;

				case 0x87:
					OP( INC,12 )            MR16D8( 1, IX + b0 - 0xf0, b1 )     NONE( 2 )   return;     // INC (ix+d)
				case 0x8f:
					OP( DEC,12 )            MR16D8( 1, IX + b0 - 0xf0, b1 )     NONE( 2 )   return;     // DEC (ix+d)

				case 0x97:
					OP( INCW,16 )           MR16D8( 1, IX + b0 - 0xf0, b1 )     NONE( 2 )   return;     // INCW (ix+d)
				case 0x9f:
					OP( DECW,16 )           MR16D8( 1, IX + b0 - 0xf0, b1 )     NONE( 2 )   return;     // DECW (ix+d)

				case 0xa0:                                                                              // RLC (ix+d)
				case 0xa1:                                                                              // RRC (ix+d)
				case 0xa2:                                                                              // RL  (ix+d)
				case 0xa3:                                                                              // RR  (ix+d)
				case 0xa4:                                                                              // SLA (ix+d)
				case 0xa5:                                                                              // SRA (ix+d)
				case 0xa6:                                                                              // SLL (ix+d)
				case 0xa7:                                                                              // SRL (ix+d)
					OP( RLC+b2-0xa0,12 )    MR16D8( 1, IX + b0 - 0xf0, b1 )     NONE( 2 )   return;

				case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:
					OP( TSET,16 )   BIT8( 1, b2 - 0x18 )    MR16D8( 2, IX + b0 - 0xf0, b1 ) return;     // TSET b,(ix+d)
				case 0xa8:  case 0xa9:  case 0xaa:  case 0xab:  case 0xac:  case 0xad:  case 0xae:  case 0xaf:
					OP( BIT,10 )    BIT8( 1, b2 - 0xa8 )    MR16D8( 2, IX + b0 - 0xf0, b1 ) return;     // BIT b,(ix+d)
				case 0xb0:  case 0xb1:  case 0xb2:  case 0xb3:  case 0xb4:  case 0xb5:  case 0xb6:  case 0xb7:
					OP( RES,14 )    BIT8( 1, b2 - 0xb0 )    MR16D8( 2, IX + b0 - 0xf0, b1 ) return;     // RES b,(ix+d)
				case 0xb8:  case 0xb9:  case 0xba:  case 0xbb:  case 0xbc:  case 0xbd:  case 0xbe:  case 0xbf:
					OP( SET,14 )    BIT8( 1, b2 - 0xb8 )    MR16D8( 2, IX + b0 - 0xf0, b1 ) return;     // SET b,(ix+d)
			}   break;

		case 0xf3:
			b1 = READ8(cpustate);
			switch ( b1 )   {
				case 0x10:                                                                              // RLD (HL+A)
				case 0x11:                                                                              // RRD (HL+A)
					OP( RLD+b1-0x10,20 )    MR16R8( 1, HL, A )          NONE( 2 )           return;

				case 0x12:                                                                              // MUL HL,(HL+A)
				case 0x13:                                                                              // DIV HL,(HL+A)
					OP( MUL+b1-0x12,26 )    R16( 1, HL )                MR16R8( 2, HL, A )  return;

				case 0x14:  case 0x15:  case 0x16:
					OP16( ADD,16 )          R16( 1, IX+b1-0x14 )        MR16R8( 2, HL, A )  return;     // ADD ix,(HL+A)

				case 0x28:  case 0x29:  case 0x2a:  case 0x2b:  case 0x2c:  case 0x2d:  case 0x2e:
					OP( LD,14 )             R8( 1, b1 - 0x28 )          MR16R8( 2, HL, A )  return;     // LD r,(HL+A)
				case 0x48:  case 0x49:  case 0x4a:  /*case 0x4b:*/  case 0x4c:  case 0x4d:  case 0x4e:
					OP16( LD,16 )           R16( 1, b1 - 0x48 )         MR16R8( 2, HL, A )  return;     // LD rr,(HL+A)

				case 0x50:  case 0x51:  case 0x52:  /*case 0x53:*/  case 0x54:  case 0x55:  case 0x56:
					OP( EX,22 )             MR16R8( 1, HL, A )          R16( 2, b1 - 0x50 ) return;     // EX (HL+A),rr

				case 0x60:                                                                              // ADD A,(HL+A)
				case 0x61:                                                                              // ADC A,(HL+A)
				case 0x62:                                                                              // SUB A,(HL+A)
				case 0x63:                                                                              // SBC A,(HL+A)
				case 0x64:                                                                              // AND A,(HL+A)
				case 0x65:                                                                              // XOR A,(HL+A)
				case 0x66:                                                                              // OR  A,(HL+A)
				case 0x67:                                                                              // CP  A,(HL+A)
					OP( ADD+b1-0x60,14 )    R8( 1, A )                  MR16R8( 2, HL, A )  return;

				case 0x70:                                                                              // ADD HL,(HL+A)
				case 0x71:                                                                              // ADC HL,(HL+A)
				case 0x72:                                                                              // SUB HL,(HL+A)
				case 0x73:                                                                              // SBC HL,(HL+A)
				case 0x74:                                                                              // AND HL,(HL+A)
				case 0x75:                                                                              // XOR HL,(HL+A)
				case 0x76:                                                                              // OR  HL,(HL+A)
				case 0x77:                                                                              // CP  HL,(HL+A)
					OP16( ADD+b1-0x70,16 )  R16( 1, HL )                MR16R8( 2, HL, A )  return;

				case 0x87:
					OP( INC,16 )            MR16R8( 1, HL, A )          NONE( 2 )           return;     // INC (HL+A)
				case 0x8f:
					OP( DEC,16 )            MR16R8( 1, HL, A )          NONE( 2 )           return;     // DEC (HL+A)

				case 0x97:
					OP( INCW,20 )           MR16R8( 1, HL, A )          NONE( 2 )           return;     // INCW (HL+A)
				case 0x9f:
					OP( DECW,20 )           MR16R8( 1, HL, A )          NONE( 2 )           return;     // DECW (HL+A)

				case 0xa0:                                                                              // RLC (HL+A)
				case 0xa1:                                                                              // RRC (HL+A)
				case 0xa2:                                                                              // RL  (HL+A)
				case 0xa3:                                                                              // RR  (HL+A)
				case 0xa4:                                                                              // SLA (HL+A)
				case 0xa5:                                                                              // SRA (HL+A)
				case 0xa6:                                                                              // SLL (HL+A)
				case 0xa7:                                                                              // SRL (HL+A)
					OP( RLC+b1-0xa0,16 )    MR16R8( 1, HL, A )          NONE( 2 )           return;

				case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:
					OP( TSET,20 )           BIT8( 1, b1 - 0x18 )        MR16R8( 2, HL, A )  return;     // TSET b,(HL+A)
				case 0xa8:  case 0xa9:  case 0xaa:  case 0xab:  case 0xac:  case 0xad:  case 0xae:  case 0xaf:
					OP( BIT,14 )            BIT8( 1, b1 - 0xa8 )        MR16R8( 2, HL, A )  return;     // BIT b,(HL+A)
				case 0xb0:  case 0xb1:  case 0xb2:  case 0xb3:  case 0xb4:  case 0xb5:  case 0xb6:  case 0xb7:
					OP( RES,18 )            BIT8( 1, b1 - 0xb0 )        MR16R8( 2, HL, A )  return;     // RES b,(HL+A)
				case 0xb8:  case 0xb9:  case 0xba:  case 0xbb:  case 0xbc:  case 0xbd:  case 0xbe:  case 0xbf:
					OP( SET,18 )            BIT8( 1, b1 - 0xb8 )        MR16R8( 2, HL, A )  return;     // SET b,(HL+A)
			}   break;

		case 0xf4:  case 0xf5:  case 0xf6:
			b1 = READ8(cpustate);
			b2 = READ8(cpustate);
			switch ( b2 )   {
				case 0x20:  case 0x21:  case 0x22:  case 0x23:  case 0x24:  case 0x25:  case 0x26:
					OP( LD,10 )     MR16D8( 1, IX + b0 - 0xf4, b1 ) R8( 2, b2 - 0x20 )      return;     // LD (ix+d),r
				case 0x37:
					OP( LD,12 )     MR16D8( 1, IX + b0 - 0xf4, b1 ) I8( 2, READ8(cpustate) )        return;     // LD (ix+d),n
				case 0x38:  case 0x39:  case 0x3a:  /*case 0x3b:*/  case 0x3c:  case 0x3d:  case 0x3e:
					OP( LDA,10 )    R16( 1, b2 - 0x38 )     R16D8( 2, IX + b0 - 0xf4, b1 )  return;     // LDA rr,ix+d
				case 0x3f:
					OP( LDW,16 )    MR16D8( 1, IX + b0 - 0xf4, b1 ) I16( 2, READ16(cpustate) )      return;     // LDW (ix+d),mn
				case 0x40:  case 0x41:  case 0x42:  /*case 0x43:*/  case 0x44:  case 0x45:  case 0x46:
					OP16( LD,12 )   MR16D8( 1, IX + b0 - 0xf4, b1 ) R16( 2, b2 - 0x40 )     return;     // LD (ix+d),rr

				case 0x68:                                                                              // ADD (ix+d),n
				case 0x69:                                                                              // ADC (ix+d),n
				case 0x6a:                                                                              // SUB (ix+d),n
				case 0x6b:                                                                              // SBC (ix+d),n
				case 0x6c:                                                                              // AND (ix+d),n
				case 0x6d:                                                                              // XOR (ix+d),n
				case 0x6e:                                                                              // OR  (ix+d),n
					OP( ADD+b2-0x68,14) MR16D8( 1, IX + b0 - 0xf4, b1 ) I8( 2, READ8(cpustate) )    return;
				case 0x6f:                                                                              // CP  (ix+d),n
					OP( ADD+b2-0x68,12) MR16D8( 1, IX + b0 - 0xf4, b1 ) I8( 2, READ8(cpustate) )    return;

				case 0xc0:  case 0xc1:  case 0xc2:  case 0xc3:  case 0xc4:  case 0xc5:  case 0xc6:  case 0xc7:
				case 0xc8:  case 0xc9:  case 0xca:  case 0xcb:  case 0xcc:  case 0xcd:  case 0xce:  case 0xcf:
					OPCC( JP,10,12 )    CC( 1, b2 - 0xc0 )  R16D8( 2, IX + b0 - 0xf4, b1 )  return;     // JP [cc,]ix+d
				case 0xd0:  case 0xd1:  case 0xd2:  case 0xd3:  case 0xd4:  case 0xd5:  case 0xd6:  case 0xd7:
				case 0xd8:  case 0xd9:  case 0xda:  case 0xdb:  case 0xdc:  case 0xdd:  case 0xde:  case 0xdf:
					OPCC( CALL,10,18 )  CC( 1, b2 - 0xd0 )  R16D8( 2, IX + b0 - 0xf4, b1 )  return;     // CALL [cc,]ix+d
			}   break;

		case 0xf7:
			b1 = READ8(cpustate);
			switch ( b1 )   {
				case 0x20:  case 0x21:  case 0x22:  case 0x23:  case 0x24:  case 0x25:  case 0x26:
					OP( LD,14 )         MR16R8( 1, HL, A )      R8( 2, b1 - 0x20 )          return;     // LD (HL+A),r
				case 0x37:
					OP( LD,16 )         MR16R8( 1, HL, A )      I8( 2, READ8(cpustate) )            return;     // LD (HL+A),n
				case 0x38:  case 0x39:  case 0x3a:  /*case 0x3b:*/  case 0x3c:  case 0x3d:  case 0x3e:
					OP( LDA,14 )        R16( 1, b1 - 0x38 )     R16R8( 2, HL, A )           return;     // LDA rr,HL+A
				case 0x3f:
					OP( LDW,20 )        MR16R8( 1, HL, A )      I16( 2, READ16(cpustate) )          return;     // LDW (HL+A),mn
				case 0x40:  case 0x41:  case 0x42:  /*case 0x43:*/  case 0x44:  case 0x45:  case 0x46:
					OP16( LD,16 )       MR16R8( 1, HL, A )      R16( 2, b1 - 0x40 )         return;     // LD (HL+A),rr

				case 0x68:                                                                              // ADD (HL+A),n
				case 0x69:                                                                              // ADC (HL+A),n
				case 0x6a:                                                                              // SUB (HL+A),n
				case 0x6b:                                                                              // SBC (HL+A),n
				case 0x6c:                                                                              // AND (HL+A),n
				case 0x6d:                                                                              // XOR (HL+A),n
				case 0x6e:                                                                              // OR  (HL+A),n
					OP( ADD+b1-0x68,18) MR16R8( 1, HL, A )      I8( 2, READ8(cpustate) )            return;
				case 0x6f:                                                                              // CP  (HL+A),n
					OP( ADD+b1-0x68,16) MR16R8( 1, HL, A )      I8( 2, READ8(cpustate) )            return;

				case 0xc0:  case 0xc1:  case 0xc2:  case 0xc3:  case 0xc4:  case 0xc5:  case 0xc6:  case 0xc7:
				case 0xc8:  case 0xc9:  case 0xca:  case 0xcb:  case 0xcc:  case 0xcd:  case 0xce:  case 0xcf:
					OPCC( JP,14,16 )    CC( 1, b1 - 0xc0 )      R16R8( 2, HL, A )           return;     // JP [cc,]HL+A
				case 0xd0:  case 0xd1:  case 0xd2:  case 0xd3:  case 0xd4:  case 0xd5:  case 0xd6:  case 0xd7:
				case 0xd8:  case 0xd9:  case 0xda:  case 0xdb:  case 0xdc:  case 0xdd:  case 0xde:  case 0xdf:
					OPCC( CALL,14,22 )  CC( 1, b1 - 0xd0 )      R16R8( 2, HL, A )           return;     // CALL [cc,]HL+A
			}   break;

		case 0xf8:  case 0xf9:  case 0xfa:  case 0xfb:  case 0xfc:  case 0xfd:  case 0xfe:
			b1 = READ8(cpustate);
			switch ( b1 )   {
				case 0x12:                                                                              // MUL HL,g
				case 0x13:                                                                              // DIV HL,g
					OP( MUL+b1-0x12,18) R16( 1, HL )            R8( 2, b0 - 0xf8 )          return;

				case 0x14:  case 0x15:  case 0x16:
					OP16( ADD,8 )       R16( 1, IX+b1-0x14 )    R16( 2, b0 - 0xf8 )         return;     // ADD ix,gg

				case 0x30:  case 0x31:  case 0x32:  case 0x33:  case 0x34:  case 0x35:  case 0x36:
					OP( LD,4 )          R8( 1, b1 - 0x30 )      R8( 2, b0 - 0xf8 )          return;     // LD r,g
				case 0x38:  case 0x39:  case 0x3a:  /*case 0x3b:*/  case 0x3c:  case 0x3d:  case 0x3e:
					OP16( LD,6 )        R16( 1, b1 - 0x38 )     R16( 2, b0 - 0xf8 )         return;     // LD rr,gg

				case 0x58:                                                                              // LDI
				case 0x59:                                                                              // LDIR
				case 0x5a:                                                                              // LDD
				case 0x5b:                                                                              // LDDR
				case 0x5c:                                                                              // CPI
				case 0x5d:                                                                              // CPIR
				case 0x5e:                                                                              // CPD
				case 0x5f:                                                                              // CPDR
				if (b0 == 0xfe) {
					OPCC( LDI+b1-0x58,14,18 )   NONE( 1 )       NONE( 2 )                   return;
				}

				case 0x60:                                                                              // ADD A,g
				case 0x61:                                                                              // ADC A,g
				case 0x62:                                                                              // SUB A,g
				case 0x63:                                                                              // SBC A,g
				case 0x64:                                                                              // AND A,g
				case 0x65:                                                                              // XOR A,g
				case 0x66:                                                                              // OR  A,g
				case 0x67:                                                                              // CP  A,g
					OP( ADD+b1-0x60,4 ) R8( 1, A )              R8( 2, b0 - 0xf8 )          return;

				case 0x68:                                                                              // ADD g,n
				case 0x69:                                                                              // ADC g,n
				case 0x6a:                                                                              // SUB g,n
				case 0x6b:                                                                              // SBC g,n
				case 0x6c:                                                                              // AND g,n
				case 0x6d:                                                                              // XOR g,n
				case 0x6e:                                                                              // OR  g,n
				case 0x6f:                                                                              // CP  g,n
					OP( ADD+b1-0x68,6 ) R8( 1, b0 - 0xf8 )      I8( 2, READ8(cpustate) )            return;

				case 0x70:                                                                              // ADD HL,gg
				case 0x71:                                                                              // ADC HL,gg
				case 0x72:                                                                              // SUB HL,gg
				case 0x73:                                                                              // SBC HL,gg
				case 0x74:                                                                              // AND HL,gg
				case 0x75:                                                                              // XOR HL,gg
				case 0x76:                                                                              // OR  HL,gg
				case 0x77:                                                                              // CP  HL,gg
					OP16( ADD+b1-0x70,8 )   R16( 1, HL )        R16( 2, b0 - 0xf8 )         return;

				case 0xa0:                                                                              // RLC g
				case 0xa1:                                                                              // RRC g
				case 0xa2:                                                                              // RL  g
				case 0xa3:                                                                              // RR  g
				case 0xa4:                                                                              // SLA g
				case 0xa5:                                                                              // SRA g
				case 0xa6:                                                                              // SLL g
				case 0xa7:                                                                              // SRL g
					OP( RLC+b1-0xa0,4 ) R8( 1, b0 - 0xf8 )      NONE( 2 )                   return;

				case 0x18:  case 0x19:  case 0x1a:  case 0x1b:  case 0x1c:  case 0x1d:  case 0x1e:  case 0x1f:
					OP( TSET,8 )        BIT8( 1, b1 - 0x18 )    R8( 2, b0 - 0xf8 )          return;     // TSET b,g
				case 0xa8:  case 0xa9:  case 0xaa:  case 0xab:  case 0xac:  case 0xad:  case 0xae:  case 0xaf:
					OP( BIT,4 )         BIT8( 1, b1 - 0xa8 )    R8( 2, b0 - 0xf8 )          return;     // BIT b,g
				case 0xb0:  case 0xb1:  case 0xb2:  case 0xb3:  case 0xb4:  case 0xb5:  case 0xb6:  case 0xb7:
					OP( RES,4 )         BIT8( 1, b1 - 0xb0 )    R8( 2, b0 - 0xf8 )          return;     // RES b,g
				case 0xb8:  case 0xb9:  case 0xba:  case 0xbb:  case 0xbc:  case 0xbd:  case 0xbe:  case 0xbf:
					OP( SET,4 )         BIT8( 1, b1 - 0xb8 )    R8( 2, b0 - 0xf8 )          return;     // SET b,g

				case 0xd0:  case 0xd1:  case 0xd2:  case 0xd3:  case 0xd4:  case 0xd5:  case 0xd6:  case 0xd7:
				case 0xd8:  case 0xd9:  case 0xda:  case 0xdb:  case 0xdc:  case 0xdd:  case 0xde:  case 0xdf:
				if (b0 == 0xfe) {
					OPCC( RET,6,14 )    CC( 1, b1 - 0xd0 )      NONE( 2 )                   return;     // RET cc
				}
			}   break;

		case 0xff:
			OP( SWI,20 )                NONE( 1 )               NONE( 2 )                   return;     // SWI
	}

	OP( UNKNOWN,2 )     NONE( 1 )       NONE( 2 )
}

#if 0
static const char *const ir_names[] =   {
	"P0",       "P1",       "P01CR/IRFL",   "IRFH",     "P2",       "P2CR",     "P3",       "P3CR",
	"P4",       "P4CR",     "P5",           "SMMOD",    "P6",       "P7",       "P67CR",    "SMCR",
	"P8",       "P8CR",     "WDMOD",        "WDCR",     "TREG0",    "TREG1",    "TREG2",    "TREG3",
	"TCLK",     "TFFCR",    "TMOD",         "TRUN",     "CAP1L",    "CAP1H",    "CAP2L",    "CAL2H",
	"TREG4L",   "TREG4H",   "TREG5L",       "TREG5H",   "T4MOD",    "T4FFCR",   "INTEL",    "INTEH",
	"DMAEH",    "SCMOD",    "SCCR",         "SCBUF",    "BX",       "BY",       "ADREG",    "ADMOD"
};

static const char *internal_registers_names(UINT16 x)
{
	INT32 ir = x - T90_IOBASE;
	if ( ir >= 0 && ir < sizeof(ir_names)/sizeof(ir_names[0]) )
		return ir_names[ir];
	return NULL;
}
static INT32 sprint_arg(char *buffer, UINT32 pc, const char *pre, const e_mode mode, const e_r r, const e_r rb)
{
	const char *reg_name;
	switch ( mode )
	{
		case MODE_NONE:     return 0;

		case MODE_BIT8:     return  sprintf( buffer, "%s%d",            pre,    r                                   );
		case MODE_I8:       return  sprintf( buffer, "%s$%02X",         pre,    r                                   );
		case MODE_D8:       return  sprintf( buffer, "%s$%04X",         pre,    (pc+2+(r&0x7f)-(r&0x80))&0xffff     );
		case MODE_I16:      return  sprintf( buffer, "%s$%04X",         pre,    r                                   );
		case MODE_D16:      return  sprintf( buffer, "%s$%04X",         pre,    (pc+2+(r&0x7fff)-(r&0x8000))&0xffff );
		case MODE_MI16:
			reg_name = internal_registers_names(r);
			return  (reg_name) ?    sprintf( buffer, "%s(%s)",          pre,    reg_name                            ):
									sprintf( buffer, "%s($%04X)",       pre,    r                                   );
		case MODE_R8:       return  sprintf( buffer, "%s%s",            pre,    r8_names[r]                         );
		case MODE_R16:      return  sprintf( buffer, "%s%s",            pre,    r16_names[r]                        );
		case MODE_MR16:     return  sprintf( buffer, "%s(%s)",          pre,    r16_names[r]                        );

		case MODE_MR16R8:   return  sprintf( buffer, "%s(%s+%s)",       pre,    r16_names[r],   r8_names[rb]        );
		case MODE_MR16D8:   return  sprintf( buffer, "%s(%s%c$%02X)",   pre,    r16_names[r],   (rb&0x80)?'-':'+',  (rb&0x80)?((rb^0xff)+1):rb  );

		case MODE_CC:       return  sprintf( buffer, "%s%s",            pre,    cc_names[r]                         );

		case MODE_R16R8:    return  sprintf( buffer, "%s%s+%s",         pre,    r16_names[r],   r8_names[rb]        );
		case MODE_R16D8:    return  sprintf( buffer, "%s%s%c$%02X",     pre,    r16_names[r],   (rb&0x80)?'-':'+',  (rb&0x80)?((rb^0xff)+1):rb  );

		//default:
		//	fatalerror("%04x: unimplemented addr mode = %d\n",pc,mode);
	}

	return 0;
}

CPU_DISASSEMBLE( t90 )
{
	t90_Regs *cpustate = get_safe_token(device);
	INT32 len;

	cpustate->addr = pc;

	decode(cpustate);
	cpustate->op &= ~OP_16;

	buffer  +=  sprintf     ( buffer,           "%-5s",             op_names[ cpustate->op ] ); // strlen("callr") == 5
	len     =   sprint_arg  ( buffer, pc,       " ",                cpustate->mode1, cpustate->r1, cpustate->r1b );
	buffer  +=  len;
	buffer  +=  sprint_arg  ( buffer, pc,       (len>1)?",":"",     cpustate->mode2, cpustate->r2, cpustate->r2b );

	return (cpustate->addr - pc) | DASMFLAG_SUPPORTED;
}
#endif

INLINE UINT16 r8( t90_Regs *cpustate, const e_r r )
{
	switch( r )
	{
		case A: return cpustate->af.b.h;
		case B: return cpustate->bc.b.h;
		case C: return cpustate->bc.b.l;
		case D: return cpustate->de.b.h;
		case E: return cpustate->de.b.l;
		case H: return cpustate->hl.b.h;
		case L: return cpustate->hl.b.l;

		//default:
		//	fatalerror("%04x: unimplemented r8 register index = %d\n",cpustate->pc.w.l,r);
	}

	return 0;
}

INLINE void w8( t90_Regs *cpustate, const e_r r, UINT16 value )
{
	switch( r )
	{
		case A: cpustate->af.b.h = value;   return;
		case B: cpustate->bc.b.h = value;   return;
		case C: cpustate->bc.b.l = value;   return;
		case D: cpustate->de.b.h = value;   return;
		case E: cpustate->de.b.l = value;   return;
		case H: cpustate->hl.b.h = value;   return;
		case L: cpustate->hl.b.l = value;   return;

		//default:
		//	fatalerror("%04x: unimplemented w8 register index = %d\n",cpustate->pc.w.l,r);
	}
}

INLINE UINT16 r16( t90_Regs *cpustate, const e_r r )
{
	switch( r )
	{
		case BC:    return cpustate->bc.w.l;
		case DE:    return cpustate->de.w.l;
		case HL:    return cpustate->hl.w.l;
		case IX:    return cpustate->ix.w.l;
		case IY:    return cpustate->iy.w.l;
		case SP:    return cpustate->sp.w.l;
		case AF:    return cpustate->af.w.l;
//      case AF2:   return cpustate->af2.w.l;
// one interrupt flip-flop? Needed by e.g. mjifb
		case AF2:   return (cpustate->af2.w.l & (~IF)) | (cpustate->af.w.l & IF);
		case PC:    return cpustate->pc.w.l;

		//default:
		//	fatalerror("%04x: unimplemented r16 register index = %d\n",cpustate->pc.w.l,r);
	}

	return 0;
}

INLINE void w16( t90_Regs *cpustate, const e_r r, UINT16 value )
{
	switch( r )
	{
		case BC:    cpustate->bc.w.l  = value;  return;
		case DE:    cpustate->de.w.l  = value;  return;
		case HL:    cpustate->hl.w.l  = value;  return;
		case IX:    cpustate->ix.w.l  = value;  return;
		case IY:    cpustate->iy.w.l  = value;  return;
		case SP:    cpustate->sp.w.l  = value;  return;
		case AF:    cpustate->af.w.l  = value;  return;
		case AF2:   cpustate->af2.w.l = value;  return;
		case PC:    cpustate->pc.d = value; return;

		//default:
		//	fatalerror("%04x: unimplemented w16 register index = %d\n",cpustate->pc.w.l,r);
	}
}


#define READ_FN( N ) \
INLINE UINT8 Read##N##_8(t90_Regs *cpustate)    { \
	switch ( cpustate->mode##N )    { \
		case MODE_CC: \
		case MODE_BIT8: \
		case MODE_I8:       return (UINT8)cpustate->r##N; \
		case MODE_D8:       return (UINT8)cpustate->r##N; \
		case MODE_R8:       return (UINT8)r8(cpustate, cpustate->r##N); \
		case MODE_MI16:     return RM8(cpustate, cpustate->r##N); \
		case MODE_MR16R8:   return RM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b))); \
		case MODE_MR16: \
			switch( cpustate->r##N ) { \
				case IX:    return RX8(cpustate, cpustate->ix.w.l,cpustate->ixbase); \
				case IY:    return RX8(cpustate, cpustate->iy.w.l,cpustate->iybase); \
			} \
			return RM8(cpustate, r16(cpustate, cpustate->r##N)); \
		case MODE_MR16D8: \
			switch( cpustate->r##N ) { \
				case IX:    return RX8(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),cpustate->ixbase); \
				case IY:    return RX8(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),cpustate->iybase); \
			} \
			return RM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b)); \
		default: \
			printf("%04x: unimplemented Read%d_8 mode = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
	} \
	return 0; \
} \
INLINE UINT16 Read##N##_16(t90_Regs *cpustate)  { \
	switch ( cpustate->mode##N )    { \
		case MODE_I16:      return cpustate->r##N; \
		case MODE_D16:      return cpustate->r##N - 1; \
		case MODE_R16:      return r16(cpustate, cpustate->r##N); \
		case MODE_R16D8:    return r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b; \
		case MODE_R16R8:    return r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b); \
		case MODE_MI16:     return RM16(cpustate, cpustate->r##N); \
		case MODE_MR16R8:   return RM16(cpustate,(UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b))); \
		case MODE_MR16: \
			switch( cpustate->r##N ) { \
				case IX:    return RX16(cpustate, cpustate->ix.w.l,cpustate->ixbase); \
				case IY:    return RX16(cpustate, cpustate->iy.w.l,cpustate->iybase); \
			} \
			return RM16(cpustate,r16(cpustate, cpustate->r##N)); \
		case MODE_MR16D8: \
			switch( cpustate->r##N ) { \
				case IX:    return RX16(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),cpustate->ixbase); \
				case IY:    return RX16(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),cpustate->iybase); \
			} \
			return RM16(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b)); \
		default: \
			printf("%04x: unimplemented Read%d_16 modes = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
	} \
	return 0; \
}



#define WRITE_FN( N ) \
INLINE void Write##N##_8( t90_Regs *cpustate, UINT8 value ) { \
	switch ( cpustate->mode##N )    { \
		case MODE_R8:       w8(cpustate, cpustate->r##N,value);     return; \
		case MODE_MI16:     WM8(cpustate, cpustate->r##N, value);   return; \
		case MODE_MR16R8:   WM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b)), value);  return; \
		case MODE_MR16: \
			switch( cpustate->r##N ) { \
				case IX:    WX8(cpustate, cpustate->ix.w.l,value,cpustate->ixbase); return; \
				case IY:    WX8(cpustate, cpustate->iy.w.l,value,cpustate->iybase); return; \
			} \
			WM8(cpustate, r16(cpustate, cpustate->r##N), value);    return; \
		case MODE_MR16D8: \
			switch( cpustate->r##N ) { \
				case IX:    WX8(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),value,cpustate->ixbase); return; \
				case IY:    WX8(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),value,cpustate->iybase); return; \
			} \
			WM8(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b), value);    return; \
		default: \
			printf("%04x: unimplemented Write%d_8 mode = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
	} \
} \
INLINE void Write##N##_16( t90_Regs *cpustate, UINT16 value ) \
{ \
	switch ( cpustate->mode##N )    { \
		case MODE_R16:      w16(cpustate, cpustate->r##N,value);    return; \
		case MODE_MI16:     WM16(cpustate, cpustate->r##N, value);  return; \
		case MODE_MR16R8:   WM16(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)r8(cpustate, cpustate->r##N##b)), value); return; \
		case MODE_MR16: \
			switch( cpustate->r##N ) { \
				case IX:    WX16(cpustate, cpustate->ix.w.l,value,cpustate->ixbase);    return; \
				case IY:    WX16(cpustate, cpustate->iy.w.l,value,cpustate->iybase);    return; \
			} \
			WM16(cpustate, r16(cpustate, cpustate->r##N), value);   return; \
		case MODE_MR16D8: \
			switch( cpustate->r##N ) { \
				case IX:    WX16(cpustate, (UINT16)(cpustate->ix.w.l + (INT8)cpustate->r##N##b),value,cpustate->ixbase);    return; \
				case IY:    WX16(cpustate, (UINT16)(cpustate->iy.w.l + (INT8)cpustate->r##N##b),value,cpustate->iybase);    return; \
			} \
			WM16(cpustate, (UINT16)(r16(cpustate, cpustate->r##N) + (INT8)cpustate->r##N##b), value);   return; \
		default: \
			printf("%04x: unimplemented Write%d_16 mode = %d\n",cpustate->pc.w.l,N,cpustate->mode##N); \
	} \
}

READ_FN(1)
READ_FN(2)
WRITE_FN(1)
WRITE_FN(2)

INLINE INT32 Test( t90_Regs *cpustate, UINT8 cond )
{
	INT32 s,v;
	switch ( cond )
	{
		case FLS:   return 0;
		case LT:    s = F & SF; v = F & VF; return (s && !v) || (!s && v);
		case LE:    s = F & SF; v = F & VF; return (F & ZF) || (s && !v) || (!s && v);
		case ULE:   return (F & CF) || (F & ZF);
		case OV:    return F & VF;
		case MI:    return F & SF;
		case Z:     return F & ZF;
		case CR:    return F & CF;
		case T:     return 1;
		case GE:    s = F & SF; v = F & VF; return (s && v) || (!s && !v);
		case GT:    s = F & SF; v = F & VF; return !((F & ZF) || (s && !v) || (!s && v));
		case UGT:   return !(F & CF) && !(F & ZF);
		case NOV:   return !(F & VF);
		case PL:    return !(F & SF);
		case NZ:    return !(F & ZF);
		case NC:    return !(F & CF);
		//default:
		//	fatalerror("%04x: unimplemented condition = %d\n",cpustate->pc.w.l,cond);
	}
	return 0;
}

INLINE void Push( t90_Regs *cpustate, e_r rr )
{
	cpustate->sp.w.l -= 2;
	WM16( cpustate, cpustate->sp.w.l, r16(cpustate, rr) );
}
INLINE void Pop( t90_Regs *cpustate, e_r rr )
{
	w16( cpustate, rr, RM16( cpustate, cpustate->sp.w.l ) );
	cpustate->sp.w.l += 2;
}

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

Interrupts

----------------------------------------------------------------------------------------------------------------
Priority    Type            Interrupt Source            Vector/8    Vector  Address         uDMA Address
----------------------------------------------------------------------------------------------------------------
1           Non Maskable    SWI                         -           10      0010            -
2           ""              NMI                         -           18      0018            -
3           ""              INTWD   Watch Dog           -           20      0020            -
4           Maskable        INT0    External 0          05          28      0028            FF28
5           ""              INTT0   Timer 0             06          30      0030            FF30
6           ""              INTT1   Timer 1             07          38      0038            FF38
7           ""              INTAD   A/D                 08          40      0040            FF48
""          ""              INTT2   Timer 2             ""          ""      ""              ""
8           ""              INTT3   Timer 3             09          48      0048            FF48
9           ""              INTT4   Timer 4             0A          50      0050            FF50
10          ""              INT1    External 1          0B          58      0058            FF58
11          ""              INTT5   Timer 5             0C          60      0060            FF60
12          ""              INT2    External 2          0D          68      0068            FF68
13          ""              INTRX   End Serial Receive  0E          70      0070            FF70
14          ""              INTTX   End Serial Transmit 0F          78      0078            FF78

----------------------------------------------------------------------------------------------------------------
Interrupt   Terminal    Mode            How To Set
----------------------------------------------------------------------------------------------------------------
NMI         -           Falling Edge    -
INT0        P80         Level           P8CR<EDGE> = 0
                        Rising Edge     P8CR<EDGE> = 1
INT1        P81         Rising Edge     T4MOD<CAPM1,0> = 0,0 or 0,1 or 1,1
                        Falling Edge    T4MOD<CAPM1,0> = 1,0
INT2        P82         Rising Edge     -

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

enum e_irq {    INTSWI = 0, INTNMI = 1, INTWD = 2,  INT0 = 3,   INTT0 = 4,  INTT1 = 5,  INTT2 = 6,  INTT3 = 7,  INTT4 = 8,  INT1 = 9,   INTT5 = 10,  INT2 = 11,   INTRX = 12,  INTTX = 13,  INTMAX = 14  };
//DECLARE_ENUM_OPERATORS(e_irq)

INLINE void leave_halt(t90_Regs *cpustate)
{
	if( cpustate->halt )
	{
		cpustate->halt = 0;
		cpustate->pc.w.l++;
	}
}

static void take_interrupt(t90_Regs *cpustate, e_irq irq)
{
	cpustate->irq_state &= ~(1 << irq);

	leave_halt(cpustate);

	Push( cpustate, PC );
	Push( cpustate, AF );

	F &= ~IF;

	cpustate->pc.w.l = 0x10 + irq * 8;

	cpustate->extra_cycles += 20*2;
}

static void check_interrupts(t90_Regs *cpustate)
{
	INT32 irq;
	INT32 mask;

	if (!(F & IF))
		return;

	for (irq = INTSWI; irq < INTMAX; irq++)
	{
		mask = (1 << irq);
		if(irq >= INT0) mask &= cpustate->irq_mask;
		if ( cpustate->irq_state & mask )
		{
			take_interrupt( cpustate, (e_irq)irq );
			return;
		}
	}
}

void tlcs90_set_irq_line(INT32 irq, INT32 state)
{
	t90_Regs *cpustate = &tlcs90_data[0];

	if ( ((cpustate->irq_state >> irq)&1) == state ) return;

	if (state)
	{
		cpustate->irq_state |= 1 << irq;
		check_interrupts(cpustate);
	}
	else
	{
		cpustate->irq_state &= ~(1 << irq);
	}
}

void tlcs90SetIRQLine(INT32 line, INT32 state)
{
	// right??
	if (line == 0) line = INT0;
	else if (line == 1) line = INT1;
	else if (line == 2) line = INT2;
	else if (line==0x20)line = INTNMI;

	switch (state)
	{
		case 0: // none
		case 1: // ack
			tlcs90_set_irq_line(line, state);
		break;

		case 2: // auto
			tlcs90_set_irq_line(line, 1);
			tlcs90Run(10);
			tlcs90_set_irq_line(line, 0);
			tlcs90Run(10);
		break;
	}
}

INLINE void Cyc(t90_Regs *cpustate) {   cpustate->icount -= cpustate->cyc_t;    }
INLINE void Cyc_f(t90_Regs *cpustate)   {   cpustate->icount -= cpustate->cyc_f;    }

INT32 tlcs90Run(INT32 nCycles)
{
	t90_Regs *cpustate = &tlcs90_data[0]; //get_safe_token(device);
	UINT8    a8,b8;
	UINT16   a16,b16;
	UINT32 a32;
	PAIR tmp;

	cpustate->icount=nCycles;
	cpustate->nCycles = nCycles + cpustate->extra_cycles;
	if (cpustate->extra_cycles>0) {
		cpustate->icount+=cpustate->extra_cycles;
	}
	cpustate->extra_cycles = 0;

	do
	{
		INT32 prev_cycles = cpustate->icount; // for timers
		cpustate->prvpc.d = cpustate->pc.d;
	//	debugger_instruction_hook(device, cpustate->pc.d);

		check_interrupts(cpustate);

		cpustate->addr = cpustate->pc.d;
		decode(cpustate);
		cpustate->pc.d = cpustate->addr;

		switch ( cpustate->op )
		{
			case NOP:
				Cyc(cpustate);
				break;

			case EX:
				a16 = Read1_16(cpustate);
				Write1_16( cpustate, Read2_16(cpustate) );
				Write2_16( cpustate, a16 );
				Cyc(cpustate);
				break;
			case EXX:
				tmp = cpustate->bc; cpustate->bc = cpustate->bc2;   cpustate->bc2 = tmp;
				tmp = cpustate->de; cpustate->de = cpustate->de2;   cpustate->de2 = tmp;
				tmp = cpustate->hl; cpustate->hl = cpustate->hl2;   cpustate->hl2 = tmp;
				Cyc(cpustate);
				break;

			case LD:
				Write1_8( cpustate, Read2_8(cpustate) );
				Cyc(cpustate);
				break;
			case LDW:
			case LD | OP_16:
				Write1_16( cpustate, Read2_16(cpustate) );
				Cyc(cpustate);
				break;

//          case LDA:
//              Cyc(cpustate);
//              break;

			case LDI:
#define _LDI                                            \
				WM8( cpustate, cpustate->de.w.l, RM8(cpustate, cpustate->hl.w.l) );     \
				cpustate->de.w.l++;                         \
				cpustate->hl.w.l++;                         \
				cpustate->bc.w.l--;                         \
				F &= SF | ZF | IF | XCF | CF;           \
				if ( cpustate->bc.w.l ) F |= VF;

				_LDI
				Cyc(cpustate);
				break;
			case LDIR:
				_LDI
				if ( cpustate->bc.w.l )
				{
					cpustate->pc.w.l -= 2;
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;

			case LDD:
#define _LDD                                            \
				WM8( cpustate, cpustate->de.w.l, RM8(cpustate, cpustate->hl.w.l) );     \
				cpustate->de.w.l--;                         \
				cpustate->hl.w.l--;                         \
				cpustate->bc.w.l--;                         \
				F &= SF | ZF | IF | XCF | CF;           \
				if ( cpustate->bc.w.l ) F |= VF;

				_LDD
				Cyc(cpustate);
				break;
			case LDDR:
				_LDD
				if ( cpustate->bc.w.l )
				{
					cpustate->pc.w.l -= 2;
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;


//          case CPD:
//              Cyc(cpustate);
//              break;
//          case CPDR:
//              Cyc(cpustate);
//              break;
			case CPI:
				a8 = RM8(cpustate, cpustate->hl.w.l);
				b8 = cpustate->af.b.h - a8;
				cpustate->hl.w.l++;
				cpustate->bc.w.l--;
				F = (F & (IF | CF)) | SZ[b8] | ((cpustate->af.b.h^a8^b8)&HF) | NF;
				if ( cpustate->bc.w.l ) F |= VF;
				Cyc(cpustate);
				break;
			case CPIR:
				a8 = RM8(cpustate, cpustate->hl.w.l);
				b8 = cpustate->af.b.h - a8;
				cpustate->hl.w.l++;
				cpustate->bc.w.l--;
				F = (F & (IF | CF)) | SZ[b8] | ((cpustate->af.b.h^a8^b8)&HF) | NF;
				if ( cpustate->bc.w.l )
				{
					F |= VF;
					cpustate->pc.w.l -= 2;
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;

			case PUSH:
				Push( cpustate, cpustate->r1 );
				Cyc(cpustate);
				break;
			case POP:
				Pop( cpustate, cpustate->r1 );
				Cyc(cpustate);
				break;

			case JP:
				if ( Test( cpustate, Read1_8(cpustate) ) )
				{
					cpustate->pc.w.l = Read2_16(cpustate);
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;
			case JR:
				if ( Test( cpustate, Read1_8(cpustate) ) )
				{
					cpustate->pc.w.l += /*2 +*/ (INT8)Read2_8(cpustate);
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;
			case JR | OP_16:
				if ( Test( cpustate, Read1_8(cpustate) ) )
				{
					cpustate->pc.w.l += /*2 +*/ Read2_16(cpustate);
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;


			case CALL:
				if ( Test( cpustate, Read1_8(cpustate) ) )
				{
					Push( cpustate, PC );
					cpustate->pc.w.l = Read2_16(cpustate);
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;
			case CALLR:
				Push( cpustate, PC );
				cpustate->pc.w.l += /*2 +*/ Read1_16(cpustate);
				Cyc(cpustate);
				break;

			case RET:
				if ( Test( cpustate, Read1_8(cpustate) ) )
				{
					Pop( cpustate, PC );
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;
			case RETI:
				Pop( cpustate, AF );
				Pop( cpustate, PC );
				Cyc(cpustate);
				break;

//          case HALT:
//              Cyc(cpustate);
//              break;
			case DI:
				cpustate->after_EI = 0;
				F &= ~IF;
				Cyc(cpustate);
				break;
			case EI:
				cpustate->after_EI = !(F & IF);
				Cyc(cpustate);
				break;

			case SWI:
				Cyc(cpustate);
				take_interrupt( cpustate, INTSWI );
				break;

			case DAA:
			{
				UINT8 cf, nf, hf, lo, hi, diff;
				cf = F & CF;
				nf = F & NF;
				hf = F & HF;
				lo = cpustate->af.b.h & 15;
				hi = cpustate->af.b.h / 16;

				if (cf)
				{
					diff = (lo <= 9 && !hf) ? 0x60 : 0x66;
				}
				else
				{
					if (lo >= 10)
					{
						diff = hi <= 8 ? 0x06 : 0x66;
					}
					else
					{
						if (hi >= 10)
						{
							diff = hf ? 0x66 : 0x60;
						}
						else
						{
							diff = hf ? 0x06 : 0x00;
						}
					}
				}
				if (nf) cpustate->af.b.h -= diff;
				else cpustate->af.b.h += diff;

				F = SZP[A] | (F & (IF | NF));
				if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) F |= XCF | CF;
				if (nf ? hf && lo <= 5 : lo >= 10)  F |= HF;
			}
				Cyc(cpustate);
				break;


			case CPL:
				cpustate->af.b.h ^= 0xff;
				F |= HF | NF;
				Cyc(cpustate);
				break;
			case NEG:
				a8 = 0;
				b8 = cpustate->af.b.h;
				a32 = a8 - b8;
				F = (F & IF) | SZ[(UINT8)a32] | NF;
				if (a32 & 0x100)            F |= CF | XCF;  //X?
				if ((a8 ^ a32 ^ b8) & 0x10) F |= HF;
				if ((b8 ^ a8) & (a8 ^ a32) & 0x80)  F |= VF;
				cpustate->af.b.h = a32;
				Cyc(cpustate);
				break;

			case LDAR:
				cpustate->hl.w.l = cpustate->pc.w.l + /*2 +*/ Read2_16(cpustate);
				Cyc(cpustate);
				break;

			case RCF:
				F &= SF | ZF | IF | VF;
				Cyc(cpustate);
				break;
			case SCF:
				F = (F & (SF | ZF | IF | VF)) | XCF | CF;
				Cyc(cpustate);
				break;
			case CCF:
				F = (F & (SF | ZF | IF | VF)) | ((F & CF)?HF:(XCF | CF));
				Cyc(cpustate);
				break;

//          case TSET:
//              Cyc(cpustate);
//              break;
			case BIT:
				F = (F & (IF | CF)) | HF | SZ_BIT[ Read2_8(cpustate) & (1 << Read1_8(cpustate)) ];
				Cyc(cpustate);
				break;
			case SET:
				Write2_8( cpustate, Read2_8(cpustate) | (1 << Read1_8(cpustate)) );
				Cyc(cpustate);
				break;
			case RES:
				Write2_8( cpustate, Read2_8(cpustate) & (~(1 << Read1_8(cpustate))) );
				Cyc(cpustate);
				break;

			case INC:
				a8 = Read1_8(cpustate) + 1;
				Write1_8( cpustate, a8 );
				F = (F & (IF | CF)) | SZHV_inc[a8];
				if (a8 == 0)    F |= XCF;
				Cyc(cpustate);
				break;
			case INCX:
				if ( F & XCF )
				{
					a8 = Read1_8(cpustate) + 1;
					Write1_8( cpustate, a8 );
					F = (F & (IF | CF)) | SZHV_inc[a8];
					if (a8 == 0)    F |= XCF;
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;
			case INC | OP_16:
				a16 = Read1_16(cpustate) + 1;
				Write1_16( cpustate, a16 );
				if (a16 == 0)   F |=  XCF;
				else            F &= ~XCF;
				Cyc(cpustate);
				break;
			case INCW:
				a16 = Read1_16(cpustate);
				a32 = a16 + 1;
				Write1_16( cpustate, a32 );
				F &= IF | CF;
				if ((UINT16)a32 == 0)   F |= ZF | XCF;
				if (a32 & 0x8000)       F |= SF;
				if ((a16 ^ 0x8000) & a32 & 0x8000)  F |= VF;
				if ((a16 ^ a32 ^ 1) & 0x1000)   F |= HF;    //??
				Cyc(cpustate);
				break;


			case DEC:
				a8 = Read1_8(cpustate) - 1;
				Write1_8( cpustate, a8 );
				F = (F & (IF | CF)) | SZHV_dec[a8];
				if (a8 == 0)    F |= XCF;
				Cyc(cpustate);
				break;
			case DECX:
				if ( F & XCF )
				{
					a8 = Read1_8(cpustate) - 1;
					Write1_8( cpustate, a8 );
					F = (F & (IF | CF)) | SZHV_dec[a8];
					if (a8 == 0)    F |= XCF;
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;
			case DEC | OP_16:
				a16 = Read1_16(cpustate) - 1;
				Write1_16( cpustate, a16 );
				if (a16 == 0)   F |=  XCF;
				else            F &= ~XCF;
				Cyc(cpustate);
				break;
			case DECW:
				a16 = Read1_16(cpustate);
				a32 = a16 - 1;
				Write1_16( cpustate, a32 );
				F = (F & (IF | CF)) | NF;
				if ((UINT16)a32 == 0)   F |= ZF | XCF;
				if (a32 & 0x8000)       F |= SF;
				if (a16 == 0x8000)      F |= VF;
				if ((a16 ^ a32 ^ 1) & 0x1000)   F |= HF;    //??
				Cyc(cpustate);
				break;

			case ADD:
			case ADC:
				a8 = Read1_8(cpustate);
				b8 = Read2_8(cpustate);
				a32 = a8 + b8;
				if ( (cpustate->op == ADC) && (F & CF) )    a32 += 1;
				Write1_8( cpustate, a32 );
				F = (F & IF) | SZ[(UINT8)a32];
				if (a32 & 0x100)            F |= CF | XCF;  //X?
				if ((a8 ^ a32 ^ b8) & 0x10) F |= HF;
				if ((b8 ^ a8 ^ 0x80) & (b8 ^ a32) & 0x80)   F |= VF;
				Cyc(cpustate);
				break;
			case ADD | OP_16:
			case ADC | OP_16:
				a16 = Read1_16(cpustate);
				b16 = Read2_16(cpustate);
				a32 = a16 + b16;
				if ( (cpustate->op == (ADC | OP_16)) && (F & CF) )  a32 += 1;
				Write1_16( cpustate, a32 );
				if ( (cpustate->op == (ADD | OP_16)) && cpustate->mode2 == MODE_R16 )
				{
					F &= SF | ZF | IF | VF;
				}
				else
				{
					F &= IF;
					if ((UINT16)a32 == 0)           F |= ZF;
					if (a32 & 0x8000)               F |= SF;
					if ((b16 ^ a16 ^ 0x8000) & (b16 ^ a32) & 0x8000)    F |= VF;
				}
				if (a32 & 0x10000)              F |= CF | XCF;  //X?
				if ((a16 ^ a32 ^ b16) & 0x1000) F |= HF;    //??
				Cyc(cpustate);
				break;

			case CP:
			case SUB:
			case SBC:
				a8 = Read1_8(cpustate);
				b8 = Read2_8(cpustate);
				a32 = a8 - b8;
				if ( (cpustate->op == SBC) && (F & CF) )    a32 -= 1;
				F = (F & IF) | SZ[(UINT8)a32] | NF;
				if (a32 & 0x100)            F |= CF | XCF;  //X?
				if ((a8 ^ a32 ^ b8) & 0x10) F |= HF;
				if ((b8 ^ a8) & (a8 ^ a32) & 0x80)  F |= VF;
				if (cpustate->op != CP)
					Write1_8( cpustate, a32 );
				Cyc(cpustate);
				break;
			case CP | OP_16:
			case SUB | OP_16:
			case SBC | OP_16:
				a16 = Read1_16(cpustate);
				b16 = Read2_16(cpustate);
				a32 = a16 - b16;
				if ( (cpustate->op == (SBC | OP_16)) && (F & CF) )  a32 -= 1;
				F = (F & IF) | NF;
				if ((UINT16)a32 == 0)           F |= ZF;
				if (a32 & 0x8000)               F |= SF;
				if (a32 & 0x10000)              F |= CF | XCF;  //X?
				if ((a16 ^ a32 ^ b16) & 0x1000) F |= HF;    //??
				if ((b16 ^ a16) & (a16 ^ a32) & 0x8000) F |= VF;
				if (cpustate->op != (CP | OP_16))
					Write1_16( cpustate, a32 );
				Cyc(cpustate);
				break;

			case AND:
				a8 = Read1_8(cpustate) & Read2_8(cpustate);
				Write1_8( cpustate, a8 );
				F = (F & IF) | SZP[a8] | HF;
				Cyc(cpustate);
				break;
			case AND | OP_16:
				a16 = Read1_16(cpustate) & Read2_16(cpustate);
				Write1_16( cpustate, a16 );
				F = (F & IF) | HF;
				if (a16 == 0)       F |= ZF;
				if (a16 & 0x8000)   F |= SF;
				Cyc(cpustate);
				break;
			case XOR:
				a8 = Read1_8(cpustate) ^ Read2_8(cpustate);
				Write1_8( cpustate, a8 );
				F = (F & IF) | SZP[a8];
				Cyc(cpustate);
				break;
			case XOR | OP_16:
				a16 = Read1_16(cpustate) ^ Read2_16(cpustate);
				Write1_16( cpustate, a16 );
				F &= IF;
				if (a16 == 0)       F |= ZF;
				if (a16 & 0x8000)   F |= SF;
				Cyc(cpustate);
				break;
			case OR:
				a8 = Read1_8(cpustate) | Read2_8(cpustate);
				Write1_8( cpustate, a8 );
				F = (F & IF) | SZP[a8];
				Cyc(cpustate);
				break;
			case OR | OP_16:
				a16 = Read1_16(cpustate) | Read2_16(cpustate);
				Write1_16( cpustate, a16 );
				F &= IF;
				if (a16 == 0)       F |= ZF;
				if (a16 & 0x8000)   F |= SF;
				Cyc(cpustate);
				break;

			case RLC:
				a8 = Read1_8(cpustate);
				a8 = (a8 << 1) | (a8 >> 7);
				Write1_8( cpustate, a8 );
				if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A )  F &= SF | ZF | IF | PF;
				else                                F = (F & IF) | SZP[a8];
				if (a8 & 0x01)                      F |= CF | XCF;  // X?
				Cyc(cpustate);
				break;
			case RRC:
				a8 = Read1_8(cpustate);
				a8 = (a8 >> 1) | (a8 << 7);
				Write1_8( cpustate, a8 );
				if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A )  F &= SF | ZF | IF | PF;
				else                                F = (F & IF) | SZP[a8];
				if (a8 & 0x80)                      F |= CF | XCF;  // X?
				Cyc(cpustate);
				break;
			case RL:
				a8 = Read1_8(cpustate);
				b8 = a8 & 0x80;
				a8 <<= 1;
				if (F & CF) a8 |= 0x01;
				Write1_8( cpustate, a8 );
				if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A )  F &= SF | ZF | IF | PF;
				else                                F = (F & IF) | SZP[a8];
				if (b8)                             F |= CF | XCF;  // X?
				Cyc(cpustate);
				break;
			case RR:
				a8 = Read1_8(cpustate);
				b8 = a8 & 0x01;
				a8 >>= 1;
				if (F & CF) a8 |= 0x80;
				Write1_8( cpustate, a8 );
				if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A )  F &= SF | ZF | IF | PF;
				else                                F = (F & IF) | SZP[a8];
				if (b8)                             F |= CF | XCF;  // X?
				Cyc(cpustate);
				break;

			case SLA:
			case SLL:
				a8 = Read1_8(cpustate);
				b8 = a8 & 0x80;
				a8 <<= 1;
				Write1_8( cpustate, a8 );
				if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A )  F &= SF | ZF | IF | PF;
				else                                F = (F & IF) | SZP[a8];
				if (b8)                             F |= CF | XCF;  // X?
				Cyc(cpustate);
				break;
			case SRA:
				a8 = Read1_8(cpustate);
				b8 = a8 & 0x01;
				a8 = (a8 & 0x80) | (a8 >> 1);
				Write1_8( cpustate, a8 );
				if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A )  F &= SF | ZF | IF | PF;
				else                                F = (F & IF) | SZP[a8];
				if (b8)                             F |= CF | XCF;  // X?
				Cyc(cpustate);
				break;
			case SRL:
				a8 = Read1_8(cpustate);
				b8 = a8 & 0x01;
				a8 >>= 1;
				Write1_8( cpustate, a8 );
				if ( cpustate->mode1 == MODE_R8 && cpustate->r1 == A )  F &= SF | ZF | IF | PF;
				else                                F = (F & IF) | SZP[a8];
				if (b8)                             F |= CF | XCF;  // X?
				Cyc(cpustate);
				break;
			case RLD:
				a8 = cpustate->af.b.h;
				b8 = Read1_8(cpustate);
				Write1_8( cpustate, (b8 << 4) | (a8 & 0x0f) );
				a8 = (a8 & 0xf0) | (b8 >> 4);
				F = (F & (IF | CF)) | SZP[a8];
				cpustate->af.b.h = a8;
				Cyc(cpustate);
				break;
			case RRD:
				a8 = cpustate->af.b.h;
				b8 = Read1_8(cpustate);
				Write1_8( cpustate, (b8 >> 4) | (a8 << 4) );
				a8 = (a8 & 0xf0) | (b8 & 0x0f);
				F = (F & (IF | CF)) | SZP[a8];
				cpustate->af.b.h = a8;
				Cyc(cpustate);
				break;

			case DJNZ:
				if ( --cpustate->bc.b.h )
				{
					cpustate->pc.w.l += /*2 +*/ (INT8)Read1_8(cpustate);
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;
			case DJNZ | OP_16:
				if ( --cpustate->bc.w.l )
				{
					cpustate->pc.w.l += /*2 +*/ (INT8)Read2_8(cpustate);
					Cyc(cpustate);
				}
				else    Cyc_f(cpustate);
				break;

			case MUL:
				cpustate->hl.w.l = (UINT16)cpustate->hl.b.l * (UINT16)Read2_8(cpustate);
				Cyc(cpustate);
				break;
			case DIV:
				a16 = cpustate->hl.w.l;
				b16 = (UINT16)Read2_8(cpustate);
				if (b16 == 0)
				{
					F |= VF;
					cpustate->hl.w.l = (a16 << 8) | ((a16 >> 8) ^ 0xff);
				}
				else
				{
					cpustate->hl.b.h = a16 % b16;
					a16 /= b16;
					if (a16 > 0xff) F |=  VF;
					else            F &= ~VF;
					cpustate->hl.b.l = a16;
				}
				Cyc(cpustate);
				break;

			//default:
			//	fatalerror("%04x: unimplemented opcode, op=%02x\n",device->pc(),cpustate->op);
		}

		if ( cpustate->op != EI )
			if (cpustate->after_EI)
			{
				F |= IF;
				cpustate->after_EI = 0;
			}

	
		// timers
		for (INT32 i = 0; i < 5; i++) {
			if (cpustate->timer_enable[i]) {
				cpustate->timer_periods[i] -= (prev_cycles - cpustate->icount);
				if (cpustate->timer_periods[i] <= 0)
				{
					cpustate->timer_cb[i](i);
					cpustate->timer_periods[i] = cpustate->timer_periods_full[i]; // retrigger timer! 
				}
			}
		}

	} while( cpustate->icount > 0 && cpustate->run_end == 0 );

	cpustate->run_end = 0;
	cpustate->total_cycles += nCycles;

	return nCycles;
}

void tlcs90NewFrame()
{
	t90_Regs *cpustate = &tlcs90_data[0];

	cpustate->total_cycles = cpustate->nCycles = cpustate->icount = 0;

//	bprintf (0, _T("NewFrame\n"));
}

void tlcs90RunEnd()
{
	t90_Regs *cpustate = &tlcs90_data[0];

	cpustate->run_end = 1;
}
	

INT32 tlcs90TotalCycles()
{
	t90_Regs *cpustate = &tlcs90_data[0];

//	bprintf (0, _T("TotalCycles: %d\n"), cpustate->total_cycles + (cpustate->nCycles - cpustate->icount));

	return cpustate->total_cycles;// + (cpustate->nCycles - cpustate->icount);
}

INT32 tlcs90Reset()
{
	t90_Regs *cpustate = &tlcs90_data[0]; //get_safe_token(device);
	cpustate->irq_state = 0;
	cpustate->irq_mask = 0;
	cpustate->pc.d = 0x0000;
	F &= ~IF;
/*
    P0/D0-D7 P1/A0-A7 P2/A8-A15 P6 P7 = INPUT
    P35/~RD P36/~WR CLK = 1 (ALWAYS OUTPUTS)
    P4/A16-A19 P83 = 0
    dedicated input ports and CPU registers remain unchanged,
    but PC IFF BX BY = 0, A undefined
*/
	memset(&cpustate->internal_registers, 0, sizeof(cpustate->internal_registers));

	return 0;
}

void tlcs90BurnCycles(INT32 cycles)
{
	t90_Regs *cpustate = &tlcs90_data[0]; //get_safe_token(device);
	cpustate->icount -= 4 * ((cycles + 3) / 4);
}





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


----------------------------------------------------------------------------------------------------------------
FFC0    P0      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     P07-P00 R W     IN      I/O Port 0

----------------------------------------------------------------------------------------------------------------
FFC1    P1      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     P17-P10 R W     IN      I/O Port 1

----------------------------------------------------------------------------------------------------------------
FFC2    P01CR/  R/W     Reset   Description                 * Prohibit Read-Modify-Write *
        IRFL
----------------------------------------------------------------------------------------------------------------
 7      -       -       0       -
 6      IRF0    R       0       INT0    interrupt request (1 = asserted)
 5      IRFT0   R       0       INTT0   ""
 4      IRFT1   R       0       INTT1   ""
 3      -       -       0       -
 2      EXT       W     0       P1/P2 control:  0 = Port                        1 = Address Bus
 1      P1CR      W     0       P1 control:     0 = IN                          1 = OUT     |
 0      P0CR      W     0       P0 control:     0 = IN                          1 = OUT     |
                                                |                                           |
                            Port 0 also functions as  data bus (D0-D7),so           P1: regardless of <P1CR>
                            P0CR is reset when external memory is accessed          P2: only if P2CR is set to 1 (output)
                                                                                    TMP90C841A: always address bus

----------------------------------------------------------------------------------------------------------------
FFC3    IRFH    R/W     Reset   Description                 * Prohibit Read-Modify-Write *
----------------------------------------------------------------------------------------------------------------
 7      IRFT2   R W     0       INTT2   interrupt request (1 = asserted)
 6      IRFT3   R W     0       INTT3   ""
 5      IRFT4   R W     0       INTT4   ""
 4      IRF1    R W     0       INT1    ""
 3      IRFT5   R W     0       INTT5   ""
 2      IRF2    R W     0       INT2    ""
 1      IRFRX   R W     0       INTRX   ""
 0      IRFTX   R W     0       INTTX   ""
                  |__ Writing Vector/8 clears the request flip-flop for that interrupt

----------------------------------------------------------------------------------------------------------------
FFC4    P2      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     P27-P20 R W     IN      I/O Port 2

----------------------------------------------------------------------------------------------------------------
FFC5    P2CR    R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     P27C-     W     0       Port 2 control: 0 = IN                          1 = OUT
        P20C

----------------------------------------------------------------------------------------------------------------
FFC6    P3      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      P37     R       IN      P37 input
 6      P36     R W     1       ~WD
 5      P35     R W     1       ~RD
 4      P34     R       IN      P34 input
 3      P33     R W     1       TxD / P33 output
 2      P32     R W     1       TxD / P32 output
 1      P31     R       IN      RxD / P31 input
 0      P30     R       IN      RxD / P30 input

----------------------------------------------------------------------------------------------------------------
FFC7    P3CR    R/W     Reset   Description             * Prohibit Read-Modify-Write *
----------------------------------------------------------------------------------------------------------------
7-6     WAITC1-0R W     00      Wait control:   00 = 2state     01 = normal     10 = no wait    11 = reserved
 5      RDE     R W     0       RD control:     0 = only external access        1 = always
 4      ODE     R W     0       P33 control:    0 = CMOS                        1 = Open Drain
3-2     TXDC1-0 R W     00      P33-P32:        00 = OUT-OUT    01 = OUT-TxD    10 = TxD-OUT    11 = TxD-~RTS/SCLK
1-0     RXDC1-0 R W     00      P31-P30:        00 = IN-IN      01 = IN-RxD     10 = RxD-IN     11 = not used

----------------------------------------------------------------------------------------------------------------
FFC8    P4      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-4     -
3-0     P43-P40 R W     0       I/O Port 4 bits 3-0 or address bus A16-A19

----------------------------------------------------------------------------------------------------------------
FFC9    P4CR    R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-4     -
3-0     P43C-     W     0       Port 4 control: 0 = OUT                         1 = Address Output
        P40C

----------------------------------------------------------------------------------------------------------------
FFCA    P5      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7       -       R       0       Test bit, must be set to 0
6       -       R       0
5-0     P55-P50 R       0       I/O Port 5 bits 5-0 / AN5-AN0 analog inputs

----------------------------------------------------------------------------------------------------------------
FFCB    SMMOD   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      -       R W     -
 6      SM7M0   R W     0       Motor Step:         0 = Full                        1 = Half
 5      P70C1   R W     0       Port 7 control:     0 = IN-OUT      0 = IN-OUT,TO3  1 = IN / M1     1 = Timer 4
 4      P70C0   R W     0                           0               1               0   Timer 2,3   1
 3      -       R W     -
 2      SM6M0   R W     0       Motor Step:         0 = Full                        1 = Half
 1      P60C1   R W     0       Port 6 control:     0 = IN-OUT      0 = IN-OUT,TO1  1 = IN / M0
 0      P60C0   R W     0                           0               1               X   Timer 0,1

----------------------------------------------------------------------------------------------------------------
FFCC    P6      R/W     Reset   Description             * Read-Modify-Write not available in Stepping Motor control *
----------------------------------------------------------------------------------------------------------------
7-4     SA60-63   W     Undef   Stepping motor Port 0 (M0) Shifter alternate reg.
3-0     P63-P60 R W     IN      Bits 3-0 of I/O Port 6 or Stepping motor Port 0 (M0)

----------------------------------------------------------------------------------------------------------------
FFCD    P7      R/W     Reset   Description             * Read-Modify-Write not available in Stepping Motor control *
----------------------------------------------------------------------------------------------------------------
7-4     SA70-73   W     Undef   Stepping motor Port 1 (M1) Shifter alternate reg.
3-0     P73-P70 R W     IN      Bits 3-0 of I/O Port 7 or Stepping motor Port 1 (M1)

----------------------------------------------------------------------------------------------------------------
FFCE    P67CR   R/W     Reset   Description             * Prohibit Read-Modify-Write *
----------------------------------------------------------------------------------------------------------------
7-4     P73-70C   W     0       Port 7:             0 = IN                          1 = OUT
3-0     P63-60C   W     0       Port 6:             0 = IN                          1 = OUT

----------------------------------------------------------------------------------------------------------------
FFD0    P8      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-4     -
 3      P83     R W     0       P83 / TIO3 / TIO4 output
 2      P82     R       IN      P82 + INT2 input
 1      P81     R       IN      P81 + INT1 input
 0      P80     R       IN      P80 + INT0 input

----------------------------------------------------------------------------------------------------------------
FFD1    P8CR    R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-4     -
 3      P83OC     W     0       P83 out control:    0 = P83                         1 = TO3 / TO4
 2      ZCE2      W     0       INT2/TI5 control:   0 = ZCD disable                 1 = ZCD enable
 1      ZCE1      W     0       INT1/TI4 control:   0 = ZCD disable                 1 = ZCD enable
 0      EDGE      W     0       INT0 control:       0 = Level                       1 = Rising edge

----------------------------------------------------------------------------------------------------------------
FFD2    WDMOD   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      WDTE    R W     1       1 = WDT Enable
 6      WDTP1   R W     0       WDT detection time: 0 = 2^14/fc     0 = 2^16/fc     1 = 2^18/fc     1 = 2^20/fc
 5      WDTP0   R W     0                           0               1               0               1
 4      WARM    R W     0       Warming up time:    0 = 2^14/fc                     1 = 2^16/fc
 3      HALTM1  R W     0       Standby mode:       0 = RUN         0 = STOP        1 = IDLE1       1 = IDLE2
 2      HALTM0  R W     0                           0               1               0               1
 1      EXF     R       Undef   Invert each time EXX instruction is executed
 0      DRIVE   R W     0       1 to drive pins in stop mode

----------------------------------------------------------------------------------------------------------------
FFD4    TREG0   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     -       W       0       Timer 0 match value

----------------------------------------------------------------------------------------------------------------
FFD5    TREG1   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     -       W       0       Timer 0 match value

----------------------------------------------------------------------------------------------------------------
FFD6    TREG2   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     -       W       0       Timer 0 match value

----------------------------------------------------------------------------------------------------------------
FFD7    TREG3   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-0     -       W       0       Timer 0 match value

----------------------------------------------------------------------------------------------------------------
FFD8    TCLK    R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-6     T3CLK1-0R W     00      Timer 3 clock:      00 = Timer 2    01 = clock      10 = clock/16   11 = clock/256  <- Timer 2 overflow output in 16 bit mode
5-4     T2CLK1-0R W     00      Timer 2 clock:      00 = -          01 = clock      10 = clock/16   11 = clock/256
3-2     T1CLK1-0R W     00      Timer 1 clock:      00 = Timer 0    01 = clock      10 = clock/16   11 = clock/256  <- Timer 0 overflow output in 16 bit mode
1-0     T0CLK1-0R W     00      Timer 0 clock:      00 = -          01 = clock      10 = clock/16   11 = clock/256

----------------------------------------------------------------------------------------------------------------
FFD9    TFFCR   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-6     TFF3C1-0  W     -       Timer 3 flip-flop:  00 = Clear      01 = Set        10 = Invert     11 = Don't care <-  Always read as 11
5       TFF3IE  R W     0       Timer 3 Invert:     0 = Disable                     1 = Enable
4       TFF3IS  R W     0       Timer 3 Invert:     0 = Timer 2                     1 = Timer 3
3-2     TFF1C1-0  W     -       Timer 1 Flip-Flop:  00 = Clear      01 = Set        10 = Invert     11 = Don't care <-  Always read as 11
1       TFF1IE  R W     0       Timer 1 Invert:     0 = Disable                     1 = Enable
0       TFF1IS  R W     0       Timer 1 Invert:     0 = Timer 0                     1 = Timer 1

----------------------------------------------------------------------------------------------------------------
FFDA    TMOD    R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-6     T32M1-0 R W     00      Timers 2 & 3:       00 = 8b x 2     01 = 16b(T3+T2) 10 = 8b PPG(T3) 11 = 8b PWM (T3) + 8b (T2)
5-4     PWM21-0 R W     00      Timer 3 PWM freq:   00 = -          01 = 63/fc      10 = 127/fc     11 = 255/fc
3-2     T10M1-0 R W     00      Timers 1 & 0:       00 = 8b x 2     01 = 16b(T1+T0) 10 = 8b PPG(T1) 11 = 8b PWM (T1) + 8b (T0)
1-0     PWM01-0 R W     00      Timer 1 PWM freq:   00 = -          01 = 63/fc      10 = 127/fc     11 = 255/fc

----------------------------------------------------------------------------------------------------------------
FFDB    TRUN    R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
7-6     BRATE1-0R W     00      Serial baud rate:   00 = 300/150    01 = 1200/600   10 = 4800/2400  11 = 19200/9600
 5      PRRUN   R W     0       Prescaler control:  0 = Stop & Clear                1 = Run
 4      T4RUN   R W     0       Timer 4 control:    0 = Stop & Clear                1 = Run
3-0     T4RUN-0 R W     00      Timers 3-0 control: 0 = Stop & Clear                1 = Run

----------------------------------------------------------------------------------------------------------------
FFE6    INTEL   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      DET2    R W     0       INTT2/INTAD interrupt enable flag (1 = enable)
 6      DET3    R W     0       INTT3       ""
 5      DET4    R W     0       INTT4       ""
 4      DE1     R W     0       INT1        ""
 3      DET5    R W     0       INTT5       ""
 2      DE2     R W     0       INT2        ""
 1      DERX    R W     0       INTRX       ""
 0      DETX    R W     0       INTTX       ""

----------------------------------------------------------------------------------------------------------------
FFE7    INTEH   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      -       R W     0       Write "0"
 6      DE0     R W     0       INT0        DMA enable flag (1 = enable)
 5      DET0    R W     0       INTT0       ""
 4      DET1    R W     0       INTT1       ""
 3      ADIS    R W     0       INTT2/INTAD selection (1 = INTAD)
 2      IE0     R W     0       INT0        interrupt enable flag (1 = enable)
 1      IET0    R W     0       INTT0       ""
 0      IET1    R W     0       INTT1       ""

----------------------------------------------------------------------------------------------------------------
FFE8    DMAEH   R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      DET2    R W     0       INTT2/INTAD DMA enable flag (1 = enable)
 6      DET3    R W     0       INTT3       ""
 5      DET4    R W     0       INTT4       ""
 4      DE1     R W     0       INT1        ""
 3      DET5    R W     0       INTT5       ""
 2      DE2     R W     0       INT2        ""
 1      DERX    R W     0       INTRX       ""
 0      DETX    R W     0       INTTX       ""

----------------------------------------------------------------------------------------------------------------
FFEC    BX      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      -       R       1
 6      -       R       1
 5      -       R       1
 4      -       R       1
 3      BX3     R W     0       IX bank register bit 3
 2      BX2     R W     0       IX bank register bit 2
 1      BX1     R w     0       IX bank register bit 1
 0      BX0     R W     0       IX bank register bit 0

----------------------------------------------------------------------------------------------------------------
FFED    BX      R/W     Reset   Description
----------------------------------------------------------------------------------------------------------------
 7      -       R       1
 6      -       R       1
 5      -       R       1
 4      -       R       1
 3      BY3     R W     0       IY bank register bit 3
 2      BY2     R W     0       IY bank register bit 2
 1      BY1     R w     0       IY bank register bit 1
 0      BY0     R W     0       IY bank register bit 0

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

UINT8 t90_internal_registers_r(UINT16 offset)
{
	t90_Regs *cpustate =  &tlcs90_data[0];

	#define RIO     tlcs90_io_read_byte( T90_IOBASE+offset )

	UINT8 data = cpustate->internal_registers[offset];
	switch ( T90_IOBASE + offset )
	{
		case T90_P3:    // 7,4,1,0
			return (data & 0x6c) | (RIO & 0x93);

		case T90_P4:    // only output
			return data & 0x0f;

		case T90_P5:
			return (RIO & 0x3f);

		case T90_P6:
		case T90_P7:
			return (data & 0xf0) | (RIO & 0x0f);

		case T90_P8:    // 2,1,0
			return (data & 0x08) | (RIO & 0x07);

		case T90_BX:
		case T90_BY:
			return 0xf0 | data;
	}
	return data;
}

static void t90_start_timer(t90_Regs *cpustate, INT32 i)
{
	INT32 prescaler;
	double period;

	cpustate->timer_value[i] = 0;

	switch((cpustate->internal_registers[ T90_TMOD - T90_IOBASE ] >> (i * 2)) & 0x03)
	{
		case 0:
			// 8-bit mode
			break;
		case 1:
			break;
		case 2:
		//	logerror("%04X: CPU Timer %d, unsupported PPG mode\n", cpustate->pc.w.l, i);
			return;
		case 3:
		//	logerror("%04X: CPU Timer %d, unsupported PWM mode\n", cpustate->pc.w.l, i);
			return;
	}

	switch((cpustate->internal_registers[ T90_TCLK - T90_IOBASE ] >> (i * 2)) & 0x03)
	{
		case 0:// if (i & 1)  logerror("%04X: CPU Timer %d clocked by Timer %d match signal\n", cpustate->pc.w.l, i,i-1);
			//	else        logerror("%04X: CPU Timer %d, unsupported TCLK = 0\n", cpustate->pc.w.l, i);
				return;
		case 2: prescaler =  16;    break;
		case 3: prescaler = 256;    break;
		default:
		case 1: prescaler =   1;    break;
	}


	period = cpustate->timer_period * prescaler;

	cpustate->timer_periods[i] = cpustate->timer_periods_full[i] = period;
	cpustate->timer_enable[i] = 1;

	//logerror("%04X: CPU Timer %d started at %lf Hz\n", cpustate->pc.w.l, i, 1.0 / period.as_double());
}

static void t90_start_timer4(t90_Regs *cpustate)
{
	INT32 prescaler;
	double period;

	cpustate->timer4_value = 0;

	switch(cpustate->internal_registers[ T90_T4MOD - T90_IOBASE ] & 0x03)
	{
		case 1:     prescaler =   1;    break;
		case 2:     prescaler =  16;    break;
		default:   // logerror("%04X: CPU Timer 4, unsupported T4MOD = %d\n", cpustate->pc.w.l,cpustate->internal_registers[ T90_T4MOD - T90_IOBASE ] & 0x03);
			return;
	}

	period = cpustate->timer_period * prescaler;

	cpustate->timer_periods[4]= cpustate->timer_periods_full[4]  = period;
	cpustate->timer_enable[4] = 1;

//	logerror("%04X: CPU Timer 4 started at %lf Hz\n", cpustate->pc.w.l, 1.0 / period.as_double());
}


static void t90_stop_timer(t90_Regs *cpustate, INT32 i)
{
	cpustate->timer_enable[i] = 0;

//	logerror("%04X: CPU Timer %d stopped\n", cpustate->pc.w.l, i);
}

static void t90_stop_timer4(t90_Regs *cpustate)
{
	t90_stop_timer(cpustate, 4);
}

void t90_timer_callback(INT32 param)
{
	t90_Regs *cpustate =  &tlcs90_data[0];

	INT32 mode, timer_fired;
	INT32 i = param;
	INT32 mask = 0x20 | (1 << i);

	if ( (cpustate->internal_registers[ T90_TRUN - T90_IOBASE ] & mask) != mask )
		return;

	timer_fired = 0;

	mode = (cpustate->internal_registers[ T90_TMOD - T90_IOBASE ] >> ((i & ~1) + 2)) & 0x03;
	// Match
  switch (mode)
  {
    case 0x02: // 8bit PPG
    case 0x03: // 8bit PWM
      //logerror("CPU Timer %d expired with unhandled mode %d\n", i, mode);
      // TODO: hmm...
    case 0x00: // 8bit
      cpustate->timer_value[i]++;
      if ( cpustate->timer_value[i] == cpustate->internal_registers[ T90_TREG0+i - T90_IOBASE ] )
        timer_fired = 1;
      break;

    case 0x01: // 16bit
      if(i & 1)
        break;
      cpustate->timer_value[i]++;
      if(cpustate->timer_value[i] == 0) cpustate->timer_value[i+1]++;
      if(cpustate->timer_value[i+1] == cpustate->internal_registers[ T90_TREG0+i+1 - T90_IOBASE ])
        if(cpustate->timer_value[i] == cpustate->internal_registers[ T90_TREG0+i - T90_IOBASE ])
          timer_fired = 1;
      break;
  }

  if(timer_fired) {
    // special stuff handling
    switch(mode) {
      case 0x02: // 8bit PPG
      case 0x03: // 8bit PWM
        // TODO: hmm...
      case 0x00: // 8bit
        if(i & 1)
          break;
        if ( (cpustate->internal_registers[ T90_TCLK - T90_IOBASE ] & (0x0C << (i * 2))) == 0 ) // T0/T1 match signal clocks T1/T3
          t90_timer_callback(i+1);
        break;
      case 0x01: // 16bit, only can happen for i=0,2
        cpustate->timer_value[i+1] = 0;
        tlcs90_set_irq_line(INTT0 + i+1, 1);
        break;
    }
    // regular handling
    cpustate->timer_value[i] = 0;
    tlcs90_set_irq_line(INTT0 + i, 1);
  }
}

void t90_timer4_callback(INT32 )
{
//  logerror("CPU Timer 4 fired! value = %d\n", (unsigned)cpustate->timer_value[4]);

	t90_Regs *cpustate =  &tlcs90_data[0];
	cpustate->timer4_value++;

	// Match

	if ( cpustate->timer4_value == (cpustate->internal_registers[ T90_TREG4L - T90_IOBASE ] + (cpustate->internal_registers[ T90_TREG4H - T90_IOBASE ] << 8)) )
	{
//      	logerror("CPU Timer 4 matches TREG4\n");
		tlcs90_set_irq_line(INTT4, 1);
	}
	if ( cpustate->timer4_value == (cpustate->internal_registers[ T90_TREG5L - T90_IOBASE ] + (cpustate->internal_registers[ T90_TREG5H - T90_IOBASE ] << 8)) )
	{
//      	logerror("CPU Timer 4 matches TREG5\n");
		tlcs90_set_irq_line(INTT5, 1);
		if (cpustate->internal_registers[ T90_T4MOD - T90_IOBASE ] & 0x04)
			cpustate->timer4_value = 0;
	}

	// Overflow

	if ( cpustate->timer_value == 0 )
	{
//      	logerror("CPU Timer 4 overflow\n");
	}
}

void t90_internal_registers_w(UINT16 offset, UINT8 data)
{
	#define WIO     tlcs90_io_write_byte( T90_IOBASE+offset, data )

	t90_Regs *cpustate = &tlcs90_data[0];
	UINT8 out_mask;
	UINT8 old = cpustate->internal_registers[offset];
	switch ( T90_IOBASE + offset )
	{
		case T90_TRUN:
		{
			int i;
			UINT8 mask;
			// Timers 0-3
			for (i = 0; i < 4; i++)
			{
				mask = 0x20 | (1 << i);
				if ( (old ^ data) & mask ) // if timer bit or prescaler bit changed
				{
					if ( (data & mask) == mask ) t90_start_timer(cpustate, i);
					else 					     t90_stop_timer(cpustate, i);
				}
			}
			// Timer 4
			mask = 0x20 | 0x10;
			if ( (old ^ data) & mask )
			{
				if ( (data & mask) == mask )    t90_start_timer4(cpustate);
				else                            t90_stop_timer4(cpustate);
			}
			break;
		}

		case T90_INTEL:
			cpustate->irq_mask  &=  ~(  (1 << INTT2 ) |
									(1 << INTT3 ) |
									(1 << INTT4 ) |
									(1 << INT1  ) |
									(1 << INTT5 ) |
									(1 << INT2  ) |
									(1 << INTRX ) |
									(1 << INTTX )   );

			cpustate->irq_mask  |=  ((data & 0x80) ? (1 << INTT2 ) : 0) |
								((data & 0x40) ? (1 << INTT3 ) : 0) |
								((data & 0x20) ? (1 << INTT4 ) : 0) |
								((data & 0x10) ? (1 << INT1  ) : 0) |
								((data & 0x08) ? (1 << INTT5 ) : 0) |
								((data & 0x04) ? (1 << INT2  ) : 0) |
								((data & 0x02) ? (1 << INTRX ) : 0) |
								((data & 0x01) ? (1 << INTTX ) : 0) ;
			break;

		case T90_INTEH:
			cpustate->irq_mask  &=  ~(  (1 << INT0 ) |
									(1 << INTT0) |
									(1 << INTT1)    );

			cpustate->irq_mask  |=  ((data & 0x04) ? (1 << INT0 ) : 0) |
								((data & 0x02) ? (1 << INTT0) : 0) |
								((data & 0x01) ? (1 << INTT1) : 0) ;
			break;

		case T90_P3:
			data &= 0x6c;
			WIO;
			break;

		case T90_P4:
			data &= 0x0f;
			out_mask = (~cpustate->internal_registers[ T90_P4CR - T90_IOBASE ]) & 0x0f;
			if (out_mask)
			{
				data &= out_mask;
				WIO;
			}
			break;

		case T90_P6:
			out_mask = cpustate->internal_registers[ T90_P67CR - T90_IOBASE ] & 0x0f;
			switch (cpustate->internal_registers[ T90_SMMOD - T90_IOBASE ] & 0x03)
			{
				case 1:
					data &= ~0x01;
					// add TO1 here
					break;
				case 2:
				case 3:
					data &= ~0x0f;
					// add M0 here
					break;
			}

			if (out_mask)
			{
				data &= out_mask;
				WIO;
			}
			break;

		case T90_P7:
			out_mask = (cpustate->internal_registers[ T90_P67CR - T90_IOBASE ] & 0xf0) >> 4;
			switch ((cpustate->internal_registers[ T90_SMMOD - T90_IOBASE ]>>4) & 0x03)
			{
				case 1:
					data &= ~0x01;
					// add TO3 here
					break;
				case 2:
				case 3:
					data &= ~0x0f;
					// add M1 here
					break;
			}

			if (out_mask)
			{
				data &= out_mask;
				WIO;
			}
			break;

		case T90_P8:
			data &= 0x0f;
			out_mask = (~cpustate->internal_registers[ T90_P8CR - T90_IOBASE ]) & 0x08;
			if (out_mask)
			{
				data &= out_mask;
				WIO;
			}
			break;

		case T90_BX:
			cpustate->ixbase = (data & 0xf) << 16;
			break;
		case T90_BY:
			cpustate->iybase = (data & 0xf) << 16;
			break;
	}
	cpustate->internal_registers[offset] = data;
}

INT32 tlcs90_init(INT32 clock)
{
	t90_Regs *cpustate = &tlcs90_data[0];
	INT32 i, p;

	for (i = 0; i < 256; i++)
	{
		p = 0;
		if( i&0x01 ) ++p;
		if( i&0x02 ) ++p;
		if( i&0x04 ) ++p;
		if( i&0x08 ) ++p;
		if( i&0x10 ) ++p;
		if( i&0x20 ) ++p;
		if( i&0x40 ) ++p;
		if( i&0x80 ) ++p;
		SZ[i] = i ? i & SF : ZF;
//      	SZ[i] |= (i & (YF | XF));       /* undocumented flag bits 5+3 */
		SZ_BIT[i] = i ? i & SF : ZF | PF;
//      	SZ_BIT[i] |= (i & (YF | XF));   /* undocumented flag bits 5+3 */
		SZP[i] = SZ[i] | ((p & 1) ? 0 : PF);
		SZHV_inc[i] = SZ[i];
		if( i == 0x80 ) SZHV_inc[i] |= VF;
		if( (i & 0x0f) == 0x00 ) SZHV_inc[i] |= HF;
		SZHV_dec[i] = SZ[i] | NF;
		if( i == 0x7f ) SZHV_dec[i] |= VF;
		if( (i & 0x0f) == 0x0f ) SZHV_dec[i] |= HF;
	}

	memset(cpustate, 0, sizeof(t90_Regs));

	cpustate->timer_period = clock / 1000000;

	// Timers
	for (i = 0; i < 4; i++)
		cpustate->timer_cb[i] = t90_timer_callback;

	cpustate->timer_cb[4] = t90_timer4_callback;

	return 0;
}


INT32 tlcs90Scan(INT32 nAction)
{
	if (nAction & ACB_DRIVER_DATA) {
		struct BurnArea ba;

		memset(&ba, 0, sizeof(ba));
		ba.Data		= &tlcs90_data[0];
		ba.nLen		= STRUCT_SIZE_HELPER(struct t90_Regs, run_end);
		ba.szName	= "tlcs90 CPU Data";
		BurnAcb(&ba);
	}

	return 0;
}


#if 0
static ADDRESS_MAP_START(tmp90840_mem, AS_PROGRAM, 8, legacy_cpu_device)
	AM_RANGE(   0x0000,     0x1fff          )   AM_ROM  // 8KB ROM (internal)
	AM_RANGE(   0xfec0,     0xffc0          )   AM_RAM  // 256b RAM (internal)
	AM_RANGE(   T90_IOBASE, T90_IOBASE+47   )   AM_READWRITE_LEGACY( t90_internal_registers_r, t90_internal_registers_w )
ADDRESS_MAP_END
static ADDRESS_MAP_START(tmp90841_mem, AS_PROGRAM, 8, legacy_cpu_device)
//  AM_RANGE(   0x0000,     0x1fff          )   AM_ROM  // rom-less
	AM_RANGE(   0xfec0,     0xffc0          )   AM_RAM  // 256b RAM (internal)
	AM_RANGE(   T90_IOBASE, T90_IOBASE+47   )   AM_READWRITE_LEGACY( t90_internal_registers_r, t90_internal_registers_w )
ADDRESS_MAP_END

static ADDRESS_MAP_START(tmp91640_mem, AS_PROGRAM, 8, legacy_cpu_device )
	AM_RANGE(   0x0000,     0x3fff          ) AM_ROM    // 16KB ROM (internal)
	AM_RANGE(   0xfdc0,     0xffc0          ) AM_RAM    // 512b RAM (internal)
	AM_RANGE(   T90_IOBASE, T90_IOBASE+47   ) AM_READWRITE_LEGACY( t90_internal_registers_r, t90_internal_registers_w )
ADDRESS_MAP_END
static ADDRESS_MAP_START(tmp91641_mem, AS_PROGRAM, 8, legacy_cpu_device )
//  AM_RANGE(   0x0000,     0x3fff          ) AM_ROM    // rom-less
	AM_RANGE(   0xfdc0,     0xffc0          ) AM_RAM    // 512b RAM (internal)
	AM_RANGE(   T90_IOBASE, T90_IOBASE+47   ) AM_READWRITE_LEGACY( t90_internal_registers_r, t90_internal_registers_w )
ADDRESS_MAP_END
#endif

#if 0

static CPU_SET_INFO( t90 )
{
	t90_Regs *cpustate = get_safe_token(device);

	switch (state)
	{
		/* --- the following bits of info are set as 64-bit signed integers --- */

		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:      set_irq_line(cpustate, INTNMI, info->i);                break;
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0:     set_irq_line(cpustate, INT0,   info->i);                break;
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ1:     set_irq_line(cpustate, INT1,   info->i);                break;
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ2:     set_irq_line(cpustate, INT2,   info->i);                break;

		case CPUINFO_INT_PC:                                cpustate->pc.d = info->i;           break;
		case CPUINFO_INT_REGISTER + T90_PC:                 cpustate->pc.w.l = info->i;                     break;
		case CPUINFO_INT_SP:                                cpustate->sp.w.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_SP:                 cpustate->sp.w.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_A:                  cpustate->af.b.h = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_B:                  cpustate->bc.b.h = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_C:                  cpustate->bc.b.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_D:                  cpustate->de.b.h = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_E:                  cpustate->de.b.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_H:                  cpustate->hl.b.h = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_L:                  cpustate->hl.b.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_AF:                 cpustate->af.w.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_BC:                 cpustate->bc.w.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_DE:                 cpustate->de.w.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_HL:                 cpustate->hl.w.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_IX:                 cpustate->ix.w.l = info->i;                     break;
		case CPUINFO_INT_REGISTER + T90_IY:                 cpustate->iy.w.l = info->i;                     break;
	}
}

CPU_GET_INFO( tmp90840 )
{
	t90_Regs *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;

	switch (state)
	{
		/* --- the following bits of info are returned as 64-bit signed integers --- */

		case CPUINFO_INT_CONTEXT_SIZE:                              info->i = sizeof(t90_Regs);         break;
		case CPUINFO_INT_INPUT_LINES:                               info->i = 1;                    break;
		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:                        info->i = 0xff;                 break;
		case CPUINFO_INT_ENDIANNESS:                                info->i = ENDIANNESS_LITTLE;            break;
		case CPUINFO_INT_CLOCK_MULTIPLIER:                          info->i = 1;                    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 = 6;                    break;
		case CPUINFO_INT_MIN_CYCLES:                                info->i = 2;                    break;
		case CPUINFO_INT_MAX_CYCLES:                                info->i = 26;                   break;

		case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM:        info->i = 8;                    break;
		case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM:        info->i = 20;                   break;
		case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM:        info->i = 0;                    break;

		case CPUINFO_INT_DATABUS_WIDTH + AS_DATA:       info->i = 0;                    break;
		case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA:       info->i = 0;                    break;
		case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA:       info->i = 0;                    break;

		case CPUINFO_INT_DATABUS_WIDTH + AS_IO:         info->i = 8;                    break;
		case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO:         info->i = 16;                   break;
		case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO:         info->i = 0;                    break;

		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:              info->i = cpustate->irq_state & (1 << INTNMI);  break;
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ0:             info->i = cpustate->irq_state & (1 << INT0);        break;
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ1:             info->i = cpustate->irq_state & (1 << INT1);        break;
		case CPUINFO_INT_INPUT_STATE + INPUT_LINE_IRQ2:             info->i = cpustate->irq_state & (1 << INT2);        break;

		case CPUINFO_INT_PREVIOUSPC:                                info->i = cpustate->prvpc.w.l;      break;
		case CPUINFO_INT_PC:                                        info->i = cpustate->pc.d;               break;
		case CPUINFO_INT_REGISTER + T90_PC:                         info->i = cpustate->pc.w.l;         break;
		case CPUINFO_INT_SP:                                        info->i = cpustate->sp.d;               break;
		case CPUINFO_INT_REGISTER + T90_SP:                         info->i = cpustate->sp.w.l;         break;
		case CPUINFO_INT_REGISTER + T90_A:                          info->i = cpustate->af.b.h;         break;
		case CPUINFO_INT_REGISTER + T90_B:                          info->i = cpustate->bc.b.h;         break;
		case CPUINFO_INT_REGISTER + T90_C:                          info->i = cpustate->bc.b.l;         break;
		case CPUINFO_INT_REGISTER + T90_D:                          info->i = cpustate->de.b.h;         break;
		case CPUINFO_INT_REGISTER + T90_E:                          info->i = cpustate->de.b.l;         break;
		case CPUINFO_INT_REGISTER + T90_H:                          info->i = cpustate->hl.b.h;         break;
		case CPUINFO_INT_REGISTER + T90_L:                          info->i = cpustate->hl.b.l;         break;
		case CPUINFO_INT_REGISTER + T90_AF:                         info->i = cpustate->af.w.l;         break;
		case CPUINFO_INT_REGISTER + T90_BC:                         info->i = cpustate->bc.w.l;         break;
		case CPUINFO_INT_REGISTER + T90_DE:                         info->i = cpustate->de.w.l;         break;
		case CPUINFO_INT_REGISTER + T90_HL:                         info->i = cpustate->hl.w.l;         break;
		case CPUINFO_INT_REGISTER + T90_IX:                         info->i = cpustate->ix.w.l;         break;
		case CPUINFO_INT_REGISTER + T90_IY:                         info->i = cpustate->iy.w.l;         break;

		/* --- the following bits of info are returned as pointers to data or functions --- */

		case CPUINFO_FCT_SET_INFO:                                  info->setinfo = CPU_SET_INFO_NAME(t90);     break;
		case CPUINFO_FCT_INIT:                                      info->init = CPU_INIT_NAME(t90);                break;
		case CPUINFO_FCT_RESET:                                     info->reset = CPU_RESET_NAME(t90);          break;
		case CPUINFO_FCT_EXIT:                                      info->exit = CPU_EXIT_NAME(t90);                break;
		case CPUINFO_FCT_EXECUTE:                                   info->execute = CPU_EXECUTE_NAME(t90);      break;
		case CPUINFO_FCT_BURN:                                      info->burn = CPU_BURN_NAME(t90);                break;
		case CPUINFO_FCT_DISASSEMBLE:                               info->disassemble = CPU_DISASSEMBLE_NAME(t90);      break;
		case CPUINFO_PTR_INSTRUCTION_COUNTER:                       info->icount = &cpustate->icount;           break;
		case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tmp90840_mem); break;

		/* --- the following bits of info are returned as NULL-terminated strings --- */

		case CPUINFO_STR_NAME:              strcpy(info->s, "TMP90840");            break;
		case CPUINFO_STR_SHORTNAME:         strcpy(info->s, "tmp90840");            break;
		case CPUINFO_STR_FAMILY:        strcpy(info->s, "Toshiba TLCS-90"); break;
		case CPUINFO_STR_VERSION:       strcpy(info->s, "1.0");             break;
		case CPUINFO_STR_SOURCE_FILE:           strcpy(info->s, __FILE__);          break;
		case CPUINFO_STR_CREDITS:       strcpy(info->s, "Luca Elia");           break;

		case CPUINFO_STR_FLAGS:
			sprintf(info->s, "%c%c%c%c%c%c%c%c",
				F & 0x80 ? 'S':'.',
				F & 0x40 ? 'Z':'.',
				F & 0x20 ? 'I':'.',
				F & 0x10 ? 'H':'.',
				F & 0x08 ? 'X':'.',
				F & 0x04 ? 'P':'.',
				F & 0x02 ? 'N':'.',
				F & 0x01 ? 'C':'.');
			break;

		case CPUINFO_STR_REGISTER + T90_PC:     sprintf(info->s, "PC:%04X", cpustate->pc.w.l);  break;
		case CPUINFO_STR_REGISTER + T90_SP:     sprintf(info->s, "SP:%04X", cpustate->sp.w.l);  break;
		case CPUINFO_STR_REGISTER + T90_A:      sprintf(info->s, "~A:%02X", cpustate->af.b.h);  break;
		case CPUINFO_STR_REGISTER + T90_B:      sprintf(info->s, "~B:%02X", cpustate->bc.b.h);  break;
		case CPUINFO_STR_REGISTER + T90_C:      sprintf(info->s, "~C:%02X", cpustate->bc.b.l);  break;
		case CPUINFO_STR_REGISTER + T90_D:      sprintf(info->s, "~D:%02X", cpustate->de.b.h);  break;
		case CPUINFO_STR_REGISTER + T90_E:      sprintf(info->s, "~E:%02X", cpustate->de.b.l);  break;
		case CPUINFO_STR_REGISTER + T90_H:      sprintf(info->s, "~H:%02X", cpustate->hl.b.h);  break;
		case CPUINFO_STR_REGISTER + T90_L:      sprintf(info->s, "~L:%02X", cpustate->hl.b.l);  break;
		case CPUINFO_STR_REGISTER + T90_AF:     sprintf(info->s, "AF:%04X", cpustate->af.w.l);  break;
		case CPUINFO_STR_REGISTER + T90_BC:     sprintf(info->s, "BC:%04X", cpustate->bc.w.l);  break;
		case CPUINFO_STR_REGISTER + T90_DE:     sprintf(info->s, "DE:%04X", cpustate->de.w.l);  break;
		case CPUINFO_STR_REGISTER + T90_HL:     sprintf(info->s, "HL:%04X", cpustate->hl.w.l);  break;
		case CPUINFO_STR_REGISTER + T90_IX:     sprintf(info->s, "IX:%04X", cpustate->ix.w.l);  break;
		case CPUINFO_STR_REGISTER + T90_IY:     sprintf(info->s, "IY:%04X", cpustate->iy.w.l);  break;
	}
}

CPU_GET_INFO( tmp90841 )
{
	switch (state)
	{
		/* --- the following bits of info are returned as 64-bit signed integers --- */

		case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tmp90841_mem); return;

		/* --- the following bits of info are returned as NULL-terminated strings --- */

		case CPUINFO_STR_NAME:              strcpy(info->s, "TMP90841");            return;
		case CPUINFO_STR_SHORTNAME:         strcpy(info->s, "tmp90841");            return;
	}

	CPU_GET_INFO_CALL(tmp90840);
}

CPU_GET_INFO( tmp91640 )
{
	switch (state)
	{
		/* --- the following bits of info are returned as 64-bit signed integers --- */

		case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tmp91640_mem); return;

		/* --- the following bits of info are returned as NULL-terminated strings --- */

		case CPUINFO_STR_NAME:              strcpy(info->s, "TMP91640");            return;
		case CPUINFO_STR_SHORTNAME:         strcpy(info->s, "tmp91640");            return;
	}

	CPU_GET_INFO_CALL(tmp90840);
}

CPU_GET_INFO( tmp91641 )
{
	switch (state)
	{
		/* --- the following bits of info are returned as 64-bit signed integers --- */

		case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tmp91641_mem); return;

		/* --- the following bits of info are returned as NULL-terminated strings --- */

		case CPUINFO_STR_NAME:              strcpy(info->s, "TMP91641");            return;
		case CPUINFO_STR_SHORTNAME:         strcpy(info->s, "tmp91641");            return;
	}

	CPU_GET_INFO_CALL(tmp90840);
}

DEFINE_LEGACY_CPU_DEVICE(TMP90840, tmp90840);
DEFINE_LEGACY_CPU_DEVICE(TMP90841, tmp90841);
DEFINE_LEGACY_CPU_DEVICE(TMP91640, tmp91640);
DEFINE_LEGACY_CPU_DEVICE(TMP91641, tmp91641);

#endif
