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

    NEC V20/V30/V33 emulator modified to a v30mz emulator

    (Re)Written June-September 2000 by Bryan McPhail (mish@tendril.co.uk) based
    on code by Oliver Bergmann (Raul_Bloodworth@hotmail.com) who based code
    on the i286 emulator by Fabrice Frances which had initial work based on
    David Hedley's pcemu(!).

    This new core features 99% accurate cycle counts for each processor,
    there are still some complex situations where cycle counts are wrong,
    typically where a few instructions have differing counts for odd/even
    source and odd/even destination memory operands.

    Flag settings are also correct for the NEC processors rather than the
    I86 versions.

    Changelist:

    22/02/2003:
        Removed cycle counts from memory accesses - they are certainly wrong,
        and there is already a memory access cycle penalty in the opcodes
        using them.

        Fixed save states.

        Fixed ADJBA/ADJBS/ADJ4A/ADJ4S flags/return values for all situations.
        (Fixes bugs in Geostorm and Thunderblaster)

        Fixed carry flag on NEG (I thought this had been fixed circa Mame 0.58,
        but it seems I never actually submitted the fix).

        Fixed many cycle counts in instructions and bug in cycle count
        macros (odd word cases were testing for odd instruction word address
        not data address).

    Todo!
        Double check cycle timing is 100%.
        Fix memory interface (should be 16 bit).

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

#include "emu.h"
#include "debugger.h"
#include "v30mz.h"


enum SREGS { ES=0, CS, SS, DS };
enum WREGS { AW=0, CW, DW, BW, SP, BP, IX, IY };

#define NEC_NMI_INT_VECTOR 2

enum BREGS {
	AL = NATIVE_ENDIAN_VALUE_LE_BE(0x0, 0x1),
	AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1, 0x0),
	CL = NATIVE_ENDIAN_VALUE_LE_BE(0x2, 0x3),
	CH = NATIVE_ENDIAN_VALUE_LE_BE(0x3, 0x2),
	DL = NATIVE_ENDIAN_VALUE_LE_BE(0x4, 0x5),
	DH = NATIVE_ENDIAN_VALUE_LE_BE(0x5, 0x4),
	BL = NATIVE_ENDIAN_VALUE_LE_BE(0x6, 0x7),
	BH = NATIVE_ENDIAN_VALUE_LE_BE(0x7, 0x6),
	SPL = NATIVE_ENDIAN_VALUE_LE_BE(0x8, 0x9),
	SPH = NATIVE_ENDIAN_VALUE_LE_BE(0x9, 0x8),
	BPL = NATIVE_ENDIAN_VALUE_LE_BE(0xa, 0xb),
	BPH = NATIVE_ENDIAN_VALUE_LE_BE(0xb, 0xa),
	IXL = NATIVE_ENDIAN_VALUE_LE_BE(0xc, 0xd),
	IXH = NATIVE_ENDIAN_VALUE_LE_BE(0xd, 0xc),
	IYL = NATIVE_ENDIAN_VALUE_LE_BE(0xe, 0xf),
	IYH = NATIVE_ENDIAN_VALUE_LE_BE(0xf, 0xe)
};


#define CF      (m_CarryVal!=0)
#define SF      (m_SignVal<0)
#define ZF      (m_ZeroVal==0)
#define PF      m_parity_table[(UINT8)m_ParityVal]
#define AF      (m_AuxVal!=0)
#define OF      (m_OverVal!=0)
#define MD      (m_MF!=0)


/***************************************************************************/
/* cpu state                                                               */
/***************************************************************************/


/* The interrupt number of a pending external interrupt pending NMI is 2.   */
/* For INTR interrupts, the level is caught on the bus during an INTA cycle */

#define INT_IRQ 0x01
#define NMI_IRQ 0x02

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

const device_type V30MZ = &device_creator<v30mz_cpu_device>;


v30mz_cpu_device::v30mz_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: cpu_device(mconfig, V30MZ, "V30MZ", tag, owner, clock, "v30mz", __FILE__)
	, m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0)
	, m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
	, m_ip(0)
	, m_TF(0)
	, m_int_vector(0)
	, m_pc(0)
{
	static const BREGS reg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH };

	/* Set up parity lookup table. */
	for (UINT16 i = 0;i < 256; i++)
	{
		UINT16 c = 0;
		for (UINT16 j = i; j > 0; j >>= 1)
		{
			if (j & 1) c++;
		}
		m_parity_table[i] = !(c & 1);
	}

	for (UINT16 i = 0; i < 256; i++)
	{
		m_Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
		m_Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ;
	}

	for (UINT16 i = 0xc0; i < 0x100; i++)
	{
		m_Mod_RM.RM.w[i] = (WREGS)( i & 7 );
		m_Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
	}
}


void v30mz_cpu_device::device_start()
{
	m_program = &space(AS_PROGRAM);
	m_direct = &m_program->direct();
	m_io = &space(AS_IO);

	save_item(NAME(m_regs.w));
	save_item(NAME(m_sregs));
	save_item(NAME(m_ip));
	save_item(NAME(m_TF));
	save_item(NAME(m_IF));
	save_item(NAME(m_DF));
	save_item(NAME(m_MF));
	save_item(NAME(m_SignVal));
	save_item(NAME(m_int_vector));
	save_item(NAME(m_pending_irq));
	save_item(NAME(m_nmi_state));
	save_item(NAME(m_irq_state));
	save_item(NAME(m_AuxVal));
	save_item(NAME(m_OverVal));
	save_item(NAME(m_ZeroVal));
	save_item(NAME(m_CarryVal));
	save_item(NAME(m_ParityVal));
	save_item(NAME(m_seg_prefix));
	save_item(NAME(m_seg_prefix_next));

	// Register state for debugger
//  state_add( NEC_PC, "PC", m_PC ).callimport().callexport().formatstr("%04X");
	state_add( NEC_IP, "IP", m_ip         ).callimport().callexport().formatstr("%04X");
	state_add( NEC_SP, "SP", m_regs.w[SP] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_AW, "AW", m_regs.w[AW] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_CW, "CW", m_regs.w[CS] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_DW, "DW", m_regs.w[DW] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_BW, "BW", m_regs.w[BW] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_BP, "BP", m_regs.w[BP] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_IX, "IX", m_regs.w[IX] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_IY, "IY", m_regs.w[IY] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_ES, "ES", m_sregs[ES] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_CS, "CS", m_sregs[CS] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_SS, "SS", m_sregs[SS] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_DS, "DS", m_sregs[DS] ).callimport().callexport().formatstr("%04X");
	state_add( NEC_VECTOR, "V", m_int_vector).callimport().callexport().formatstr("%02X");

	state_add(STATE_GENPC, "curpc", m_pc).callimport().callexport().formatstr("%05X");
	state_add(STATE_GENFLAGS, "GENFLAGS", m_TF).callimport().callexport().formatstr("%16s").noshow();

	m_icountptr = &m_icount;
}


void v30mz_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
{
	switch (entry.index())
	{
		case STATE_GENPC:
			string.printf("%08X", pc() );
			break;

		case STATE_GENFLAGS:
			{
				UINT16 flags = CompressFlags();
				string.printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
					flags & 0x8000 ? 'M':'.',
					flags & 0x4000 ? '?':'.',
					flags & 0x2000 ? '?':'.',
					flags & 0x1000 ? '?':'.',
					flags & 0x0800 ? 'O':'.',
					flags & 0x0400 ? 'D':'.',
					flags & 0x0200 ? 'I':'.',
					flags & 0x0100 ? 'T':'.',
					flags & 0x0080 ? 'S':'.',
					flags & 0x0040 ? 'Z':'.',
					flags & 0x0020 ? '?':'.',
					flags & 0x0010 ? 'A':'.',
					flags & 0x0008 ? '?':'.',
					flags & 0x0004 ? 'P':'.',
					flags & 0x0002 ? 'N':'.',
					flags & 0x0001 ? 'C':'.');
			}
			break;
	}
}


void v30mz_cpu_device::device_reset()
{
	m_ZeroVal = 1;
	m_ParityVal = 1;
	m_regs.w[AW] = 0;
	m_regs.w[CW] = 0;
	m_regs.w[DW] = 0;
	m_regs.w[BW] = 0;
	m_regs.w[SP] = 0;
	m_regs.w[BP] = 0;
	m_regs.w[IX] = 0;
	m_regs.w[IY] = 0;
	m_sregs[ES] = 0;
	m_sregs[CS] = 0xffff;
	m_sregs[SS] = 0;
	m_sregs[DS] = 0;
	m_ip = 0;
	m_SignVal = 0;
	m_AuxVal = 0;
	m_OverVal = 0;
	m_CarryVal = 0;
	m_TF = 0;
	m_IF = 0;
	m_DF = 0;
	m_MF = 1;
	m_int_vector = 0;
	m_pending_irq = 0;
	m_nmi_state = 0;
	m_irq_state = 0;
	m_no_interrupt = 0;
	m_fire_trap = 0;
	m_prefix_base = 0;
	m_seg_prefix = false;
	m_seg_prefix_next = false;
	m_ea = 0;
	m_eo = 0;
	m_e16 = 0;
	m_modrm = 0;
	m_dst = 0;
	m_src = 0;
}


inline UINT32 v30mz_cpu_device::pc()
{
	m_pc = ( m_sregs[CS] << 4 ) + m_ip;
	return m_pc;
}


inline UINT8 v30mz_cpu_device::read_byte(UINT32 addr)
{
	return m_program->read_byte(addr);
}


inline UINT16 v30mz_cpu_device::read_word(UINT32 addr)
{
	return m_program->read_byte(addr) | ( m_program->read_byte(addr+1) << 8 );
}


inline void v30mz_cpu_device::write_byte(UINT32 addr, UINT8 data)
{
	m_program->write_byte(addr, data);
}


inline void v30mz_cpu_device::write_word(UINT32 addr, UINT16 data)
{
	m_program->write_byte( addr, data & 0xff );
	m_program->write_byte( addr + 1, data >> 8 );
}


inline UINT8 v30mz_cpu_device::read_port(UINT16 port)
{
	return m_io->read_byte(port);
}


inline void v30mz_cpu_device::write_port(UINT16 port, UINT8 data)
{
	m_io->write_byte(port, data);
}


inline UINT8 v30mz_cpu_device::fetch_op()
{
	UINT8 data = m_direct->read_decrypted_byte( pc() );
	m_ip++;
	return data;
}


inline UINT8 v30mz_cpu_device::fetch()
{
	UINT8 data = m_direct->read_raw_byte( pc() );
	m_ip++;
	return data;
}


inline UINT16 v30mz_cpu_device::fetch_word()
{
	UINT16 data = fetch();
	data |= ( fetch() << 8 );
	return data;
}


inline UINT8 v30mz_cpu_device::repx_op()
{
	UINT8 next = fetch_op();
	bool seg_prefix = false;
	int seg = 0;

	switch (next)
	{
	case 0x26:
		seg_prefix = true;
		seg = ES;
		break;
	case 0x2e:
		seg_prefix = true;
		seg = CS;
		break;
	case 0x36:
		seg_prefix = true;
		seg = SS;
		break;
	case 0x3e:
		seg_prefix = true;
		seg = DS;
		break;
	}

	if ( seg_prefix )
	{
		m_seg_prefix = true;
		m_seg_prefix_next = true;
		m_prefix_base = m_sregs[seg] << 4;
		next = fetch_op();
		CLK(2);
	}

	return next;
}


inline void v30mz_cpu_device::CLK(UINT32 cycles)
{
	m_icount -= cycles;
}


inline void v30mz_cpu_device::CLKM(UINT32 cycles_reg, UINT32 cycles_mem)
{
	m_icount -= ( m_modrm >= 0xc0 ) ? cycles_reg : cycles_mem;
}


inline UINT32 v30mz_cpu_device::default_base(int seg)
{
	if ( m_seg_prefix && (seg==DS || seg==SS) )
	{
		return m_prefix_base;
	}
	else
	{
		return m_sregs[seg] << 4;
	}
}


