text: /**********************************************************************
  
      Zilog Z8 Single-Chip MCU emulation
  
      Copyright MESS Team.
      Visit http://mamedev.org for licensing and usage restrictions.
  
  **********************************************************************/
  
  /***************************************************************************
      MACROS
  ***************************************************************************/
  
  #define read(_reg)		register_read(cpustate, _reg)
  #define r(_data)		get_working_register(cpustate, _data)
  #define Ir(_data)		get_intermediate_register(cpustate, get_working_register(cpustate, _data))
  #define R				get_register(cpustate, fetch(cpustate))
  #define IR				get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
  #define RR				get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))
  #define IM				fetch(cpustate)
  #define flag(_flag)		((cpustate->r[Z8_REGISTER_FLAGS] & Z8_FLAGS##_##_flag) ? 1 : 0)
  
  #define mode_r1_r2(_func)	\
  	UINT8 dst_src = fetch(cpustate);\
  	UINT8 dst = r(dst_src >> 4);\
  	UINT8 src = read(r(dst_src & 0x0f));\
  	_func(cpustate, dst, src);
  
  #define mode_r1_Ir2(_func) \
  	UINT8 dst_src = fetch(cpustate);\
  	UINT8 dst = r(dst_src >> 4);\
  	UINT8 src = read(Ir(dst_src & 0x0f));\
  	_func(cpustate, dst, src);
  
  #define mode_R2_R1(_func) \
  	UINT8 src = read(R);\
  	UINT8 dst = R;\
  	_func(cpustate, dst, src);
  
  #define mode_IR2_R1(_func) \
  	UINT8 src = read(R);\
  	UINT8 dst = IR;\
  	_func(cpustate, dst, src);
  
  #define mode_R1_IM(_func) \
  	UINT8 dst = R;\
  	UINT8 src = IM;\
  	_func(cpustate, dst, src);
  
  #define mode_IR1_IM(_func) \
  	UINT8 dst = IR;\
  	UINT8 src = IM;\
  	_func(cpustate, dst, src);
  
  #define mode_r1(_func) \
  	UINT8 dst = r(opcode >> 4);\
  	_func(cpustate, dst);
  
  #define mode_R1(_func) \
  	UINT8 dst = R;\
  	_func(cpustate, dst);
  
  #define mode_RR1(_func) \
  	UINT8 dst = R;\
  	_func(cpustate, dst);
  
  #define mode_IR1(_func) \
  	UINT8 dst = IR;\
  	_func(cpustate, dst);
  
  #define mode_r1_IM(_func) \
  	UINT8 dst = r(opcode >> 4);\
  	UINT8 src = IM;\
  	_func(cpustate, dst, src);
  
  #define mode_r1_R2(_func) \
  	UINT8 dst = r(opcode >> 4);\
  	UINT8 src = read(R);\
  	_func(cpustate, dst, src);
  
  #define mode_r2_R1(_func) \
  	UINT8 src = read(r(opcode >> 4));\
  	UINT8 dst = R;\
  	_func(cpustate, dst, src);
  
  #define mode_Ir1_r2(_func) \
  	UINT8 dst_src = fetch(cpustate);\
  	UINT8 dst = Ir(dst_src >> 4);\
  	UINT8 src = read(r(dst_src & 0x0f));\
  	_func(cpustate, dst, src);
  
  #define mode_R2_IR1(_func) \
  	UINT8 src = read(R);\
  	UINT8 dst = IR;\
  	_func(cpustate, dst, src);
  
  #define mode_r1_x_R2(_func) \
  	UINT8 dst_src = fetch(cpustate);\
  	UINT8 dst = r(dst_src >> 4);\
  	UINT8 src = read(read(r(dst_src & 0x0f)) + R);\
  	_func(cpustate, dst, src);
  
  #define mode_r2_x_R1(_func) \
  	UINT8 dst_src = fetch(cpustate);\
  	UINT8 dst = R + read(r(dst_src & 0x0f));\
  	UINT8 src = read(r(dst_src >> 4));\
  	_func(cpustate, dst, src);
  
  /***************************************************************************
      LOAD INSTRUCTIONS
  ***************************************************************************/
  
  static void clear(z8_state *cpustate, UINT8 dst)
  {
  	/* dst <- 0 */
  	register_write(cpustate, dst, 0);
  }
  
  INSTRUCTION( clr_R1 )			{ mode_R1(clear) }
  INSTRUCTION( clr_IR1 )			{ mode_IR1(clear) }
  
  static void load(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst <- src */
  	register_write(cpustate, dst, src);
  }
  
  INSTRUCTION( ld_r1_IM )			{ mode_r1_IM(load) }
  INSTRUCTION( ld_r1_R2 )			{ mode_r1_R2(load) }
  INSTRUCTION( ld_r2_R1 )			{ mode_r2_R1(load) }
  INSTRUCTION( ld_Ir1_r2 )		{ mode_Ir1_r2(load) }
  INSTRUCTION( ld_R2_IR1 )		{ mode_R2_IR1(load) }
  INSTRUCTION( ld_r1_x_R2 )		{ mode_r1_x_R2(load) }
  INSTRUCTION( ld_r2_x_R1 )		{ mode_r2_x_R1(load) }
  
  INSTRUCTION( ld_r1_r2 )			{ mode_r1_r2(load) }
  INSTRUCTION( ld_r1_Ir2 )		{ mode_r1_Ir2(load) }
  INSTRUCTION( ld_R2_R1 )			{ mode_R2_R1(load) }
  INSTRUCTION( ld_IR2_R1 )		{ mode_IR2_R1(load) }
  INSTRUCTION( ld_R1_IM )			{ mode_R1_IM(load) }
  INSTRUCTION( ld_IR1_IM )		{ mode_IR1_IM(load) }
  
  static void load_from_memory(z8_state *cpustate, address_space *space)
  {
  	UINT8 operands = fetch(cpustate);
  	UINT8 dst = get_working_register(cpustate, operands >> 4);
  	UINT8 src = get_working_register(cpustate, operands & 0x0f);
  
  	UINT16 address = register_pair_read(cpustate, src);
  	UINT8 data = cpustate->direct->read_decrypted_byte(address);
  
  	register_write(cpustate, dst, data);
  }
  
  static void load_to_memory(z8_state *cpustate, address_space *space)
  {
  	UINT8 operands = fetch(cpustate);
  	UINT8 src = get_working_register(cpustate, operands >> 4);
  	UINT8 dst = get_working_register(cpustate, operands & 0x0f);
  
  	UINT16 address = register_pair_read(cpustate, dst);
  	UINT8 data = register_read(cpustate, src);
  
  	cpustate->program->write_byte(address, data);
  }
  
  static void load_from_memory_autoinc(z8_state *cpustate, address_space *space)
  {
  	UINT8 operands = fetch(cpustate);
  	UINT8 dst = get_working_register(cpustate, operands >> 4);
  	UINT8 real_dst = get_intermediate_register(cpustate, dst);
  	UINT8 src = get_working_register(cpustate, operands & 0x0f);
  
  	UINT16 address = register_pair_read(cpustate, src);
  	UINT8 data = cpustate->direct->read_decrypted_byte(address);
  
  	register_write(cpustate, real_dst, data);
  
  	register_write(cpustate, dst, real_dst + 1);
  	register_pair_write(cpustate, src, address + 1);
  }
  
  static void load_to_memory_autoinc(z8_state *cpustate, address_space *space)
  {
  	UINT8 operands = fetch(cpustate);
  	UINT8 src = get_working_register(cpustate, operands >> 4);
  	UINT8 dst = get_working_register(cpustate, operands & 0x0f);
  	UINT8 real_src = get_intermediate_register(cpustate, src);
  
  	UINT16 address = register_pair_read(cpustate, dst);
  	UINT8 data = register_read(cpustate, real_src);
  
  	cpustate->program->write_byte(address, data);
  
  	register_pair_write(cpustate, dst, address + 1);
  	register_write(cpustate, src, real_src + 1);
  }
  
  INSTRUCTION( ldc_r1_Irr2 )		{ load_from_memory(cpustate, cpustate->program); }
  INSTRUCTION( ldc_r2_Irr1 )		{ load_to_memory(cpustate, cpustate->program); }
  INSTRUCTION( ldci_Ir1_Irr2 )	{ load_from_memory_autoinc(cpustate, cpustate->program); }
  INSTRUCTION( ldci_Ir2_Irr1 )	{ load_to_memory_autoinc(cpustate, cpustate->program); }
  INSTRUCTION( lde_r1_Irr2 )		{ load_from_memory(cpustate, cpustate->data); }
  INSTRUCTION( lde_r2_Irr1 )		{ load_to_memory(cpustate, cpustate->data); }
  INSTRUCTION( ldei_Ir1_Irr2 )	{ load_from_memory_autoinc(cpustate, cpustate->data); }
  INSTRUCTION( ldei_Ir2_Irr1 )	{ load_to_memory_autoinc(cpustate, cpustate->data); }
  
  static void pop(z8_state *cpustate, UINT8 dst)
  {
  	/* dst <- @SP
         SP <- SP + 1 */
  	register_write(cpustate, dst, stack_pop_byte(cpustate));
  }
  
  INSTRUCTION( pop_R1 )			{ mode_R1(pop) }
  INSTRUCTION( pop_IR1 )			{ mode_IR1(pop) }
  
  static void push(z8_state *cpustate, UINT8 src)
  {
  	/* SP <- SP - 1
         @SP <- src */
  	stack_push_byte(cpustate, read(src));
  }
  
  INSTRUCTION( push_R2 )			{ mode_R1(push) }
  INSTRUCTION( push_IR2 )			{ mode_IR1(push) }
  
  /***************************************************************************
      ARITHMETIC INSTRUCTIONS
  ***************************************************************************/
  
  static void add_carry(z8_state *cpustate, UINT8 dst, INT8 src)
  {
  	/* dst <- dst + src + C */
  	UINT8 data = register_read(cpustate, dst);
  	UINT16 new_data = data + src + flag(C);
  
  	set_flag_c(new_data & 0x100);
  	set_flag_z(new_data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
  	set_flag_d(0);
  	set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
  
  	register_write(cpustate, dst, new_data & 0xff);
  }
  
  INSTRUCTION( adc_r1_r2 )		{ mode_r1_r2(add_carry) }
  INSTRUCTION( adc_r1_Ir2 )		{ mode_r1_Ir2(add_carry) }
  INSTRUCTION( adc_R2_R1 )		{ mode_R2_R1(add_carry) }
  INSTRUCTION( adc_IR2_R1 )		{ mode_IR2_R1(add_carry) }
  INSTRUCTION( adc_R1_IM )		{ mode_R1_IM(add_carry) }
  INSTRUCTION( adc_IR1_IM )		{ mode_IR1_IM(add_carry) }
  
  static void add(z8_state *cpustate, UINT8 dst, INT8 src)
  {
  	/* dst <- dst + src */
  	UINT8 data = register_read(cpustate, dst);
  	UINT16 new_data = data + src;
  
  	set_flag_c(new_data & 0x100);
  	set_flag_z(new_data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v(((data & 0x80) == (src & 0x80)) && ((new_data & 0x80) != (src & 0x80)));
  	set_flag_d(0);
  	set_flag_h(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10));
  
  	register_write(cpustate, dst, new_data & 0xff);
  }
  
  INSTRUCTION( add_r1_r2 )		{ mode_r1_r2(add) }
  INSTRUCTION( add_r1_Ir2 )		{ mode_r1_Ir2(add) }
  INSTRUCTION( add_R2_R1 )		{ mode_R2_R1(add) }
  INSTRUCTION( add_IR2_R1 )		{ mode_IR2_R1(add) }
  INSTRUCTION( add_R1_IM )		{ mode_R1_IM(add) }
  INSTRUCTION( add_IR1_IM )		{ mode_IR1_IM(add) }
  
  static void compare(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst - src */
  	UINT8 data = register_read(cpustate, dst);
  	UINT16 new_data = data - src;
  
  	set_flag_c(!(new_data & 0x100));
  	set_flag_z(new_data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
  }
  
  INSTRUCTION( cp_r1_r2 )			{ mode_r1_r2(compare) }
  INSTRUCTION( cp_r1_Ir2 )		{ mode_r1_Ir2(compare) }
  INSTRUCTION( cp_R2_R1 )			{ mode_R2_R1(compare) }
  INSTRUCTION( cp_IR2_R1 )		{ mode_IR2_R1(compare) }
  INSTRUCTION( cp_R1_IM )			{ mode_R1_IM(compare) }
  INSTRUCTION( cp_IR1_IM )		{ mode_IR1_IM(compare) }
  
  static void decimal_adjust(z8_state *cpustate, UINT8 dst)
  {
  }
  
  INSTRUCTION( da_R1 )			{ mode_R1(decimal_adjust) }
  INSTRUCTION( da_IR1 )			{ mode_IR1(decimal_adjust) }
  
  static void decrement(z8_state *cpustate, UINT8 dst)
  {
  	/* dst <- dst - 1 */
  	UINT8 data = register_read(cpustate, dst) - 1;
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(data == 0x7f);
  
  	register_write(cpustate, dst, data);
  }
  
  INSTRUCTION( dec_R1 )			{ mode_R1(decrement) }
  INSTRUCTION( dec_IR1 )			{ mode_IR1(decrement) }
  
  static void decrement_word(z8_state *cpustate, UINT8 dst)
  {
  	/* dst <- dst - 1 */
  	UINT16 data = register_pair_read(cpustate, dst) - 1;
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x8000);
  	set_flag_v(data == 0x7fff);
  
  	register_pair_write(cpustate, dst, data);
  }
  
  INSTRUCTION( decw_RR1 )			{ mode_RR1(decrement_word) }
  INSTRUCTION( decw_IR1 )			{ mode_IR1(decrement_word) }
  
  static void increment(z8_state *cpustate, UINT8 dst)
  {
  	/* dst <- dst + 1 */
  	UINT8 data = register_read(cpustate, dst) + 1;
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(data == 0x80);
  
  	register_write(cpustate, dst, data);
  }
  
  INSTRUCTION( inc_r1 )			{ mode_r1(increment) }
  INSTRUCTION( inc_R1 )			{ mode_R1(increment) }
  INSTRUCTION( inc_IR1 )			{ mode_IR1(increment) }
  
  static void increment_word(z8_state *cpustate, UINT8 dst)
  {
  	/* dst <- dst + 1 */
  	UINT16 data = register_pair_read(cpustate, dst) + 1;
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x8000);
  	set_flag_v(data == 0x8000);
  
  	register_pair_write(cpustate, dst, data);
  }
  
  INSTRUCTION( incw_RR1 )			{ mode_RR1(increment_word) }
  INSTRUCTION( incw_IR1 )			{ mode_IR1(increment_word) }
  
  static void subtract_carry(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst <- dst - src - C */
  	UINT8 data = register_read(cpustate, dst);
  	UINT16 new_data = data - src;
  
  	set_flag_c(!(new_data & 0x100));
  	set_flag_z(new_data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
  	set_flag_d(1);
  	set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
  
  	register_write(cpustate, dst, new_data & 0xff);
  }
  
  INSTRUCTION( sbc_r1_r2 )		{ mode_r1_r2(subtract_carry) }
  INSTRUCTION( sbc_r1_Ir2 )		{ mode_r1_Ir2(subtract_carry) }
  INSTRUCTION( sbc_R2_R1 )		{ mode_R2_R1(subtract_carry) }
  INSTRUCTION( sbc_IR2_R1 )		{ mode_IR2_R1(subtract_carry) }
  INSTRUCTION( sbc_R1_IM )		{ mode_R1_IM(subtract_carry) }
  INSTRUCTION( sbc_IR1_IM )		{ mode_IR1_IM(subtract_carry) }
  
  static void subtract(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst <- dst - src */
  	UINT8 data = register_read(cpustate, dst);
  	UINT16 new_data = data - src;
  
  	set_flag_c(!(new_data & 0x100));
  	set_flag_z(new_data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v(((data & 0x80) != (src & 0x80)) && ((new_data & 0x80) == (src & 0x80)));
  	set_flag_d(1);
  	set_flag_h(!(((data & 0x1f) == 0x0f) && ((new_data & 0x1f) == 0x10)));
  
  	register_write(cpustate, dst, new_data & 0xff);
  }
  
  INSTRUCTION( sub_r1_r2 )		{ mode_r1_r2(subtract) }
  INSTRUCTION( sub_r1_Ir2 )		{ mode_r1_Ir2(subtract) }
  INSTRUCTION( sub_R2_R1 )		{ mode_R2_R1(subtract) }
  INSTRUCTION( sub_IR2_R1 )		{ mode_IR2_R1(subtract) }
  INSTRUCTION( sub_R1_IM )		{ mode_R1_IM(subtract) }
  INSTRUCTION( sub_IR1_IM )		{ mode_IR1_IM(subtract) }
  
  /***************************************************************************
      LOGICAL INSTRUCTIONS
  ***************************************************************************/
  
  static void _and(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst <- dst AND src */
  	UINT8 data = register_read(cpustate, dst) & src;
  	register_write(cpustate, dst, data);
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(0);
  }
  
  INSTRUCTION( and_r1_r2 )		{ mode_r1_r2(_and) }
  INSTRUCTION( and_r1_Ir2 )		{ mode_r1_Ir2(_and) }
  INSTRUCTION( and_R2_R1 )		{ mode_R2_R1(_and) }
  INSTRUCTION( and_IR2_R1 )		{ mode_IR2_R1(_and) }
  INSTRUCTION( and_R1_IM )		{ mode_R1_IM(_and) }
  INSTRUCTION( and_IR1_IM )		{ mode_IR1_IM(_and) }
  
  static void complement(z8_state *cpustate, UINT8 dst)
  {
  	/* dst <- NOT dst */
  	UINT8 data = register_read(cpustate, dst) ^ 0xff;
  	register_write(cpustate, dst, data);
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(0);
  }
  
  INSTRUCTION( com_R1 )			{ mode_R1(complement) }
  INSTRUCTION( com_IR1 )			{ mode_IR1(complement) }
  
  static void _or(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst <- dst OR src */
  	UINT8 data = register_read(cpustate, dst) | src;
  	register_write(cpustate, dst, data);
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(0);
  }
  
  INSTRUCTION( or_r1_r2 )			{ mode_r1_r2(_or) }
  INSTRUCTION( or_r1_Ir2 )		{ mode_r1_Ir2(_or) }
  INSTRUCTION( or_R2_R1 )			{ mode_R2_R1(_or) }
  INSTRUCTION( or_IR2_R1 )		{ mode_IR2_R1(_or) }
  INSTRUCTION( or_R1_IM )			{ mode_R1_IM(_or) }
  INSTRUCTION( or_IR1_IM )		{ mode_IR1_IM(_or) }
  
  static void _xor(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst <- dst XOR src */
  	UINT8 data = register_read(cpustate, dst) ^ src;
  	register_write(cpustate, dst, data);
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(0);
  }
  
  INSTRUCTION( xor_r1_r2 )		{ mode_r1_r2(_xor) }
  INSTRUCTION( xor_r1_Ir2 )		{ mode_r1_Ir2(_xor) }
  INSTRUCTION( xor_R2_R1 )		{ mode_R2_R1(_xor) }
  INSTRUCTION( xor_IR2_R1 )		{ mode_IR2_R1(_xor) }
  INSTRUCTION( xor_R1_IM )		{ mode_R1_IM(_xor) }
  INSTRUCTION( xor_IR1_IM )		{ mode_IR1_IM(_xor) }
  
  /***************************************************************************
      PROGRAM CONTROL INSTRUCTIONS
  ***************************************************************************/
  
  static void call(z8_state *cpustate, UINT16 dst)
  {
  	stack_push_word(cpustate, cpustate->pc);
  	cpustate->pc = dst;
  }
  
  INSTRUCTION( call_IRR1 )		{ UINT16 dst = register_pair_read(cpustate, get_intermediate_register(cpustate, get_register(cpustate, fetch(cpustate)))); call(cpustate, dst); }
  INSTRUCTION( call_DA )			{ UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate); call(cpustate, dst); }
  
  INSTRUCTION( djnz_r1_RA )
  {
  	INT8 ra = (INT8)fetch(cpustate);
  
  	/* r <- r - 1 */
  	int r = get_working_register(cpustate, opcode >> 4);
  	UINT8 data = register_read(cpustate, r) - 1;
  	register_write(cpustate, r, data);
  
  	/* if r<>0, PC <- PC + dst */
  	if (data != 0)
  	{
  		cpustate->pc += ra;
  		*cycles += 2;
  	}
  }
  
  INSTRUCTION( iret )
  {
  	/* FLAGS <- @SP
         SP <- SP + 1 */
  	register_write(cpustate, Z8_REGISTER_FLAGS, stack_pop_byte(cpustate));
  
  	/* PC <- @SP
         SP <- SP + 2 */
  	cpustate->pc = stack_pop_word(cpustate);
  
  	/* IMR (7) <- 1 */
  	cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE;
  }
  
  INSTRUCTION( ret )
  {
  	/* PC <- @SP
         SP <- SP + 2 */
  	cpustate->pc = stack_pop_word(cpustate);
  }
  
  static void jump(z8_state *cpustate, UINT16 dst)
  {
  	/* PC <- dst */
  	cpustate->pc = dst;
  }
  
  INSTRUCTION( jp_IRR1 )			{ jump(cpustate, register_pair_read(cpustate, IR)); }
  
  static int check_condition_code(z8_state *cpustate, int cc)
  {
  	int truth = 0;
  
  	switch (cc)
  	{
  	case CC_F:		truth = 0; break;
  	case CC_LT:		truth = flag(S) ^ flag(V); break;
  	case CC_LE:		truth = (flag(Z) | (flag(S) ^ flag(V))); break;
  	case CC_ULE:	truth = flag(C) | flag(Z); break;
  	case CC_OV:		truth = flag(V); break;
  	case CC_MI:		truth = flag(S); break;
  	case CC_Z:		truth = flag(Z); break;
  	case CC_C:		truth = flag(C); break;
  	case CC_T:		truth = 1; break;
  	case CC_GE:		truth = !(flag(S) ^ flag(V)); break;
  	case CC_GT:		truth = !(flag(Z) | (flag(S) ^ flag(V))); break;
  	case CC_UGT:	truth = ((!flag(C)) & (!flag(Z))); break;
  	case CC_NOV:	truth = !flag(V); break;
  	case CC_PL:		truth = !flag(S); break;
  	case CC_NZ:		truth = !flag(Z); break;
  	case CC_NC:		truth = !flag(C); break;
  	}
  
  	return truth;
  }
  
  INSTRUCTION( jp_cc_DA )
  {
  	UINT16 dst = (fetch(cpustate) << 8) | fetch(cpustate);
  
  	/* if cc is true, then PC <- dst */
  	if (check_condition_code(cpustate, opcode >> 4))
  	{
  		jump(cpustate, dst);
  		*cycles += 2;
  	}
  }
  
  INSTRUCTION( jr_cc_RA )
  {
  	INT8 ra = (INT8)fetch(cpustate);
  	UINT16 dst = cpustate->pc + ra;
  
  	/* if cc is true, then PC <- dst */
  	if (check_condition_code(cpustate, opcode >> 4))
  	{
  		jump(cpustate, dst);
  		*cycles += 2;
  	}
  }
  
  /***************************************************************************
      BIT MANIPULATION INSTRUCTIONS
  ***************************************************************************/
  
  static void test_complement_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* NOT(dst) AND src */
  	UINT8 data = (register_read(cpustate, dst) ^ 0xff) & src;
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(0);
  }
  
  INSTRUCTION( tcm_r1_r2 )		{ mode_r1_r2(test_complement_under_mask) }
  INSTRUCTION( tcm_r1_Ir2 )		{ mode_r1_Ir2(test_complement_under_mask) }
  INSTRUCTION( tcm_R2_R1 )		{ mode_R2_R1(test_complement_under_mask) }
  INSTRUCTION( tcm_IR2_R1 )		{ mode_IR2_R1(test_complement_under_mask) }
  INSTRUCTION( tcm_R1_IM )		{ mode_R1_IM(test_complement_under_mask) }
  INSTRUCTION( tcm_IR1_IM )		{ mode_IR1_IM(test_complement_under_mask) }
  
  static void test_under_mask(z8_state *cpustate, UINT8 dst, UINT8 src)
  {
  	/* dst AND src */
  	UINT8 data = register_read(cpustate, dst) & src;
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  	set_flag_v(0);
  }
  
  INSTRUCTION( tm_r1_r2 )			{ mode_r1_r2(test_under_mask) }
  INSTRUCTION( tm_r1_Ir2 )		{ mode_r1_Ir2(test_under_mask) }
  INSTRUCTION( tm_R2_R1 )			{ mode_R2_R1(test_under_mask) }
  INSTRUCTION( tm_IR2_R1 )		{ mode_IR2_R1(test_under_mask) }
  INSTRUCTION( tm_R1_IM )			{ mode_R1_IM(test_under_mask) }
  INSTRUCTION( tm_IR1_IM )		{ mode_IR1_IM(test_under_mask) }
  
  /***************************************************************************
      ROTATE AND SHIFT INSTRUCTIONS
  ***************************************************************************/
  
  static void rotate_left(z8_state *cpustate, UINT8 dst)
  {
  	/* << */
  	UINT8 data = register_read(cpustate, dst);
  	UINT8 new_data = (data << 1) | BIT(data, 7);
  
  	set_flag_c(data & 0x80);
  	set_flag_z(data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v((data & 0x80) != (new_data & 0x80));
  
  	register_write(cpustate, dst, new_data);
  }
  
  INSTRUCTION( rl_R1 )			{ mode_R1(rotate_left) }
  INSTRUCTION( rl_IR1 )			{ mode_IR1(rotate_left) }
  
  static void rotate_left_carry(z8_state *cpustate, UINT8 dst)
  {
  	/* << C */
  	UINT8 data = register_read(cpustate, dst);
  	UINT8 new_data = (data << 1) | flag(C);
  
  	set_flag_c(data & 0x80);
  	set_flag_z(data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v((data & 0x80) != (new_data & 0x80));
  
  	register_write(cpustate, dst, new_data);
  }
  
  INSTRUCTION( rlc_R1 )			{ mode_R1(rotate_left_carry) }
  INSTRUCTION( rlc_IR1 )			{ mode_IR1(rotate_left_carry) }
  
  static void rotate_right(z8_state *cpustate, UINT8 dst)
  {
  	/* >> */
  	UINT8 data = register_read(cpustate, dst);
  	UINT8 new_data = ((data & 0x01) << 7) | (data >> 1);
  
  	set_flag_c(data & 0x01);
  	set_flag_z(data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v((data & 0x80) != (new_data & 0x80));
  
  	register_write(cpustate, dst, new_data);
  }
  
  INSTRUCTION( rr_R1 )			{ mode_R1(rotate_right) }
  INSTRUCTION( rr_IR1 )			{ mode_IR1(rotate_right) }
  
  static void rotate_right_carry(z8_state *cpustate, UINT8 dst)
  {
  	/* >> C */
  	UINT8 data = register_read(cpustate, dst);
  	UINT8 new_data = (flag(C) << 7) | (data >> 1);
  
  	set_flag_c(data & 0x01);
  	set_flag_z(data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v((data & 0x80) != (new_data & 0x80));
  
  	register_write(cpustate, dst, new_data);
  }
  
  INSTRUCTION( rrc_R1 )			{ mode_R1(rotate_right_carry) }
  INSTRUCTION( rrc_IR1 )			{ mode_IR1(rotate_right_carry) }
  
  static void shift_right_arithmetic(z8_state *cpustate, UINT8 dst)
  {
  	/* */
  	UINT8 data = register_read(cpustate, dst);
  	UINT8 new_data = (data & 0x80) | ((data >> 1) & 0x7f);
  
  	set_flag_c(data & 0x01);
  	set_flag_z(data == 0);
  	set_flag_s(new_data & 0x80);
  	set_flag_v(0);
  
  	register_write(cpustate, dst, new_data);
  }
  
  INSTRUCTION( sra_R1 )			{ mode_R1(shift_right_arithmetic) }
  INSTRUCTION( sra_IR1 )			{ mode_IR1(shift_right_arithmetic) }
  
  static void swap(z8_state *cpustate, UINT8 dst)
  {
  	/* dst(7-4) <-> dst(3-0) */
  	UINT8 data = register_read(cpustate, dst);
  	data = (data << 4) | (data >> 4);
  	register_write(cpustate, dst, data);
  
  	set_flag_z(data == 0);
  	set_flag_s(data & 0x80);
  //  set_flag_v(0); undefined
  }
  
  INSTRUCTION( swap_R1 )			{ mode_R1(swap) }
  INSTRUCTION( swap_IR1 )			{ mode_IR1(swap) }
  
  /***************************************************************************
      CPU CONTROL INSTRUCTIONS
  ***************************************************************************/
  
  INSTRUCTION( ccf )				{ cpustate->r[Z8_REGISTER_FLAGS] ^= Z8_FLAGS_C; }
  INSTRUCTION( di )				{ cpustate->r[Z8_REGISTER_IMR] &= ~Z8_IMR_ENABLE; }
  INSTRUCTION( ei )				{ cpustate->r[Z8_REGISTER_IMR] |= Z8_IMR_ENABLE; }
  INSTRUCTION( nop )				{ /* no operation */ }
  INSTRUCTION( rcf )				{ set_flag_c(0); }
  INSTRUCTION( scf )				{ set_flag_c(1); }
  INSTRUCTION( srp_IM )			{ cpustate->r[Z8_REGISTER_RP] = fetch(cpustate); }
  