diff options
Diffstat (limited to 'src/devices/cpu/v30mz/v30mz.c')
-rw-r--r-- | src/devices/cpu/v30mz/v30mz.c | 3732 |
1 files changed, 3732 insertions, 0 deletions
diff --git a/src/devices/cpu/v30mz/v30mz.c b/src/devices/cpu/v30mz/v30mz.c new file mode 100644 index 00000000000..3bc7c28236a --- /dev/null +++ b/src/devices/cpu/v30mz/v30mz.c @@ -0,0 +1,3732 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol,Bryan McPhail +/**************************************************************************** + + 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]; + } + + memset(&m_regs, 0x00, sizeof(m_regs)); +} + + +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, std::string &str) +{ + switch (entry.index()) + { + case STATE_GENPC: + strprintf(str, "%08X", pc()); + break; + + case STATE_GENFLAGS: + { + UINT16 flags = CompressFlags(); + strprintf(str, "%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_byte( pc() ); + m_ip++; + return data; +} + + +inline UINT8 v30mz_cpu_device::fetch() +{ + UINT8 data = m_direct->read_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; + + } + } +} |