inline UINT32 v30mz_cpu_device::get_ea()
{
	switch( m_modrm & 0xc7 )
	{
	case 0x00:
		m_eo = m_regs.w[BW] + m_regs.w[IX];
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x01:
		m_eo = m_regs.w[BW] + m_regs.w[IY];
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x02:
		m_eo = m_regs.w[BP] + m_regs.w[IX];
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x03:
		m_eo = m_regs.w[BP] + m_regs.w[IY];
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x04:
		m_eo = m_regs.w[IX];
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x05:
		m_eo = m_regs.w[IY];
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x06:
		m_eo = fetch_word();
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x07:
		m_eo = m_regs.w[BW];
		m_ea = default_base(DS) + m_eo;
		break;

	case 0x40:
		m_eo = m_regs.w[BW] + m_regs.w[IX] + (INT8)fetch();
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x41:
		m_eo = m_regs.w[BW] + m_regs.w[IY] + (INT8)fetch();
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x42:
		m_eo = m_regs.w[BP] + m_regs.w[IX] + (INT8)fetch();
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x43:
		m_eo = m_regs.w[BP] + m_regs.w[IY] + (INT8)fetch();
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x44:
		m_eo = m_regs.w[IX] + (INT8)fetch();
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x45:
		m_eo = m_regs.w[IY] + (INT8)fetch();
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x46:
		m_eo = m_regs.w[BP] + (INT8)fetch();
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x47:
		m_eo = m_regs.w[BW] + (INT8)fetch();
		m_ea = default_base(DS) + m_eo;
		break;

	case 0x80:
		m_e16 = fetch_word();
		m_eo = m_regs.w[BW] + m_regs.w[IX] + (INT16)m_e16;
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x81:
		m_e16 = fetch_word();
		m_eo = m_regs.w[BW] + m_regs.w[IY] + (INT16)m_e16;
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x82:
		m_e16 = fetch_word();
		m_eo = m_regs.w[BP] + m_regs.w[IX] + (INT16)m_e16;
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x83:
		m_e16 = fetch_word();
		m_eo = m_regs.w[BP] + m_regs.w[IY] + (INT16)m_e16;
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x84:
		m_e16 = fetch_word();
		m_eo = m_regs.w[IX] + (INT16)m_e16;
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x85:
		m_e16 = fetch_word();
		m_eo = m_regs.w[IY] + (INT16)m_e16;
		m_ea = default_base(DS) + m_eo;
		break;
	case 0x86:
		m_e16 = fetch_word();
		m_eo = m_regs.w[BP] + (INT16)m_e16;
		m_ea = default_base(SS) + m_eo;
		break;
	case 0x87:
		m_e16 = fetch_word();
		m_eo = m_regs.w[BW] + (INT16)m_e16;
		m_ea = default_base(DS) + m_eo;
		break;
	}

	return m_ea;
}


inline void v30mz_cpu_device::PutbackRMByte(UINT8 data)
{
	if ( m_modrm >= 0xc0 )
	{
		m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ] = data;
	}
	else
	{
		write_byte( m_ea, data );
	}
}


inline void v30mz_cpu_device::PutbackRMWord(UINT16 data)
{
	if ( m_modrm >= 0xc0 )
	{
		m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ] = data;
	}
	else
	{
		write_word( m_ea, data );
	}
}

inline void v30mz_cpu_device::PutImmRMWord()
{
	if ( m_modrm >= 0xc0 )
	{
		m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ] = fetch_word();
	}
	else
	{
		UINT32 addr = get_ea();
		write_word( addr, fetch_word() );
	}
}

inline void v30mz_cpu_device::PutRMWord(UINT16 val)
{
	if ( m_modrm >= 0xc0 )
	{
		m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ] = val;
	}
	else
	{
		write_word( get_ea(), val );
	}
}


inline void v30mz_cpu_device::PutRMByte(UINT8 val)
{
	if ( m_modrm >= 0xc0 )
	{
		m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ] = val;
	}
	else
	{
		write_byte( get_ea(), val );
	}
}


inline void v30mz_cpu_device::PutImmRMByte()
{
	if ( m_modrm >= 0xc0 )
	{
		m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ] = fetch();
	}
	else
	{
		UINT32 addr = get_ea();
		write_byte( addr, fetch() );
	}
}


inline void v30mz_cpu_device::DEF_br8()
{
	m_modrm = fetch();
	m_src = RegByte();
	m_dst = GetRMByte();
}


inline void v30mz_cpu_device::DEF_wr16()
{
	m_modrm = fetch();
	m_src = RegWord();
	m_dst = GetRMWord();
}


inline void v30mz_cpu_device::DEF_r8b()
{
	m_modrm = fetch();
	m_dst = RegByte();
	m_src = GetRMByte();
}


inline void v30mz_cpu_device::DEF_r16w()
{
	m_modrm = fetch();
	m_dst = RegWord();
	m_src = GetRMWord();
}


inline void v30mz_cpu_device::DEF_ald8()
{
	m_src = fetch();
	m_dst = m_regs.b[AL];
}


inline void v30mz_cpu_device::DEF_axd16()
{
	m_src = fetch_word();
	m_dst = m_regs.w[AW];
}



inline void v30mz_cpu_device::RegByte(UINT8 data)
{
	m_regs.b[ m_Mod_RM.reg.b[ m_modrm ] ] = data;
}


inline void v30mz_cpu_device::RegWord(UINT16 data)
{
	m_regs.w[ m_Mod_RM.reg.w[ m_modrm ] ] = data;
}


inline UINT8 v30mz_cpu_device::RegByte()
{
	return m_regs.b[ m_Mod_RM.reg.b[ m_modrm ] ];
}


inline UINT16 v30mz_cpu_device::RegWord()
{
	return m_regs.w[ m_Mod_RM.reg.w[ m_modrm ] ];
}


inline UINT16 v30mz_cpu_device::GetRMWord()
{
	if ( m_modrm >= 0xc0 )
	{
		return m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ];
	}
	else
	{
		return read_word( get_ea() );
	}
}


inline UINT16 v30mz_cpu_device::GetnextRMWord()
{
	UINT32 addr = ( m_ea & 0xf0000 ) | ( ( m_ea + 2 ) & 0xffff );

	return read_word( addr );
}


inline UINT8 v30mz_cpu_device::GetRMByte()
{
	if ( m_modrm >= 0xc0 )
	{
		return m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ];
	}
	else
	{
		return read_byte( get_ea() );
	}
}


inline void v30mz_cpu_device::PutMemB(int seg, UINT16 offset, UINT8 data)
{
	write_byte( default_base( seg ) + offset, data);
}


inline void v30mz_cpu_device::PutMemW(int seg, UINT16 offset, UINT16 data)
{
	PutMemB( seg, offset, data & 0xff);
	PutMemB( seg, offset+1, data >> 8);
}


inline UINT8 v30mz_cpu_device::GetMemB(int seg, UINT16 offset)
{
	return read_byte( default_base(seg) + offset );
}


inline UINT16 v30mz_cpu_device::GetMemW(int seg, UINT16 offset)
{
	return GetMemB(seg, offset) | ( GetMemB(seg, offset + 1) << 8 );
}


// Setting flags

inline void v30mz_cpu_device::set_CFB(UINT32 x)
{
	m_CarryVal = x & 0x100;
}

inline void v30mz_cpu_device::set_CFW(UINT32 x)
{
	m_CarryVal = x & 0x10000;
}

inline void v30mz_cpu_device::set_AF(UINT32 x,UINT32 y,UINT32 z)
{
	m_AuxVal = (x ^ (y ^ z)) & 0x10;
}

inline void v30mz_cpu_device::set_SF(UINT32 x)
{
	m_SignVal = x;
}

inline void v30mz_cpu_device::set_ZF(UINT32 x)
{
	m_ZeroVal = x;
}

inline void v30mz_cpu_device::set_PF(UINT32 x)
{
	m_ParityVal = x;
}

inline void v30mz_cpu_device::set_SZPF_Byte(UINT32 x)
{
	m_SignVal = m_ZeroVal = m_ParityVal = (INT8)x;
}

inline void v30mz_cpu_device::set_SZPF_Word(UINT32 x)
{
	m_SignVal = m_ZeroVal = m_ParityVal = (INT16)x;
}

inline void v30mz_cpu_device::set_OFW_Add(UINT32 x,UINT32 y,UINT32 z)
{
	m_OverVal = (x ^ y) & (x ^ z) & 0x8000;
}

inline void v30mz_cpu_device::set_OFB_Add(UINT32 x,UINT32 y,UINT32 z)
{
	m_OverVal = (x ^ y) & (x ^ z) & 0x80;
}

inline void v30mz_cpu_device::set_OFW_Sub(UINT32 x,UINT32 y,UINT32 z)
{
	m_OverVal = (z ^ y) & (z ^ x) & 0x8000;
}

inline void v30mz_cpu_device::set_OFB_Sub(UINT32 x,UINT32 y,UINT32 z)
{
	m_OverVal = (z ^ y) & (z ^ x) & 0x80;
}


inline UINT16 v30mz_cpu_device::CompressFlags()
{
	return (CF ? 1 : 0)
		| (PF ? 4 : 0)
		| (AF ? 0x10 : 0)
		| (ZF ? 0x40 : 0)
		| (SF ? 0x80 : 0)
		| (m_TF << 8)
		| (m_IF << 9)
		| (m_DF << 10)
		| (OF << 11)
		| (MD << 15);
}

inline void v30mz_cpu_device::ExpandFlags(UINT16 f)
{
	m_CarryVal = (f) & 1;
	m_ParityVal = !((f) & 4);
	m_AuxVal = (f) & 16;
	m_ZeroVal = !((f) & 64);
	m_SignVal = (f) & 128 ? -1 : 0;
	m_TF = ((f) & 256) == 256;
	m_IF = ((f) & 512) == 512;
	m_DF = ((f) & 1024) == 1024;
	m_OverVal = (f) & 2048;
	m_MF = ((f) & 0x8000) == 0x8000;
}

inline void v30mz_cpu_device::i_insb()
{
	PutMemB( ES, m_regs.w[IY], read_port( m_regs.w[DW] ) );
	m_regs.w[IY] += -2 * m_DF + 1;
	CLK(6);
}

inline void v30mz_cpu_device::i_insw()
{
	PutMemB( ES, m_regs.w[IY], read_port( m_regs.w[DW] ) );
	PutMemB( ES, (m_regs.w[IY] + 1) & 0xffff, read_port((m_regs.w[DW]+1)&0xffff));
	m_regs.w[IY] += -4 * m_DF + 2;
	CLK(6);
}

inline void v30mz_cpu_device::i_outsb()
{
	write_port( m_regs.w[DW], GetMemB( DS, m_regs.w[IX] ) );
	m_regs.w[IX] += -2 * m_DF + 1;
	CLK(7);
}

inline void v30mz_cpu_device::i_outsw()
{
	write_port( m_regs.w[DW], GetMemB( DS, m_regs.w[IX] ) );
	write_port( (m_regs.w[DW]+1)&0xffff, GetMemB( DS, (m_regs.w[IX]+1)&0xffff ) );
	m_regs.w[IX] += -4 * m_DF + 2;
	CLK(7);
}

inline void v30mz_cpu_device::i_movsb()
{
	UINT8 tmp = GetMemB( DS, m_regs.w[IX] );
	PutMemB( ES, m_regs.w[IY], tmp);
	m_regs.w[IY] += -2 * m_DF + 1;
	m_regs.w[IX] += -2 * m_DF + 1;
	CLK(5);
}

inline void v30mz_cpu_device::i_movsw()
{
	UINT16 tmp = GetMemW( DS, m_regs.w[IX] );
	PutMemW( ES, m_regs.w[IY], tmp );
	m_regs.w[IY] += -4 * m_DF + 2;
	m_regs.w[IX] += -4 * m_DF + 2;
	CLK(5);
}

inline void v30mz_cpu_device::i_cmpsb()
{
	m_src = GetMemB( ES, m_regs.w[IY] );
	m_dst = GetMemB( DS, m_regs.w[IX] );
	SUBB();
	m_regs.w[IY] += -2 * m_DF + 1;
	m_regs.w[IX] += -2 * m_DF + 1;
	CLK(6);
}

inline void v30mz_cpu_device::i_cmpsw()
{
	m_src = GetMemW( ES, m_regs.w[IY] );
	m_dst = GetMemW( DS, m_regs.w[IX] );
	SUBW();
	m_regs.w[IY] += -4 * m_DF + 2;
	m_regs.w[IX] += -4 * m_DF + 2;
	CLK(6);
}

inline void v30mz_cpu_device::i_stosb()
{
	PutMemB( ES, m_regs.w[IY], m_regs.b[AL] );
	m_regs.w[IY] += -2 * m_DF + 1;
	CLK(3);
}

inline void v30mz_cpu_device::i_stosw()
{
	PutMemW( ES, m_regs.w[IY], m_regs.w[AW] );
	m_regs.w[IY] += -4 * m_DF + 2;
	CLK(3);
}

inline void v30mz_cpu_device::i_lodsb()
{
	m_regs.b[AL] = GetMemB( DS, m_regs.w[IX] );
	m_regs.w[IX] += -2 * m_DF + 1;
	CLK(3);
}

inline void v30mz_cpu_device::i_lodsw()
{
	m_regs.w[AW] = GetMemW( DS, m_regs.w[IX] );
	m_regs.w[IX] += -4 * m_DF + 2;
	CLK(3);
}

inline void v30mz_cpu_device::i_scasb()
{
	m_src = GetMemB( ES, m_regs.w[IY] );
	m_dst = m_regs.b[AL];
	SUBB();
	m_regs.w[IY] += -2 * m_DF + 1;
	CLK(4);
}

inline void v30mz_cpu_device::i_scasw()
{
	m_src = GetMemW( ES, m_regs.w[IY] );
	m_dst = m_regs.w[AW];
	SUBW();
	m_regs.w[IY] += -4 * m_DF + 2;
	CLK(4);
}


inline void v30mz_cpu_device::i_popf()
{
	UINT32 tmp = POP();

	ExpandFlags(tmp);
	CLK(3);
	if (m_TF)
	{
		m_fire_trap = 1;
	}
}


inline void v30mz_cpu_device::ADDB()
{
	UINT32 res = m_dst + m_src;

	set_CFB(res);
	set_OFB_Add(res,m_src,m_dst);
	set_AF(res,m_src,m_dst);
	set_SZPF_Byte(res);
	m_dst = res & 0xff;
}


inline void v30mz_cpu_device::ADDW()
{
	UINT32 res = m_dst + m_src;

	set_CFW(res);
	set_OFW_Add(res,m_src,m_dst);
	set_AF(res,m_src,m_dst);
	set_SZPF_Word(res);
	m_dst = res & 0xffff;
}


inline void v30mz_cpu_device::SUBB()
{
	UINT32 res = m_dst - m_src;

	set_CFB(res);
	set_OFB_Sub(res,m_src,m_dst);
	set_AF(res,m_src,m_dst);
	set_SZPF_Byte(res);
	m_dst = res & 0xff;
}


inline void v30mz_cpu_device::SUBW()
{
	UINT32 res = m_dst - m_src;

	set_CFW(res);
	set_OFW_Sub(res,m_src,m_dst);
	set_AF(res,m_src,m_dst);
	set_SZPF_Word(res);
	m_dst = res & 0xffff;
}


inline void v30mz_cpu_device::ORB()
{
	m_dst |= m_src;
	m_CarryVal = m_OverVal = m_AuxVal = 0;
	set_SZPF_Byte(m_dst);
}


inline void v30mz_cpu_device::ORW()
{
	m_dst |= m_src;
	m_CarryVal = m_OverVal = m_AuxVal = 0;
	set_SZPF_Word(m_dst);
}


inline void v30mz_cpu_device::ANDB()
{
	m_dst &= m_src;
	m_CarryVal = m_OverVal = m_AuxVal = 0;
	set_SZPF_Byte(m_dst);
}


inline void v30mz_cpu_device::ANDW()
{
	m_dst &= m_src;
	m_CarryVal = m_OverVal = m_AuxVal = 0;
	set_SZPF_Word(m_dst);
}


inline void v30mz_cpu_device::XORB()
{
	m_dst ^= m_src;
	m_CarryVal = m_OverVal = m_AuxVal = 0;
	set_SZPF_Byte(m_dst);
}


inline void v30mz_cpu_device::XORW()
{
	m_dst ^= m_src;
	m_CarryVal = m_OverVal = m_AuxVal = 0;
	set_SZPF_Word(m_dst);
}


inline void v30mz_cpu_device::ROL_BYTE()
{
	m_CarryVal = m_dst & 0x80;
	m_dst = (m_dst << 1) | ( CF ? 1 : 0 );
}

inline void v30mz_cpu_device::ROL_WORD()
{
	m_CarryVal = m_dst & 0x8000;
	m_dst = (m_dst << 1) | ( CF ? 1 : 0 );
}

inline void v30mz_cpu_device::ROR_BYTE()
{
	m_CarryVal = m_dst & 0x1;
	m_dst = (m_dst >> 1) | (CF ? 0x80 : 0x00);
}

inline void v30mz_cpu_device::ROR_WORD()
{
	m_CarryVal = m_dst & 0x1;
	m_dst = (m_dst >> 1) + (CF ? 0x8000 : 0x0000);
}

inline void v30mz_cpu_device::ROLC_BYTE()
{
	m_dst = (m_dst << 1) | ( CF ? 1 : 0 );
	set_CFB(m_dst);
}

inline void v30mz_cpu_device::ROLC_WORD()
{
	m_dst = (m_dst << 1) | ( CF ? 1 : 0 );
	set_CFW(m_dst);
}

inline void v30mz_cpu_device::RORC_BYTE()
{
	m_dst |= ( CF ? 0x100 : 0x00);
	m_CarryVal = m_dst & 0x01;
	m_dst >>= 1;
}

inline void v30mz_cpu_device::RORC_WORD()
{
	m_dst |= ( CF ? 0x10000 : 0);
	m_CarryVal = m_dst & 0x01;
	m_dst >>= 1;
}

inline void v30mz_cpu_device::SHL_BYTE(UINT8 c)
{
	m_icount -= c;
	m_dst <<= c;
	set_CFB(m_dst);
	set_SZPF_Byte(m_dst);
	PutbackRMByte(m_dst);
}

inline void v30mz_cpu_device::SHL_WORD(UINT8 c)
{
	m_icount -= c;
	m_dst <<= c;
	set_CFW(m_dst);
	set_SZPF_Word(m_dst);
	PutbackRMWord(m_dst);
}

inline void v30mz_cpu_device::SHR_BYTE(UINT8 c)
{
	m_icount -= c;
	m_dst >>= c-1;
	m_CarryVal = m_dst & 0x1;
	m_dst >>= 1;
	set_SZPF_Byte(m_dst);
	PutbackRMByte(m_dst);
}

inline void v30mz_cpu_device::SHR_WORD(UINT8 c)
{
	m_icount -= c;
	m_dst >>= c-1;
	m_CarryVal = m_dst & 0x1;
	m_dst >>= 1;
	set_SZPF_Word(m_dst);
	PutbackRMWord(m_dst);
}

inline void v30mz_cpu_device::SHRA_BYTE(UINT8 c)
{
	m_icount -= c;
	m_dst = ((INT8)m_dst) >> (c-1);
	m_CarryVal = m_dst & 0x1;
	m_dst = m_dst >> 1;
	set_SZPF_Byte(m_dst);
	PutbackRMByte(m_dst);
}

inline void v30mz_cpu_device::SHRA_WORD(UINT8 c)
{
	m_icount -= c;
	m_dst = ((INT16)m_dst) >> (c-1);
	m_CarryVal = m_dst & 0x1;
	m_dst = m_dst >> 1;
	set_SZPF_Word(m_dst);
	PutbackRMWord(m_dst);
}


inline void v30mz_cpu_device::XchgAWReg(UINT8 reg)
{
	UINT16 tmp = m_regs.w[reg];

	m_regs.w[reg] = m_regs.w[AW];
	m_regs.w[AW] = tmp;
}


inline void v30mz_cpu_device::IncWordReg(UINT8 reg)
{
	UINT32 tmp = m_regs.w[reg];
	UINT32 tmp1 = tmp+1;

	m_OverVal = (tmp == 0x7fff);
	set_AF(tmp1,tmp,1);
	set_SZPF_Word(tmp1);
	m_regs.w[reg] = tmp1;
}


inline void v30mz_cpu_device::DecWordReg(UINT8 reg)
{
	UINT32 tmp = m_regs.w[reg];
	UINT32 tmp1 = tmp-1;

	m_OverVal = (tmp == 0x8000);
	set_AF(tmp1,tmp,1);
	set_SZPF_Word(tmp1);
	m_regs.w[reg] = tmp1;
}


inline void v30mz_cpu_device::PUSH(UINT16 data)
{
	m_regs.w[SP] -= 2;
	write_word( ( m_sregs[SS] << 4 ) + m_regs.w[SP], data );
}


inline UINT16 v30mz_cpu_device::POP()
{
	UINT16 data = read_word( ( m_sregs[SS] << 4 ) + m_regs.w[SP] );

	m_regs.w[SP] += 2;
	return data;
}


inline void v30mz_cpu_device::JMP(bool cond)
{
	int rel  = (int)((INT8)fetch());

	if (cond)
	{
		m_ip += rel;
		CLK(9);
	}
	CLK(1);
}


inline void v30mz_cpu_device::ADJ4(INT8 param1,INT8 param2)
{
	if (AF || ((m_regs.b[AL] & 0xf) > 9))
	{
		UINT16 tmp;
		tmp = m_regs.b[AL] + param1;
		m_regs.b[AL] = tmp;
		m_AuxVal = 1;
		m_CarryVal |= tmp & 0x100;
	}
	if (CF || (m_regs.b[AL]>0x9f))
	{
		m_regs.b[AL] += param2;
		m_CarryVal = 1;
	}
	set_SZPF_Byte(m_regs.b[AL]);
}


inline void v30mz_cpu_device::ADJB(INT8 param1, INT8 param2)
{
	if (AF || ((m_regs.b[AL] & 0xf) > 9))
	{
		m_regs.b[AL] += param1;
		m_regs.b[AH] += param2;
		m_AuxVal = 1;
		m_CarryVal = 1;
	}
	else
	{
		m_AuxVal = 0;
		m_CarryVal = 0;
	}
	m_regs.b[AL] &= 0x0F;
}


void v30mz_cpu_device::interrupt(int int_num)
{
	PUSH( CompressFlags() );
	CLK(2);
	m_TF = m_IF = 0;

	if (int_num == -1)
	{
		int_num = standard_irq_callback(0);

		m_irq_state = CLEAR_LINE;
		m_pending_irq &= ~INT_IRQ;
	}

	UINT16 dest_off = read_word( int_num * 4 + 0 );
	UINT16 dest_seg = read_word( int_num * 4 + 2 );

	PUSH(m_sregs[CS]);
	PUSH(m_ip);
	m_ip = dest_off;
	m_sregs[CS] = dest_seg;
}


void v30mz_cpu_device::execute_set_input( int inptnum, int state )
{
	if (inptnum == INPUT_LINE_NMI)
	{
		if ( m_nmi_state == state )
		{
			return;
		}
		m_nmi_state = state;
		if (state != CLEAR_LINE)
		{
			m_pending_irq |= NMI_IRQ;
		}
	}
	else
	{
		m_irq_state = state;
		if (state == CLEAR_LINE)
		{
			m_pending_irq &= ~INT_IRQ;
		}
		else
		{
			m_pending_irq |= INT_IRQ;
		}
	}
}


offs_t v30mz_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
	extern CPU_DISASSEMBLE( nec );
	return CPU_DISASSEMBLE_NAME(nec)(this, buffer, pc, oprom, opram, options);
}


void v30mz_cpu_device::execute_run()
{
	while(m_icount > 0 )
	{
		if ( m_seg_prefix_next )
		{
			m_seg_prefix = true;
			m_seg_prefix_next = false;
		}
		else
		{
			m_seg_prefix = false;

				/* Dispatch IRQ */
			if ( m_pending_irq && m_no_interrupt == 0 )
			{
				if ( m_pending_irq & NMI_IRQ )
				{
					interrupt(NEC_NMI_INT_VECTOR);
					m_pending_irq &= ~NMI_IRQ;
				}
				else if ( m_IF )
				{
					/* the actual vector is retrieved after pushing flags */
					/* and clearing the IF */
					interrupt(-1);
				}
			}

			/* No interrupt allowed between last instruction and this one */
			if ( m_no_interrupt )
			{
				m_no_interrupt--;
			}

			/* trap should allow one instruction to be executed */
			if ( m_fire_trap )
			{
				if ( m_fire_trap >= 2 )
				{
					interrupt(1);
					m_fire_trap = 0;
				}
				else
				{
					m_fire_trap++;
				}
			}
		}

		debugger_instruction_hook( this, pc() );

		UINT8 op = fetch_op();

		switch(op)
		{
			case 0x00: // i_add_br8
				DEF_br8();
				ADDB();
				PutbackRMByte(m_dst);
				CLKM(1,3);
				break;

			case 0x01: // i_add_wr16
				DEF_wr16();
				ADDW();
				PutbackRMWord(m_dst);
				CLKM(1,3);
				break;

			case 0x02: // i_add_r8b
				DEF_r8b();
				ADDB();
				RegByte(m_dst);
				CLKM(1,2);
				break;

			case 0x03: // i_add_r16w
				DEF_r16w();
				ADDW();
				RegWord(m_dst);
				CLKM(1,2);
				break;

			case 0x04: // i_add_ald8
				DEF_ald8();
				ADDB();
				m_regs.b[AL] = m_dst;
				CLK(1);
				break;

			case 0x05: // i_add_axd16
				DEF_axd16();
				ADDW();
				m_regs.w[AW] = m_dst;
				CLK(1);
				break;

			case 0x06: // i_push_es
				PUSH(m_sregs[ES]);
				CLK(2);
				break;

			case 0x07: // i_pop_es
				m_sregs[ES] = POP();
				CLK(3);
				break;

			case 0x08: // i_or_br8
				DEF_br8();
				ORB();
				PutbackRMByte(m_dst);
				CLKM(1,3);
				break;

			case 0x09: // i_or_wr16
				DEF_wr16();
				ORW();
				PutbackRMWord(m_dst);
				CLKM(1,3);
				break;

			case 0x0a: // i_or_r8b
				DEF_r8b();
				ORB();
				RegByte(m_dst);
				CLKM(1,2);
				break;

			case 0x0b: // i_or_r16w
				DEF_r16w();
				ORW();
				RegWord(m_dst);
				CLKM(1,2);
				break;

			case 0x0c: // i_or_ald8
				DEF_ald8();
				ORB();
				m_regs.b[AL] = m_dst;
				CLK(1);
				break;

			case 0x0d: // i_or_axd16
				DEF_axd16();
				ORW();
				m_regs.w[AW] = m_dst;
				CLK(1);
				break;

			case 0x0e: // i_push_cs
				PUSH(m_sregs[CS]);
				CLK(2);
				break;

			case 0x0f: // i_pre_nec
				{
					UINT32 tmp, tmp2;

					switch ( fetch() )
					{
					case 0x10:  /* Test */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = m_regs.b[CL] & 0x7;
						m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0;
						m_CarryVal = m_OverVal = 0;
						break;
					case 0x11:  /* Test */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = m_regs.b[CL] & 0xf;
						m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0;
						m_CarryVal = m_OverVal = 0;
						break;
					case 0x12:  /* Clr */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = m_regs.b[CL] & 0x7;
						tmp &= ~(1<<tmp2);
						PutbackRMByte(tmp);
						break;
					case 0x13:  /* Clr */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = m_regs.b[CL] & 0xf;
						tmp &= ~(1<<tmp2);
						PutbackRMWord(tmp);
						break;
					case 0x14:  /* Set */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = m_regs.b[CL] & 0x7;
						tmp |= (1<<tmp2);
						PutbackRMByte(tmp);
						break;
					case 0x15:  /* Set */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = m_regs.b[CL] & 0xf;
						tmp |= (1<<tmp2);
						PutbackRMWord(tmp);
						break;
					case 0x16:  /* Not */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = m_regs.b[CL] & 0x7;
						tmp ^= (1 << tmp2);
						PutbackRMByte(tmp);
						break;
					case 0x17:  /* Not */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = m_regs.b[CL] & 0xf;
						tmp ^= (1 << tmp2);
						PutbackRMWord(tmp);
						break;

					case 0x18:  /* Test */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = fetch() & 0x7;
						m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0;
						m_CarryVal = m_OverVal = 0;
						break;
					case 0x19:  /* Test */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = fetch() & 0xf;
						m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0;
						m_CarryVal = m_OverVal = 0;
						break;
					case 0x1a:  /* Clr */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = fetch() & 0x7;
						tmp &= ~(1<<tmp2);
						PutbackRMByte(tmp);
						break;
					case 0x1b:  /* Clr */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = fetch() & 0xf;
						tmp &= ~(1<<tmp2);
						PutbackRMWord(tmp);
						break;
					case 0x1c:  /* Set */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = fetch() & 0x7;
						tmp |= (1<<tmp2);
						PutbackRMByte(tmp);
						break;
					case 0x1d:  /* Set */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = fetch() & 0xf;
						tmp |= (1<<tmp2);
						PutbackRMWord(tmp);
						break;
					case 0x1e:  /* Not */
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = fetch() & 0x7;
						tmp ^= (1 << tmp2);
						PutbackRMByte(tmp);
						break;
					case 0x1f:  /* Not */
						m_modrm = fetch();
						tmp = GetRMWord();
						tmp2 = fetch() & 0xf;
						tmp ^= (1 << tmp2);
						PutbackRMWord(tmp);
						break;

					case 0x20:
						{
							int count = (m_regs.b[CL]+1)/2;
							UINT16 di = m_regs.w[IY];
							UINT16 si = m_regs.w[IX];
							if (m_seg_prefix)
							{
								logerror("%s: %06x: Warning: seg_prefix defined for add4s\n", tag(), pc());
							}
							m_ZeroVal = m_CarryVal = 0;
							for (int i=0;i<count;i++)
							{
								CLK(19);
								tmp = GetMemB(DS, si);
								tmp2 = GetMemB(ES, di);
								int v1 = (tmp>>4)*10 + (tmp&0xf);
								int v2 = (tmp2>>4)*10 + (tmp2&0xf);
								int result = v1 + v2 + m_CarryVal;
								m_CarryVal = result > 99 ? 1 : 0;
								result = result % 100;
								v1 = ((result/10)<<4) | (result % 10);
								PutMemB(ES, di,v1);
								if (v1)
								{
									m_ZeroVal = 1;
								}
								si++;
								di++;
							}
						}
						break;
					case 0x22:
						{
							int count = (m_regs.b[CL]+1)/2;
							UINT16 di = m_regs.w[IY];
							UINT16 si = m_regs.w[IX];
							if (m_seg_prefix)
							{
								logerror("%s: %06x: Warning: seg_prefix defined for sub4s\n", tag(), pc());
							}
							m_ZeroVal = m_CarryVal = 0;
							for (int i=0; i<count; i++)
							{
								int result;
								CLK(19);
								tmp = GetMemB(ES, di);
								tmp2 = GetMemB(DS, si);
								int v1 = (tmp>>4)*10 + (tmp&0xf);
								int v2 = (tmp2>>4)*10 + (tmp2&0xf);
								if (v1 < (v2+m_CarryVal))
								{
									v1+=100;
									result = v1-(v2+m_CarryVal);
									m_CarryVal = 1;
								}
								else
								{
									result = v1-(v2+m_CarryVal);
									m_CarryVal = 0;
								}
								v1 = ((result/10)<<4) | (result % 10);
								PutMemB(ES, di,v1);
								if (v1)
								{
									m_ZeroVal = 1;
								}
								si++;
								di++;
							}
						}
						break;
					case 0x26:
						{
							int count = (m_regs.b[CL]+1)/2;
							UINT16 di = m_regs.w[IY];
							UINT16 si = m_regs.w[IX];
							if (m_seg_prefix)
							{
								logerror("%s: %06x: Warning: seg_prefix defined for cmp4s\n", tag(), pc());
							}
							m_ZeroVal = m_CarryVal = 0;
							for (int i=0; i<count; i++)
							{
								int result;
								CLK(19);
								tmp = GetMemB(ES, di);
								tmp2 = GetMemB(DS, si);
								int v1 = (tmp>>4)*10 + (tmp&0xf);
								int v2 = (tmp2>>4)*10 + (tmp2&0xf);
								if (v1 < (v2+m_CarryVal))
								{
									v1+=100;
									result = v1-(v2+m_CarryVal);
									m_CarryVal = 1;
								}
								else
								{
									result = v1-(v2+m_CarryVal);
									m_CarryVal = 0;
								}
								v1 = ((result/10)<<4) | (result % 10);
								if (v1)
								{
									m_ZeroVal = 1;
								}
								si++;
								di++;
							}
						}
						break;
					case 0x28:
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp <<= 4;
						tmp |= m_regs.b[AL] & 0xf;
						m_regs.b[AL] = (m_regs.b[AL] & 0xf0) | ((tmp>>8)&0xf);
						tmp &= 0xff;
						PutbackRMByte(tmp);
						CLKM(9,15);
						break;
					case 0x2a:
						m_modrm = fetch();
						tmp = GetRMByte();
						tmp2 = (m_regs.b[AL] & 0xf)<<4;
						m_regs.b[AL] = (m_regs.b[AL] & 0xf0) | (tmp&0xf);
						tmp = tmp2 | (tmp>>4);
						PutbackRMByte(tmp);
						CLKM(13,19);
						break;
					case 0x31:
						m_modrm = fetch(); m_modrm = 0; logerror("%s: %06x: Unimplemented bitfield INS\n", tag(), pc()); break;
					case 0x33:
						m_modrm = fetch(); m_modrm = 0; logerror("%s: %06x: Unimplemented bitfield EXT\n", tag(), pc()); break;
					case 0x92:  /* V25/35 FINT */
						CLK(2);
						break;
					case 0xe0:
						m_modrm = fetch();
						m_modrm = 0;
						logerror("%s: %06x: V33 unimplemented BRKXA (break to expansion address)\n", tag(), pc());
						break;
					case 0xf0:
						m_modrm = fetch();
						m_modrm = 0;
						logerror("%s: %06x: V33 unimplemented RETXA (return from expansion address)\n", tag(), pc());
						break;
					case 0xff:
						m_modrm = fetch();
						m_modrm = 0;
						logerror("%s: %06x: unimplemented BRKEM (break to 8080 emulation mode)\n", tag(), pc());
						break;
					default:
						logerror("%s: %06x: Unknown V20 instruction\n", tag(), pc());
						break;
					}
				}
				break;


			case 0x10: // i_adc_br8
				DEF_br8();
				m_src += CF ? 1 : 0;
				ADDB();
				PutbackRMByte(m_dst);
				CLKM(1,3);
				break;

			case 0x11: // i_adc_wr16
				DEF_wr16();
				m_src += CF ? 1 : 0;
				ADDW();
				PutbackRMWord(m_dst);
				CLKM(1,3);
				break;

			case 0x12: // i_adc_r8b
				DEF_r8b();
				m_src += CF ? 1 : 0;
				ADDB();
				RegByte(m_dst);
				CLKM(1,2);
				break;

			case 0x13: // i_adc_r16w
				DEF_r16w();
				m_src += CF ? 1 : 0;
				ADDW();
				RegWord(m_dst);
				CLKM(1,2);
				break;

			case 0x14: // i_adc_ald8
				DEF_ald8();
				m_src += CF ? 1 : 0;
				ADDB();
				m_regs.b[AL] = m_dst;
				CLK(1);
				break;

			case 0x15: // i_adc_axd16
				DEF_axd16();
				m_src += CF ? 1 : 0;
				ADDW();
				m_regs.w[AW] = m_dst;
				CLK(1);
				break;

			case 0x16: // i_push_ss
				PUSH(m_sregs[SS]);
				CLK(2);
				break;

			case 0x17: // i_pop_ss
				m_sregs[SS] = POP();
				CLK(3);
				m_no_interrupt = 1;
				break;


			case 0x18: // i_sbb_br8
				DEF_br8();
				m_src += CF ? 1 : 0;
				SUBB();
				PutbackRMByte(m_dst);
				CLKM(1,3);
				break;

			case 0x19: // i_sbb_wr16
				DEF_wr16();
				m_src += CF ? 1 : 0;
				SUBW();
				PutbackRMWord(m_dst);
				CLKM(1,3);
				break;

			case 0x1a: // i_sbb_r8b
				DEF_r8b();
				m_src += CF ? 1 : 0;
				SUBB();
				RegByte(m_dst);
				CLKM(1,2);
				break;

			case 0x1b: // i_sbb_r16w
				DEF_r16w();
				m_src += CF ? 1 : 0;
				SUBW();
				RegWord(m_dst);
				CLKM(1,2);
				break;

			case 0x1c: // i_sbb_ald8
				DEF_ald8();
				m_src += CF ? 1 : 0;
				SUBB();
				m_regs.b[AL] = m_dst;
				CLK(1);
				break;

			case 0x1d: // i_sbb_axd16
				DEF_axd16();
				m_src += CF ? 1 : 0;
				SUBW();
				m_regs.w[AW] = m_dst;
				CLK(1);
				break;

			case 0x1e: // i_push_ds
				PUSH(m_sregs[DS]);
				CLK(2);
				break;

			case 0x1f: // i_pop_ds
				m_sregs[DS] = POP();
				CLK(3);
				break;


			case 0x20: // i_and_br8
				DEF_br8();
				ANDB();
				PutbackRMByte(m_dst);
				CLKM(1,3);
				break;

			case 0x21: // i_and_wr16
				DEF_wr16();
				ANDW();
				PutbackRMWord(m_dst);
				CLKM(1,3);
				break;

			case 0x22: // i_and_r8b
				DEF_r8b();
				ANDB();
				RegByte(m_dst);
				CLKM(1,2);
				break;

			case 0x23: // i_and_r16w
				DEF_r16w();
				ANDW();
				RegWord(m_dst);
				CLKM(1,2);
				break;

			case 0x24: // i_and_ald8
				DEF_ald8();
				ANDB();
				m_regs.b[AL] = m_dst;
				CLK(1);
				break;

			case 0x25: // i_and_axd16
				DEF_axd16();
				ANDW();
				m_regs.w[AW] = m_dst;
				CLK(1);
				break;

			case 0x26: // i_es
				m_seg_prefix_next = true;
				m_prefix_base = m_sregs[ES]<<4;
				CLK(1);
				break;

			case 0x27: // i_daa
				ADJ4(6,0x60);
				CLK(10);
				break;


			case 0x28: // i_sub_br8
				DEF_br8();
				SUBB();
				PutbackRMByte(m_dst);
				CLKM(1,3);
				break;

			case 0x29: // i_sub_wr16
				DEF_wr16();
				SUBW();
				PutbackRMWord(m_dst);
				CLKM(1,3);
				break;

			case 0x2a: // i_sub_r8b
				DEF_r8b();
				SUBB();
				RegByte(m_dst);
				CLKM(1,2);
				break;

			case 0x2b: // i_sub_r16w
				DEF_r16w();
				SUBW();
				RegWord(m_dst);
				CLKM(1,2);
				break;

			case 0x2c: // i_sub_ald8
				DEF_ald8();
				SUBB();
				m_regs.b[AL] = m_dst;
				CLK(1);
				break;

			case 0x2d: // i_sub_axd16
				DEF_axd16();
				SUBW();
				m_regs.w[AW] = m_dst;
				CLK(1);
				break;

			case 0x2e: // i_cs
				m_seg_prefix_next = true;
				m_prefix_base = m_sregs[CS]<<4;
				CLK(1);
				break;

			case 0x2f: // i_das
				ADJ4(-6,-0x60);
				CLK(10);
				break;


			case 0x30: // i_xor_br8
				DEF_br8();
				XORB();
				PutbackRMByte(m_dst);
				CLKM(1,3);
				break;

			case 0x31: // i_xor_wr16
				DEF_wr16();
				XORW();
				PutbackRMWord(m_dst);
				CLKM(1,3);
				break;

			case 0x32: // i_xor_r8b
				DEF_r8b();
				XORB();
				RegByte(m_dst);
				CLKM(1,2);
				break;

			case 0x33: // i_xor_r16w
				DEF_r16w();
				XORW();
				RegWord(m_dst);
				CLKM(1,2);
				break;

			case 0x34: // i_xor_ald8
				DEF_ald8();
				XORB();
				m_regs.b[AL] = m_dst;
				CLK(1);
				break;

			case 0x35: // i_xor_axd16
				DEF_axd16();
				XORW();
				m_regs.w[AW] = m_dst;
				CLK(1);
				break;

			case 0x36: // i_ss
				m_seg_prefix_next = true;
				m_prefix_base = m_sregs[SS]<<4;
				CLK(1);
				break;

			case 0x37: // i_aaa
				ADJB(6, (m_regs.b[AL] > 0xf9) ? 2 : 1);
				CLK(9);
				break;


			case 0x38: // i_cmp_br8
				DEF_br8();
				SUBB();
				CLKM(1,2);
				break;

			case 0x39: // i_cmp_wr16
				DEF_wr16();
				SUBW();
				CLKM(1,2);
				break;

			case 0x3a: // i_cmp_r8b
				DEF_r8b();
				SUBB();
				CLKM(1,2);
				break;

			case 0x3b: // i_cmp_r16w
				DEF_r16w();
				SUBW();
				CLKM(1,2);
				break;

			case 0x3c: // i_cmp_ald8
				DEF_ald8();
				SUBB();
				CLK(1);
				break;

			case 0x3d: // i_cmp_axd16
				DEF_axd16();
				SUBW();
				CLK(1);
				break;

			case 0x3e: // i_ds
				m_seg_prefix_next = true;
				m_prefix_base = m_sregs[DS]<<4;
				CLK(1);
				break;

			case 0x3f: // i_aas
				ADJB(-6, (m_regs.b[AL] < 6) ? -2 : -1);
				CLK(9);
				break;


			case 0x40: // i_inc_ax
				IncWordReg(AW);
				CLK(1);
				break;

			case 0x41: // i_inc_cx
				IncWordReg(CW);
				CLK(1);
				break;

			case 0x42: // i_inc_dx
				IncWordReg(DW);
				CLK(1);
				break;

			case 0x43: // i_inc_bx
				IncWordReg(BW);
				CLK(1);
				break;

			case 0x44: // i_inc_sp
				IncWordReg(SP);
				CLK(1);
				break;

			case 0x45: // i_inc_bp
				IncWordReg(BP);
				CLK(1);
				break;

			case 0x46: // i_inc_si
				IncWordReg(IX);
				CLK(1);
				break;

			case 0x47: // i_inc_di
				IncWordReg(IY);
				CLK(1);
				break;


			case 0x48: // i_dec_ax
				DecWordReg(AW);
				CLK(1);
				break;

			case 0x49: // i_dec_cx
				DecWordReg(CW);
				CLK(1);
				break;

			case 0x4a: // i_dec_dx
				DecWordReg(DW);
				CLK(1);
				break;

			case 0x4b: // i_dec_bx
				DecWordReg(BW);
				CLK(1);
				break;

			case 0x4c: // i_dec_sp
				DecWordReg(SP);
				CLK(1);
				break;

			case 0x4d: // i_dec_bp
				DecWordReg(BP);
				CLK(1);
				break;

			case 0x4e: // i_dec_si
				DecWordReg(IX);
				CLK(1);
				break;

			case 0x4f: // i_dec_di
				DecWordReg(IY);
				CLK(1);
				break;


			case 0x50: // i_push_ax
				PUSH(m_regs.w[AW]);
				CLK(1);
				break;

			case 0x51: // i_push_cx
				PUSH(m_regs.w[CW]);
				CLK(1);
				break;

			case 0x52: // i_push_dx
				PUSH(m_regs.w[DW]);
				CLK(1);
				break;

			case 0x53: // i_push_bx
				PUSH(m_regs.w[BW]);
				CLK(1);
				break;

			case 0x54: // i_push_sp
				PUSH(m_regs.w[SP]);
				CLK(1);
				break;

			case 0x55: // i_push_bp
				PUSH(m_regs.w[BP]);
				CLK(1);
				break;

			case 0x56: // i_push_si
				PUSH(m_regs.w[IX]);
				CLK(1);
				break;

			case 0x57: // i_push_di
				PUSH(m_regs.w[IY]);
				CLK(1);
				break;


			case 0x58: // i_pop_ax
				m_regs.w[AW] = POP();
				CLK(1);
				break;

			case 0x59: // i_pop_cx
				m_regs.w[CW] = POP();
				CLK(1);
				break;

			case 0x5a: // i_pop_dx
				m_regs.w[DW] = POP();
				CLK(1);
				break;

			case 0x5b: // i_pop_bx
				m_regs.w[BW] = POP();
				CLK(1);
				break;

			case 0x5c: // i_pop_sp
				m_regs.w[SP] = POP();
				CLK(1);
				break;

			case 0x5d: // i_pop_bp
				m_regs.w[BP] = POP();
				CLK(1);
				break;

			case 0x5e: // i_pop_si
				m_regs.w[IX] = POP();
				CLK(1);
				break;

			case 0x5f: // i_pop_di
				m_regs.w[IY] = POP();
				CLK(1);
				break;


			case 0x60: // i_pusha
				{
					UINT32 tmp = m_regs.w[SP];

					PUSH(m_regs.w[AW]);
					PUSH(m_regs.w[CW]);
					PUSH(m_regs.w[DW]);
					PUSH(m_regs.w[BW]);
					PUSH(tmp);
					PUSH(m_regs.w[BP]);
					PUSH(m_regs.w[IX]);
					PUSH(m_regs.w[IY]);
					CLK(9);
				}
				break;

			case 0x61: // i_popa
				m_regs.w[IY] = POP();
				m_regs.w[IX] = POP();
				m_regs.w[BP] = POP();
								POP();
				m_regs.w[BW] = POP();
				m_regs.w[DW] = POP();
				m_regs.w[CW] = POP();
				m_regs.w[AW] = POP();
				CLK(8);
				break;

			case 0x62: // i_chkind
				{
					UINT32 low,high,tmp;
					m_modrm = fetch();
					low = GetRMWord();
					high = GetnextRMWord();
					tmp = RegWord();
					if (tmp<low || tmp>high)
					{
						interrupt(5);
						CLK(20);
					}
					else
					{
						CLK(13);
					}
					logerror("%s: %06x: bound %04x high %04x low %04x tmp\n", tag(), pc(), high, low, tmp);
				}
				break;

			case 0x64: // i_repnc
				{
					UINT8 next = repx_op();
					UINT16 c = m_regs.w[CW];

					switch (next)
					{
					case 0x6c:  CLK(2); if (c) do { i_insb();  c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6d:  CLK(2); if (c) do { i_insw();  c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6e:  CLK(2); if (c) do { i_outsb(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6f:  CLK(2); if (c) do { i_outsw(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa4:  CLK(2); if (c) do { i_movsb(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa5:  CLK(2); if (c) do { i_movsw(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa6:  CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa7:  CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaa:  CLK(2); if (c) do { i_stosb(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xab:  CLK(2); if (c) do { i_stosw(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xac:  CLK(2); if (c) do { i_lodsb(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xad:  CLK(2); if (c) do { i_lodsw(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xae:  CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaf:  CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && !CF); m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					default:
						logerror("%s: %06x: REPNC invalid\n", tag(), pc() );
						// Decrement IP so the normal instruction will be executed next
						m_ip--;
						break;
					}
				}
				break;


			case 0x65: // i_repc
				{
					UINT8 next = repx_op();
					UINT16 c = m_regs.w[CW];

					switch (next)
					{
					case 0x6c:  CLK(2); if (c) do { i_insb();  c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6d:  CLK(2); if (c) do { i_insw();  c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6e:  CLK(2); if (c) do { i_outsb(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6f:  CLK(2); if (c) do { i_outsw(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa4:  CLK(2); if (c) do { i_movsb(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa5:  CLK(2); if (c) do { i_movsw(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa6:  CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa7:  CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaa:  CLK(2); if (c) do { i_stosb(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xab:  CLK(2); if (c) do { i_stosw(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xac:  CLK(2); if (c) do { i_lodsb(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xad:  CLK(2); if (c) do { i_lodsw(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xae:  CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaf:  CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && CF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					default:
						logerror("%s: %06x: REPC invalid\n", tag(), pc());
						// Decrement IP so the normal instruction will be executed next
						m_ip--;
						break;
					}
				}
				break;


			case 0x68: // i_push_d16
				PUSH( fetch_word() );
				CLK(1);
				break;

			case 0x69: // i_imul_d16
				{
					UINT32 tmp;
					DEF_r16w();
					tmp = fetch_word();
					m_dst = (INT32)((INT16)m_src)*(INT32)((INT16)tmp);
					m_CarryVal = m_OverVal = (((INT32)m_dst) >> 15 != 0) && (((INT32)m_dst) >> 15 != -1);
					RegWord(m_dst);
					CLKM(3,4);
				}
				break;

			case 0x6a: // i_push_d8
				PUSH( (UINT16)((INT16)((INT8)fetch())) );
				CLK(1);
				break;

			case 0x6b: // i_imul_d8
				{
					UINT32 src2;
					DEF_r16w();
					src2= (UINT16)((INT16)((INT8)fetch()));
					m_dst = (INT32)((INT16)m_src)*(INT32)((INT16)src2);
					m_CarryVal = m_OverVal = (((INT32)m_dst) >> 15 != 0) && (((INT32)m_dst) >> 15 != -1);
					RegWord(m_dst);
					CLKM(3,4);
				}
				break;

			case 0x6c: // i_insb
				i_insb();
				break;

			case 0x6d: // i_insw
				i_insw();
				break;

			case 0x6e: // i_outsb
				i_outsb();
				break;

			case 0x6f: // i_outsw
				i_outsw();
				break;


			case 0x70: // i_jo
				JMP( OF);
				break;

			case 0x71: // i_jno
				JMP(!OF);
				break;

			case 0x72: // i_jc
				JMP( CF);
				break;

			case 0x73: // i_jnc
				JMP(!CF);
				break;

			case 0x74: // i_jz
				JMP( ZF);
				break;

			case 0x75: // i_jnz
				JMP(!ZF);
				break;

			case 0x76: // i_jce
				JMP(CF || ZF);
				break;

			case 0x77: // i_jnce
				JMP(!(CF || ZF));
				break;

			case 0x78: // i_js
				JMP( SF);
				break;

			case 0x79: // i_jns
				JMP(!SF);
				break;

			case 0x7a: // i_jp
				JMP( PF);
				break;

			case 0x7b: // i_jnp
				JMP(!PF);
				break;

			case 0x7c: // i_jl
				JMP((SF!=OF)&&(!ZF));
				break;

			case 0x7d: // i_jnl
				JMP((ZF)||(SF==OF));
				break;

			case 0x7e: // i_jle
				JMP((ZF)||(SF!=OF));
				break;

			case 0x7f: // i_jnle
				JMP((SF==OF)&&(!ZF));
				break;


			case 0x80: // i_80pre
				m_modrm = fetch();
				m_dst = GetRMByte();
				m_src = fetch();
				if (m_modrm >=0xc0 )             { CLK(1); }
				else if ((m_modrm & 0x38)==0x38) { CLK(2); }
				else                             { CLK(3); }
				switch (m_modrm & 0x38)
				{
				case 0x00:                      ADDB(); PutbackRMByte(m_dst);   break;
				case 0x08:                      ORB();  PutbackRMByte(m_dst);   break;
				case 0x10: m_src += CF ? 1 : 0; ADDB(); PutbackRMByte(m_dst);   break;
				case 0x18: m_src += CF ? 1 : 0; SUBB(); PutbackRMByte(m_dst);   break;
				case 0x20:                      ANDB(); PutbackRMByte(m_dst);   break;
				case 0x28:                      SUBB(); PutbackRMByte(m_dst);   break;
				case 0x30:                      XORB(); PutbackRMByte(m_dst);   break;
				case 0x38:                      SUBB();                         break;  /* CMP */
				}
				break;


			case 0x81: // i_81pre
				m_modrm = fetch();
				m_dst = GetRMWord();
				m_src = fetch_word();
				if (m_modrm >=0xc0 )             { CLK(1); }
				else if ((m_modrm & 0x38)==0x38) { CLK(2); }
				else                             { CLK(3); }
				switch (m_modrm & 0x38)
				{
				case 0x00:                      ADDW(); PutbackRMWord(m_dst);   break;
				case 0x08:                      ORW();  PutbackRMWord(m_dst);   break;
				case 0x10: m_src += CF ? 1 : 0; ADDW(); PutbackRMWord(m_dst);   break;
				case 0x18: m_src += CF ? 1 : 0; SUBW(); PutbackRMWord(m_dst);   break;
				case 0x20:                      ANDW(); PutbackRMWord(m_dst);   break;
				case 0x28:                      SUBW(); PutbackRMWord(m_dst);   break;
				case 0x30:                      XORW(); PutbackRMWord(m_dst);   break;
				case 0x38:                      SUBW();                         break;  /* CMP */
				}
				break;


			case 0x82: // i_82pre
				m_modrm = fetch();
				m_dst = GetRMByte();
				m_src = (INT8)fetch();
				if (m_modrm >=0xc0 )             { CLK(1); }
				else if ((m_modrm & 0x38)==0x38) { CLK(2); }
				else                             { CLK(3); }
				switch (m_modrm & 0x38)
				{
				case 0x00:                      ADDB(); PutbackRMByte(m_dst);   break;
				case 0x08:                      ORB();  PutbackRMByte(m_dst);   break;
				case 0x10: m_src += CF ? 1 : 0; ADDB(); PutbackRMByte(m_dst);   break;
				case 0x18: m_src += CF ? 1 : 0; SUBB(); PutbackRMByte(m_dst);   break;
				case 0x20:                      ANDB(); PutbackRMByte(m_dst);   break;
				case 0x28:                      SUBB(); PutbackRMByte(m_dst);   break;
				case 0x30:                      XORB(); PutbackRMByte(m_dst);   break;
				case 0x38:                      SUBB();                         break; /* CMP */
				}
				break;


			case 0x83: // i_83pre
				m_modrm = fetch();
				m_dst = GetRMWord();
				m_src = ((INT16)((INT8)fetch()));
				if ( m_modrm >= 0xc0 )               { CLK(1); }
				else if (( m_modrm & 0x38 ) == 0x38) { CLK(2); }
				else                                 { CLK(3); }
				switch (m_modrm & 0x38)
				{
				case 0x00:                      ADDW(); PutbackRMWord(m_dst); break;
				case 0x08:                      ORW();  PutbackRMWord(m_dst); break;
				case 0x10: m_src += CF ? 1 : 0; ADDW(); PutbackRMWord(m_dst); break;
				case 0x18: m_src += CF ? 1 : 0; SUBW(); PutbackRMWord(m_dst); break;
				case 0x20:                      ANDW(); PutbackRMWord(m_dst); break;
				case 0x28:                      SUBW(); PutbackRMWord(m_dst); break;
				case 0x30:                      XORW(); PutbackRMWord(m_dst); break;
				case 0x38:                      SUBW();                       break; /* CMP */
				}
				break;


			case 0x84: // i_test_br8
				DEF_br8();
				ANDB();
				CLKM(1,2);
				break;

			case 0x85: // i_test_wr16
				DEF_wr16();
				ANDW();
				CLKM(1,2);
				break;

			case 0x86: // i_xchg_br8
				DEF_br8();
				RegByte(m_dst);
				PutbackRMByte(m_src);
				CLKM(3,5);
				break;

			case 0x87: // i_xchg_wr16
				DEF_wr16();
				RegWord(m_dst);
				PutbackRMWord(m_src);
				CLKM(3,5);
				break;


			case 0x88: // i_mov_br8
				m_modrm = fetch();
				m_src = RegByte();
				PutRMByte(m_src);
				CLK(1);
				break;

			case 0x89: // i_mov_wr16
				m_modrm = fetch();
				m_src = RegWord();
				PutRMWord(m_src);
				CLK(1);
				break;

			case 0x8a: // i_mov_r8b
				m_modrm = fetch();
				m_src = GetRMByte();
				RegByte(m_src);
				CLK(1);
				break;

			case 0x8b: // i_mov_r16w
				m_modrm = fetch();
				m_src = GetRMWord();
				RegWord(m_src);
				CLK(1);
				break;

			case 0x8c: // i_mov_wsreg
				m_modrm = fetch();
				PutRMWord(m_sregs[(m_modrm & 0x38) >> 3]);
				CLKM(1,3);
				break;

			case 0x8d: // i_lea
				m_modrm = fetch();
				get_ea();
				RegWord(m_eo);
				CLK(1);
				break;

			case 0x8e: // i_mov_sregw
				m_modrm = fetch();
				m_src = GetRMWord();
				CLKM(2,3);
				switch (m_modrm & 0x38)
				{
				case 0x00:  /* mov es,ew */
					m_sregs[ES] = m_src;
					break;
				case 0x08:  /* mov cs,ew */
					m_sregs[CS] = m_src;
					break;
				case 0x10:  /* mov ss,ew */
					m_sregs[SS] = m_src;
					break;
				case 0x18:  /* mov ds,ew */
					m_sregs[DS] = m_src;
					break;
				default:
					logerror("%s: %06x: Mov Sreg - Invalid register\n", tag(), pc());
				}
				m_no_interrupt = 1;
				break;

			case 0x8f: // i_popw
				m_modrm = fetch();
				PutRMWord( POP() );
				CLKM(1,3);
				break;

			case 0x90: // i_nop
				CLK(1);
				break;

			case 0x91: // i_xchg_axcx
				XchgAWReg(CW);
				CLK(3);
				break;

			case 0x92: // i_xchg_axdx
				XchgAWReg(DW);
				CLK(3);
				break;

			case 0x93: // i_xchg_axbx
				XchgAWReg(BW);
				CLK(3);
				break;

			case 0x94: // i_xchg_axsp
				XchgAWReg(SP);
				CLK(3);
				break;

			case 0x95: // i_xchg_axbp
				XchgAWReg(BP);
				CLK(3);
				break;

			case 0x96: // i_xchg_axsi
				XchgAWReg(IX);
				CLK(3);
				break;

			case 0x97: // i_xchg_axdi
				XchgAWReg(IY);
				CLK(3);
				break;


			case 0x98: // i_cbw
				m_regs.b[AH] = (m_regs.b[AL] & 0x80) ? 0xff : 0;
				CLK(1);
				break;

			case 0x99: // i_cwd
				m_regs.w[DW] = (m_regs.b[AH] & 0x80) ? 0xffff : 0;
				CLK(1);
				break;

			case 0x9a: // i_call_far
				{
					UINT16 tmp = fetch_word();
					UINT16 tmp2 = fetch_word();
					PUSH(m_sregs[CS]);
					PUSH(m_ip);
					m_ip = tmp;
					m_sregs[CS] = tmp2;
					CLK(10);
				}
				break;

			case 0x9b: // i_wait
				logerror("%s: %06x: Hardware POLL\n", tag(), pc());
				break;

			case 0x9c: // i_pushf
				PUSH( CompressFlags() );
				CLK(2);
				break;

			case 0x9d: // i_popf
				i_popf();
				break;

			case 0x9e: // i_sahf
				{
					UINT32 tmp = (CompressFlags() & 0xff00) | (m_regs.b[AH] & 0xd5);
					ExpandFlags(tmp);
					CLK(4);
				}
				break;

			case 0x9f: // i_lahf
				m_regs.b[AH] = CompressFlags();
				CLK(2);
				break;


			case 0xa0: // i_mov_aldisp
				{
					UINT32 addr = fetch_word();
					m_regs.b[AL] = GetMemB(DS, addr);
					CLK(1);
				}
				break;

			case 0xa1: // i_mov_axdisp
				{
					UINT32 addr = fetch_word();
					m_regs.b[AL] = GetMemB(DS, addr);
					m_regs.b[AH] = GetMemB(DS, addr+1);
					CLK(1);
				}
				break;

			case 0xa2: // i_mov_dispal
				{
					UINT32 addr = fetch_word();
					PutMemB(DS, addr, m_regs.b[AL]);
					CLK(1);
				}
				break;

			case 0xa3: // i_mov_dispax
				{
					UINT32 addr = fetch_word();
					PutMemB(DS, addr, m_regs.b[AL]);
					PutMemB(DS, addr+1, m_regs.b[AH]);
					CLK(1);
				}
				break;

			case 0xa4: // i_movsb
				i_movsb();
				break;

			case 0xa5: // i_movsw
				i_movsw();
				break;

			case 0xa6: // i_cmpsb
				i_cmpsb();
				break;

			case 0xa7: // i_cmpsw
				i_cmpsw();
				break;


			case 0xa8: // i_test_ald8
				DEF_ald8();
				ANDB();
				CLK(1);
				break;

			case 0xa9: // i_test_axd16
				DEF_axd16();
				ANDW();
				CLK(1);
				break;

			case 0xaa: // i_stosb
				i_stosb();
				break;

			case 0xab: // i_stosw
				i_stosw();
				break;

			case 0xac: // i_lodsb
				i_lodsb();
				break;

			case 0xad: // i_lodsw
				i_lodsw();
				break;

			case 0xae: // i_scasb
				i_scasb();
				break;

			case 0xaf: // i_scasw
				i_scasw();
				break;


			case 0xb0: // i_mov_ald8
				m_regs.b[AL] = fetch();
				CLK(1);
				break;

			case 0xb1: // i_mov_cld8
				m_regs.b[CL] = fetch();
				CLK(1);
				break;

			case 0xb2: // i_mov_dld8
				m_regs.b[DL] = fetch();
				CLK(1);
				break;

			case 0xb3: // i_mov_bld8
				m_regs.b[BL] = fetch();
				CLK(1);
				break;

			case 0xb4: // i_mov_ahd8
				m_regs.b[AH] = fetch();
				CLK(1);
				break;

			case 0xb5: // i_mov_chd8
				m_regs.b[CH] = fetch();
				CLK(1);
				break;

			case 0xb6: // i_mov_dhd8
				m_regs.b[DH] = fetch();
				CLK(1);
				break;

			case 0xb7: // i_mov_bhd8
				m_regs.b[BH] = fetch();
				CLK(1);
				break;


			case 0xb8: // i_mov_axd16
				m_regs.b[AL] = fetch();
				m_regs.b[AH] = fetch();
				CLK(1);
				break;

			case 0xb9: // i_mov_cxd16
				m_regs.b[CL] = fetch();
				m_regs.b[CH] = fetch();
				CLK(1);
				break;

			case 0xba: // i_mov_dxd16
				m_regs.b[DL] = fetch();
				m_regs.b[DH] = fetch();
				CLK(1);
				break;

			case 0xbb: // i_mov_bxd16
				m_regs.b[BL] = fetch();
				m_regs.b[BH] = fetch();
				CLK(1);
				break;

			case 0xbc: // i_mov_spd16
				m_regs.b[SPL] = fetch();
				m_regs.b[SPH] = fetch();
				CLK(1);
				break;

			case 0xbd: // i_mov_bpd16
				m_regs.b[BPL] = fetch();
				m_regs.b[BPH] = fetch();
				CLK(1);
				break;

			case 0xbe: // i_mov_sid16
				m_regs.b[IXL] = fetch();
				m_regs.b[IXH] = fetch();
				CLK(1);
				break;

			case 0xbf: // i_mov_did16
				m_regs.b[IYL] = fetch();
				m_regs.b[IYH] = fetch();
				CLK(1);
				break;


			case 0xc0: // i_rotshft_bd8
				{
					UINT8 c;
					m_modrm = fetch();
					m_src = GetRMByte();
					m_dst = m_src;
					c = fetch();
					CLKM(3,5);
					if (c)
					{
						switch ( m_modrm & 0x38 )
						{
						case 0x00: do { ROL_BYTE();  c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x08: do { ROR_BYTE();  c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x20: SHL_BYTE(c); break;
						case 0x28: SHR_BYTE(c); break;
						case 0x30: logerror("%s: %06x: Undefined opcode 0xc0 0x30 (SHLA)\n", tag(), pc()); break;
						case 0x38: SHRA_BYTE(c); break;
						}
					}
				}
				break;

			case 0xc1: // i_rotshft_wd8
				{
					UINT8 c;
					m_modrm = fetch();
					m_src = GetRMWord();
					m_dst = m_src;
					c = fetch();
					CLKM(3,5);
					if (c)
					{
						switch ( m_modrm & 0x38 )
						{
						case 0x00: do { ROL_WORD();  c--; } while (c>0); PutbackRMWord(m_dst); break;
						case 0x08: do { ROR_WORD();  c--; } while (c>0); PutbackRMWord(m_dst); break;
						case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
						case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
						case 0x20: SHL_WORD(c); break;
						case 0x28: SHR_WORD(c); break;
						case 0x30: logerror("%s: %06x: Undefined opcode 0xc1 0x30 (SHLA)\n", tag(), pc()); break;
						case 0x38: SHRA_WORD(c); break;
						}
					}
				}
				break;


			case 0xc2: // i_ret_d16
				{
					UINT32 count = fetch_word();
					m_ip = POP();
					m_regs.w[SP] += count;
					CLK(6);
				}
				break;

			case 0xc3: // i_ret
				m_ip = POP();
				CLK(6);
				break;

			case 0xc4: // i_les_dw
				m_modrm = fetch();
				RegWord( GetRMWord() );
				m_sregs[ES] = GetnextRMWord();
				CLK(6);
				break;

			case 0xc5: // i_lds_dw
				m_modrm = fetch();
				RegWord( GetRMWord() );
				m_sregs[DS] = GetnextRMWord();
				CLK(6);
				break;

			case 0xc6: // i_mov_bd8
				m_modrm = fetch();
				PutImmRMByte();
				CLK(1);
				break;

			case 0xc7: // i_mov_wd16
				m_modrm = fetch();
				PutImmRMWord();
				CLK(1);
				break;


			case 0xc8: // i_enter
				{
					UINT16 nb = fetch();
					UINT32 level;

					CLK(8);
					nb |= fetch() << 8;
					level = fetch();
					PUSH(m_regs.w[BP]);
					m_regs.w[BP] = m_regs.w[SP];
					m_regs.w[SP] -= nb;
					for (int i=1; i<level; i++)
					{
						PUSH( GetMemW(SS,m_regs.w[BP] - i*2) );
						CLK(4);
					}
					if (level)
					{
						PUSH(m_regs.w[BP]);
						CLK( ( level == 1 ) ? 2 : 3 );
					}
				}
				break;

			case 0xc9: // i_leave
				m_regs.w[SP] = m_regs.w[BP];
				m_regs.w[BP] = POP();
				CLK(2);
				break;

			case 0xca: // i_retf_d16
				{
					UINT32 count = fetch_word();
					m_ip = POP();
					m_sregs[CS] = POP();
					m_regs.w[SP] += count;
					CLK(9);
				}
				break;

			case 0xcb: // i_retf
				m_ip = POP();
				m_sregs[CS] = POP();
				CLK(8);
				break;

			case 0xcc: // i_int3
				interrupt(3);
				CLK(9);
				break;

			case 0xcd: // i_int
				interrupt(fetch());
				CLK(10);
				break;

			case 0xce: // i_into
				if (OF)
				{
					interrupt(4);
					CLK(7);
				}
				CLK(6);
				break;

			case 0xcf: // i_iret
				m_ip = POP();
				m_sregs[CS] = POP();
				i_popf();
				CLK(10);
				break;


			case 0xd0: // i_rotshft_b
				m_modrm = fetch();
				m_src = GetRMByte();
				m_dst = m_src;
				CLKM(1,3);
				switch ( m_modrm & 0x38 )
				{
				case 0x00: ROL_BYTE();  PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
				case 0x08: ROR_BYTE();  PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
				case 0x10: ROLC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
				case 0x18: RORC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
				case 0x20: SHL_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break;
				case 0x28: SHR_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break;
				case 0x30: logerror("%s: %06x: Undefined opcode 0xd0 0x30 (SHLA)\n", tag(), pc()); break;
				case 0x38: SHRA_BYTE(1); m_OverVal = 0; break;
				}
				break;

			case 0xd1: // i_rotshft_w
				m_modrm = fetch();
				m_src = GetRMWord();
				m_dst = m_src;
				CLKM(1,3);
				switch ( m_modrm & 0x38 )
				{
				case 0x00: ROL_WORD();  PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
				case 0x08: ROR_WORD();  PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
				case 0x10: ROLC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
				case 0x18: RORC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
				case 0x20: SHL_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000;  break;
				case 0x28: SHR_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000;  break;
				case 0x30: logerror("%s: %06x: Undefined opcode 0xd1 0x30 (SHLA)\n", tag(), pc()); break;
				case 0x38: SHRA_WORD(1); m_OverVal = 0; break;
				}
				break;

			case 0xd2: // i_rotshft_bcl
				{
					UINT8 c;

					m_modrm = fetch();
					m_src = GetRMByte();
					m_dst = m_src;
					c = m_regs.b[CL];
					CLKM(3,5);
					if (c)
					{
						switch ( m_modrm & 0x38 )
						{
						case 0x00: do { ROL_BYTE();  c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x08: do { ROR_BYTE();  c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
						case 0x20: SHL_BYTE(c); break;
						case 0x28: SHR_BYTE(c); break;
						case 0x30: logerror("%s: %06x: Undefined opcode 0xd2 0x30 (SHLA)\n", tag(), pc()); break;
						case 0x38: SHRA_BYTE(c); break;
						}
					}
				}
				break;

			case 0xd3: // i_rotshft_wcl
				{
					UINT8 c;

					m_modrm = fetch();
					m_src = GetRMWord();
					m_dst = m_src;
					c = m_regs.b[CL];
					CLKM(3,5);
					if (c)
					{
						switch ( m_modrm & 0x38 )
						{
							case 0x00: do { ROL_WORD();  c--; } while (c>0); PutbackRMWord(m_dst); break;
							case 0x08: do { ROR_WORD();  c--; } while (c>0); PutbackRMWord(m_dst); break;
							case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
							case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
							case 0x20: SHL_WORD(c); break;
							case 0x28: SHR_WORD(c); break;
							case 0x30: logerror("%s: %06x: Undefined opcode 0xd3 0x30 (SHLA)\n", tag(), pc()); break;
							case 0x38: SHRA_WORD(c); break;
						}
					}
				}
				break;

			case 0xd4: // i_aam
				fetch();
				m_regs.b[AH] = m_regs.b[AL] / 10;
				m_regs.b[AL] %= 10;
				set_SZPF_Word(m_regs.w[AW]);
				CLK(17);
				break;

			case 0xd5: // i_aad
				fetch();
				m_regs.b[AL] = m_regs.b[AH] * 10 + m_regs.b[AL];
				m_regs.b[AH] = 0;
				set_SZPF_Byte(m_regs.b[AL]);
				CLK(5);
				break;

			case 0xd6: // i_setalc
				m_regs.b[AL] = (CF) ? 0xff : 0x00;
				CLK(3);
				logerror("%s: %06x: Undefined opcode (SETALC)\n", tag(), pc() );
				break;

			case 0xd7: // i_trans
				m_regs.b[AL] = GetMemB( DS, m_regs.w[BW] + m_regs.b[AL] );
				CLK(5);
				break;

			case 0xd8: // i_fpo
				m_modrm = fetch();
				CLK(1);
				logerror("%s: %06x: Unimplemented floating point control %04x\n", tag(), pc(), m_modrm);
				break;


			case 0xe0: // i_loopne
				{
					INT8 disp = (INT8)fetch();

					m_regs.w[CW]--;
					if (!ZF && m_regs.w[CW])
					{
						m_ip = m_ip + disp;
						CLK(3);
					}
					CLK(3);
				}
				break;

			case 0xe1: // i_loope
				{
					INT8 disp = (INT8)fetch();

					m_regs.w[CW]--;
					if (ZF && m_regs.w[CW])
					{
						m_ip = m_ip + disp;
						CLK(3);
					}
					CLK(3);
				}
				break;

			case 0xe2: // i_loop
				{
					INT8 disp = (INT8)fetch();

					m_regs.w[CW]--;
					if (m_regs.w[CW])
					{
						m_ip = m_ip + disp;
						CLK(3);
					}
					CLK(2);
				}
				break;

			case 0xe3: // i_jcxz
				{
					INT8 disp = (INT8)fetch();

					if (m_regs.w[CW] == 0)
					{
						m_ip = m_ip + disp;
						CLK(3);
					}
					CLK(1);
				}
				break;

			case 0xe4: // i_inal
				m_regs.b[AL] = read_port( fetch() );
				CLK(6);
				break;

			case 0xe5: // i_inax
				{
					UINT8 port = fetch();

					m_regs.b[AL] = read_port(port);
					m_regs.b[AH] = read_port(port+1);
					CLK(6);
				}
				break;

			case 0xe6: // i_outal
				write_port( fetch(), m_regs.b[AL]);
				CLK(6);
				break;

			case 0xe7: // i_outax
				{
					UINT8 port = fetch();

					write_port(port, m_regs.b[AL]);
					write_port(port+1, m_regs.b[AH]);
					CLK(6);
				}
				break;


			case 0xe8: // i_call_d16
				{
					INT16 tmp = (INT16)fetch_word();

					PUSH(m_ip);
					m_ip = m_ip + tmp;
					CLK(5);
				}
				break;

			case 0xe9: // i_jmp_d16
				{
					INT16 offset = (INT16)fetch_word();
					m_ip += offset;
					CLK(4);
				}
				break;

			case 0xea: // i_jmp_far
				{
					UINT16 tmp = fetch_word();
					UINT16 tmp1 = fetch_word();

					m_sregs[CS] = tmp1;
					m_ip = tmp;
					CLK(7);
				}
				break;

			case 0xeb: // i_jmp_d8
				{
					int tmp = (int)((INT8)fetch());

					CLK(4);
					if (tmp==-2 && m_no_interrupt==0 && (m_pending_irq==0) && m_icount>0)
					{
						m_icount%=12; /* cycle skip */
					}
					m_ip = (UINT16)(m_ip+tmp);
				}
				break;

			case 0xec: // i_inaldx
				m_regs.b[AL] = read_port(m_regs.w[DW]);
				CLK(6);
				break;

			case 0xed: // i_inaxdx
				{
					UINT32 port = m_regs.w[DW];

					m_regs.b[AL] = read_port(port);
					m_regs.b[AH] = read_port(port+1);
					CLK(6);
				}
				break;

			case 0xee: // i_outdxal
				write_port(m_regs.w[DW], m_regs.b[AL]);
				CLK(6);
				break;

			case 0xef: // i_outdxax
				{
					UINT32 port = m_regs.w[DW];

					write_port(port, m_regs.b[AL]);
					write_port(port+1, m_regs.b[AH]);
					CLK(6);
				}
				break;


			case 0xf0: // i_lock
				logerror("%s: %06x: Warning - BUSLOCK\n", tag(), pc());
				m_no_interrupt = 1;
				CLK(1);
				break;

			case 0xf2: // i_repne
				{
					UINT8 next = repx_op();
					UINT16 c = m_regs.w[CW];

					switch (next)
					{
					case 0x6c:  CLK(3); if (c) do { i_insb();  c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6d:  CLK(3); if (c) do { i_insw();  c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6e:  CLK(3); if (c) do { i_outsb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6f:  CLK(3); if (c) do { i_outsw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa4:  CLK(3); if (c) do { i_movsb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa5:  CLK(3); if (c) do { i_movsw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa6:  CLK(3); if (c) do { i_cmpsb(); c--; } while (c>0 && !ZF);   m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa7:  CLK(3); if (c) do { i_cmpsw(); c--; } while (c>0 && !ZF);   m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaa:  CLK(3); if (c) do { i_stosb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xab:  CLK(3); if (c) do { i_stosw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xac:  CLK(3); if (c) do { i_lodsb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xad:  CLK(3); if (c) do { i_lodsw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xae:  CLK(3); if (c) do { i_scasb(); c--; } while (c>0 && !ZF);   m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaf:  CLK(3); if (c) do { i_scasw(); c--; } while (c>0 && !ZF);   m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					default:
						logerror("%s: %06x: REPNE invalid\n", tag(), pc());
						// Decrement IP so the normal instruction will be executed next
						m_ip--;
						break;
					}
				}
				break;

			case 0xf3: // i_repe
				{
					UINT8 next = repx_op();
					UINT16 c = m_regs.w[CW];

					switch (next)
					{
					case 0x6c:  CLK(3); if (c) do { i_insb();  c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6d:  CLK(3); if (c) do { i_insw();  c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6e:  CLK(3); if (c) do { i_outsb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0x6f:  CLK(3); if (c) do { i_outsw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa4:  CLK(3); if (c) do { i_movsb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa5:  CLK(3); if (c) do { i_movsw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa6:  CLK(3); if (c) do { i_cmpsb(); c--; } while (c>0 && ZF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xa7:  CLK(3); if (c) do { i_cmpsw(); c--; } while (c>0 && ZF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaa:  CLK(3); if (c) do { i_stosb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xab:  CLK(3); if (c) do { i_stosw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xac:  CLK(3); if (c) do { i_lodsb(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xad:  CLK(3); if (c) do { i_lodsw(); c--; } while (c>0);          m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xae:  CLK(3); if (c) do { i_scasb(); c--; } while (c>0 && ZF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					case 0xaf:  CLK(3); if (c) do { i_scasw(); c--; } while (c>0 && ZF);    m_regs.w[CW]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
					default:
						logerror("%s: %06x: REPE invalid\n", tag(), pc());
						// Decrement IP so the normal instruction will be executed next
						m_ip--;
						break;
					}
				}
				break;

			case 0xf4: // i_hlt
				logerror("%s: %06x: HALT\n", tag(), pc());
				m_icount = 0;
				break;

			case 0xf5: // i_cmc
				m_CarryVal ^= 1;
				CLK(4);
				break;

			case 0xf6: // i_f6pre
				{
					UINT32 tmp;
					UINT32 uresult,uresult2;
					INT32 result,result2;

					m_modrm = fetch();
					tmp = GetRMByte();
					switch ( m_modrm & 0x38 )
					{
					case 0x00:  /* TEST */
						tmp &= fetch();
						m_CarryVal = m_OverVal = 0;
						set_SZPF_Byte(tmp);
						CLKM(1,2);
						break;
					case 0x08:
						logerror("%s: %06x: Undefined opcode 0xf6 0x08\n", tag(), pc());
						break;
					case 0x10:  /* NOT */
						PutbackRMByte(~tmp);
						CLKM(1,3);
						break;
					case 0x18:  /* NEG */
						m_CarryVal = (tmp!=0) ? 1 : 0;
						tmp = (~tmp)+1;
						set_SZPF_Byte(tmp);
						PutbackRMByte(tmp&0xff);
						CLKM(1,3);
						break;
					case 0x20:  /* MULU */
						uresult = m_regs.b[AL] * tmp;
						m_regs.w[AW] = (UINT16)uresult;
						m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0;
						CLKM(3,4);
						break;
					case 0x28:  /* MUL */
						result = (INT16)((INT8)m_regs.b[AL])*(INT16)((INT8)tmp);
						m_regs.w[AW] = (UINT16)result;
						m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0;
						CLKM(3,4);
						break;
					case 0x30:  /* DIVU */
						if (tmp)
						{
							uresult = m_regs.w[AW];
							uresult2 = uresult % tmp;
							if ((uresult /= tmp) > 0xff)
							{
								interrupt(0);
							}
							else
							{
								m_regs.b[AL] = uresult;
								m_regs.b[AH] = uresult2;
							}
						}
						else
						{
							interrupt(0);
						}
						CLKM(15,16);
						break;
					case 0x38:  /* DIV */
						if (tmp)
						{
							result = (INT16)m_regs.w[AW];
							result2 = result % (INT16)((INT8)tmp);
							if ((result /= (INT16)((INT8)tmp)) > 0xff)
							{
								interrupt(0);
							}
							else
							{
								m_regs.b[AL] = result;
								m_regs.b[AH] = result2;
							}
						}
						else
						{
							interrupt(0);
						}
						CLKM(17,18);
						break;
					}
				}
				break;


			case 0xf7: // i_f7pre
				{
					UINT32 tmp,tmp2;
					UINT32 uresult,uresult2;
					INT32 result,result2;

					m_modrm = fetch();
					tmp = GetRMWord();
					switch ( m_modrm & 0x38 )
					{
					case 0x00:  /* TEST */
						tmp2 = fetch_word();
						tmp &= tmp2;
						m_CarryVal = m_OverVal = 0;
						set_SZPF_Word(tmp);
						CLKM(1,2);
						break;
					case 0x08:
						logerror("%s: %06x: Undefined opcode 0xf7 0x08\n", tag(), pc());
						break;
					case 0x10:  /* NOT */
						PutbackRMWord(~tmp);
						CLKM(1,3);
						break;
					case 0x18:  /* NEG */
						m_CarryVal = (tmp!=0) ? 1 : 0;
						tmp = (~tmp) + 1;
						set_SZPF_Word(tmp);
						PutbackRMWord(tmp);
						CLKM(1,3);
						break;
					case 0x20:  /* MULU */
						uresult = m_regs.w[AW]*tmp;
						m_regs.w[AW] = uresult & 0xffff;
						m_regs.w[DW] = ((UINT32)uresult)>>16;
						m_CarryVal = m_OverVal = (m_regs.w[DW] != 0) ? 1 : 0;
						CLKM(3,4);
						break;
					case 0x28:  /* MUL */
						result = (INT32)((INT16)m_regs.w[AW]) * (INT32)((INT16)tmp);
						m_regs.w[AW] = result & 0xffff;
						m_regs.w[DW] = result >> 16;
						m_CarryVal = m_OverVal = (m_regs.w[DW] != 0) ? 1 : 0;
						CLKM(3,4);
						break;
					case 0x30:  /* DIVU */
						if (tmp)
						{
							uresult = (((UINT32)m_regs.w[DW]) << 16) | m_regs.w[AW];
							uresult2 = uresult % tmp;
							if ((uresult /= tmp) > 0xffff)
							{
								interrupt(0);
							}
							else
							{
								m_regs.w[AW] = uresult;
								m_regs.w[DW] = uresult2;
							}
						}
						else
						{
							interrupt(0);
						}
						CLKM(23,24);
						break;
					case 0x38:  /* DIV */
						if (tmp)
						{
							result = ((UINT32)m_regs.w[DW] << 16) + m_regs.w[AW];
							result2 = result % (INT32)((INT16)tmp);
							if ((result /= (INT32)((INT16)tmp)) > 0xffff)
							{
								interrupt(0);
							}
							else
							{
								m_regs.w[AW] = result;
								m_regs.w[DW] = result2;
							}
						}
						else
						{
							interrupt(0);
						}
						CLKM(24,25);
						break;
					}
				}
				break;


			case 0xf8: // i_clc
				m_CarryVal = 0;
				CLK(4);
				break;

			case 0xf9: // i_stc
				m_CarryVal = 1;
				CLK(4);
				break;

			case 0xfa: // i_di
				m_IF = 0;
				CLK(4);
				break;

			case 0xfb: // i_ei
				m_IF = 1;
				CLK(4);
				break;

			case 0xfc: // i_cld
				m_DF = 0;
				CLK(4);
				break;

			case 0xfd: // i_std
				m_DF = 1;
				CLK(4);
				break;

			case 0xfe: // i_fepre
				{
					UINT32 tmp, tmp1;
					m_modrm = fetch();
					tmp = GetRMByte();
					switch ( m_modrm & 0x38 )
					{
					case 0x00:  /* INC */
						tmp1 = tmp+1;
						m_OverVal = (tmp==0x7f);
						set_AF(tmp1,tmp,1);
						set_SZPF_Byte(tmp1);
						PutbackRMByte(tmp1);
						CLKM(1,3);
						break;
					case 0x08:  /* DEC */
						tmp1 = tmp-1;
						m_OverVal = (tmp==0x80);
						set_AF(tmp1,tmp,1);
						set_SZPF_Byte(tmp1);
						PutbackRMByte(tmp1);
						CLKM(1,3);
						break;
					default:
						logerror("%s: %06x: FE Pre with unimplemented mod\n", tag(), pc());
						break;
					}
				}
				break;

			case 0xff: // i_ffpre
				{
					UINT32 tmp, tmp1;
					m_modrm = fetch();
					tmp = GetRMWord();
					switch ( m_modrm & 0x38 )
					{
					case 0x00:  /* INC */
						tmp1 = tmp+1;
						m_OverVal = (tmp==0x7fff);
						set_AF(tmp1,tmp,1);
						set_SZPF_Word(tmp1);
						PutbackRMWord(tmp1);
						CLKM(1,3);
						break;
					case 0x08:  /* DEC */
						tmp1 = tmp-1;
						m_OverVal = (tmp==0x8000);
						set_AF(tmp1,tmp,1);
						set_SZPF_Word(tmp1);
						PutbackRMWord(tmp1);
						CLKM(1,3);
						break;
					case 0x10:  /* CALL */
						PUSH(m_ip);
						m_ip = tmp;
						CLKM(5,6);
						break;
					case 0x18:  /* CALL FAR */
						tmp1 = m_sregs[CS];
						m_sregs[CS] = GetnextRMWord();
						PUSH(tmp1);
						PUSH(m_ip);
						m_ip = tmp;
						CLKM(5,12);
						break;
					case 0x20:  /* JMP */
						m_ip = tmp;
						CLKM(4,5);
						break;
					case 0x28:  /* JMP FAR */
						m_ip = tmp;
						m_sregs[CS] = GetnextRMWord();
						CLK(10);
						break;
					case 0x30:
						PUSH(tmp);
						CLK(1);
						break;
					default:
						logerror("%s: %06x: FF Pre with unimplemented mod\n", tag(), pc());
						break;
					}
				}
				break;

		default:
			m_icount -= 10;
			logerror("%s: %06x: Invalid Opcode %02x\n", tag(), pc(), op);
			break;

		}
	}
}
