--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Author : Takeda.Toshiya
+ Date : 2012.10.18-
+
+ [ i286 ]
+*/
+
+#include "i286.h"
+#ifdef USE_DEBUGGER
+#include "debugger.h"
+#endif
+
+/* ----------------------------------------------------------------------------
+ MAME i286
+---------------------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning( disable : 4018 )
+#pragma warning( disable : 4146 )
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4996 )
+#endif
+
+#if defined(HAS_I86)
+ #define CPU_MODEL i8086
+#elif defined(HAS_I88)
+ #define CPU_MODEL i8088
+#elif defined(HAS_I186)
+ #define CPU_MODEL i80186
+#elif defined(HAS_V30)
+ #define CPU_MODEL v30
+#elif defined(HAS_I286)
+ #define CPU_MODEL i80286
+#endif
+
+#ifndef __BIG_ENDIAN__
+#define LSB_FIRST
+#endif
+
+#ifndef INLINE
+#define INLINE inline
+#endif
+
+#define logerror(...)
+
+/*****************************************************************************/
+/* src/emu/devcpu.h */
+
+// CPU interface functions
+#define CPU_INIT_NAME(name) cpu_init_##name
+#define CPU_INIT(name) void* CPU_INIT_NAME(name)()
+#define CPU_INIT_CALL(name) CPU_INIT_NAME(name)()
+
+#define CPU_RESET_NAME(name) cpu_reset_##name
+#define CPU_RESET(name) void CPU_RESET_NAME(name)(cpu_state *cpustate)
+#define CPU_RESET_CALL(name) CPU_RESET_NAME(name)(cpustate)
+
+#define CPU_EXECUTE_NAME(name) cpu_execute_##name
+#define CPU_EXECUTE(name) int CPU_EXECUTE_NAME(name)(cpu_state *cpustate, int icount)
+#define CPU_EXECUTE_CALL(name) CPU_EXECUTE_NAME(name)(cpustate, icount)
+
+#define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
+#define CPU_DISASSEMBLE(name) int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t eip, const UINT8 *oprom)
+#define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(buffer, eip, oprom)
+
+/*****************************************************************************/
+/* src/emu/didisasm.h */
+
+// Disassembler constants
+const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
+const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
+const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
+const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
+const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
+const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
+
+/*****************************************************************************/
+/* src/emu/diexec.h */
+
+// I/O line states
+enum line_state
+{
+ CLEAR_LINE = 0, // clear (a fired or held) line
+ ASSERT_LINE, // assert an interrupt immediately
+ HOLD_LINE, // hold interrupt line until acknowledged
+ PULSE_LINE // pulse interrupt line instantaneously (only for NMI, RESET)
+};
+
+enum
+{
+ INPUT_LINE_IRQ = 0,
+ INPUT_LINE_NMI
+};
+
+/*****************************************************************************/
+/* src/emu/emucore.h */
+
+// constants for expression endianness
+enum endianness_t
+{
+ ENDIANNESS_LITTLE,
+ ENDIANNESS_BIG
+};
+
+// declare native endianness to be one or the other
+#ifdef LSB_FIRST
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
+#else
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
+#endif
+// endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
+#define ENDIAN_VALUE_LE_BE(endian,leval,beval) (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
+// endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
+#define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval) ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
+// endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
+#define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
+
+/*****************************************************************************/
+/* src/emu/memory.h */
+
+// offsets and addresses are 32-bit (for now...)
+typedef UINT32 offs_t;
+
+/*****************************************************************************/
+/* src/osd/osdcomm.h */
+
+/* Highly useful macro for compile-time knowledge of an array size */
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
+
+#if defined(HAS_I86) || defined(HAS_I88) || defined(HAS_I186) || defined(HAS_V30)
+#define cpu_state i8086_state
+#include "mame/emu/cpu/i86/i86.c"
+#elif defined(HAS_I286)
+#define cpu_state i80286_state
+#include "mame/emu/cpu/i86/i286.c"
+#endif
+#ifdef USE_DEBUGGER
+#ifdef HAS_V30
+#include "mame/emu/cpu/nec/necdasm.c"
+#else
+#include "mame/emu/cpu/i386/i386dasm.c"
+#endif
+#endif
+
+void I286::initialize()
+{
+ opaque = CPU_INIT_CALL(CPU_MODEL);
+
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->pic = d_pic;
+ cpustate->program = d_mem;
+ cpustate->io = d_io;
+#ifdef I86_PSEUDO_BIOS
+ cpustate->bios = d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpustate->dma = d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ cpustate->emu = emu;
+ cpustate->debugger = d_debugger;
+ cpustate->program_stored = d_mem;
+ cpustate->io_stored = d_io;
+
+ d_debugger->set_context_mem(d_mem);
+ d_debugger->set_context_io(d_io);
+#endif
+}
+
+void I286::release()
+{
+ free(opaque);
+}
+
+void I286::reset()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ int busreq = cpustate->busreq;
+
+ CPU_RESET_CALL(CPU_MODEL);
+
+ cpustate->pic = d_pic;
+ cpustate->program = d_mem;
+ cpustate->io = d_io;
+#ifdef I86_PSEUDO_BIOS
+ cpustate->bios = d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpustate->dma = d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ cpustate->emu = emu;
+ cpustate->debugger = d_debugger;
+ cpustate->program_stored = d_mem;
+ cpustate->io_stored = d_io;
+#endif
+ cpustate->busreq = busreq;
+}
+
+int I286::run(int icount)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return CPU_EXECUTE_CALL(CPU_MODEL);
+}
+
+void I286::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+
+ if(id == SIG_CPU_NMI) {
+ set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
+ } else if(id == SIG_CPU_IRQ) {
+ set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
+ } else if(id == SIG_CPU_BUSREQ) {
+ cpustate->busreq = (data & mask) ? 1 : 0;
+ } else if(id == SIG_I86_TEST) {
+ cpustate->test_state = (data & mask) ? 1 : 0;
+#ifdef HAS_I286
+ } else if(id == SIG_I86_A20) {
+ i80286_set_a20_line(cpustate, data & mask);
+#endif
+ }
+}
+
+void I286::set_intr_line(bool line, bool pending, uint32_t bit)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
+}
+
+void I286::set_extra_clock(int icount)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->extra_cycles += icount;
+}
+
+int I286::get_extra_clock()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->extra_cycles;
+}
+
+uint32_t I286::get_pc()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->prevpc;
+}
+
+uint32_t I286::get_next_pc()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->pc;
+}
+
+#ifdef USE_DEBUGGER
+void I286::write_debug_data8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem->write_data8w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_data8(uint32_t addr)
+{
+ int wait;
+ return d_mem->read_data8w(addr, &wait);
+}
+
+void I286::write_debug_data16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem->write_data16w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_data16(uint32_t addr)
+{
+ int wait;
+ return d_mem->read_data16w(addr, &wait);
+}
+
+void I286::write_debug_io8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io->write_io8w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_io8(uint32_t addr) {
+ int wait;
+ return d_io->read_io8w(addr, &wait);
+}
+
+void I286::write_debug_io16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io->write_io16w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_io16(uint32_t addr) {
+ int wait;
+ return d_io->read_io16w(addr, &wait);
+}
+
+bool I286::write_debug_reg(const _TCHAR *reg, uint32_t data)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ if(_tcsicmp(reg, _T("IP")) == 0) {
+ cpustate->pc = ((data & 0xffff) + cpustate->base[CS]) & AMASK;
+ CHANGE_PC(cpustate->pc);
+ } else if(_tcsicmp(reg, _T("AX")) == 0) {
+ cpustate->regs.w[AX] = data;
+ } else if(_tcsicmp(reg, _T("BX")) == 0) {
+ cpustate->regs.w[BX] = data;
+ } else if(_tcsicmp(reg, _T("CX")) == 0) {
+ cpustate->regs.w[CX] = data;
+ } else if(_tcsicmp(reg, _T("DX")) == 0) {
+ cpustate->regs.w[DX] = data;
+ } else if(_tcsicmp(reg, _T("SP")) == 0) {
+ cpustate->regs.w[SP] = data;
+ } else if(_tcsicmp(reg, _T("BP")) == 0) {
+ cpustate->regs.w[BP] = data;
+ } else if(_tcsicmp(reg, _T("SI")) == 0) {
+ cpustate->regs.w[SI] = data;
+ } else if(_tcsicmp(reg, _T("DI")) == 0) {
+ cpustate->regs.w[DI] = data;
+ } else if(_tcsicmp(reg, _T("AL")) == 0) {
+ cpustate->regs.b[AL] = data;
+ } else if(_tcsicmp(reg, _T("AH")) == 0) {
+ cpustate->regs.b[AH] = data;
+ } else if(_tcsicmp(reg, _T("BL")) == 0) {
+ cpustate->regs.b[BL] = data;
+ } else if(_tcsicmp(reg, _T("BH")) == 0) {
+ cpustate->regs.b[BH] = data;
+ } else if(_tcsicmp(reg, _T("CL")) == 0) {
+ cpustate->regs.b[CL] = data;
+ } else if(_tcsicmp(reg, _T("CH")) == 0) {
+ cpustate->regs.b[CH] = data;
+ } else if(_tcsicmp(reg, _T("DL")) == 0) {
+ cpustate->regs.b[DL] = data;
+ } else if(_tcsicmp(reg, _T("DH")) == 0) {
+ cpustate->regs.b[DH] = data;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void I286::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ my_stprintf_s(buffer, buffer_len,
+ _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]"),
+ cpustate->regs.w[AX], cpustate->regs.w[BX], cpustate->regs.w[CX], cpustate->regs.w[DX], cpustate->regs.w[SP], cpustate->regs.w[BP], cpustate->regs.w[SI], cpustate->regs.w[DI],
+ cpustate->sregs[DS], cpustate->sregs[ES], cpustate->sregs[SS], cpustate->sregs[CS], cpustate->pc - cpustate->base[CS],
+ OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
+ SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'));
+}
+
+int I286::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ UINT64 eip = pc - cpustate->base[CS];
+ UINT8 ops[16];
+ for(int i = 0; i < 16; i++) {
+ int wait;
+ ops[i] = d_mem->read_data8w(pc + i, &wait);
+ }
+ UINT8 *oprom = ops;
+
+#ifdef HAS_V30
+ return CPU_DISASSEMBLE_CALL(nec_generic) & DASMFLAG_LENGTHMASK;
+#else
+ return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
+#endif
+}
+#endif
+
+#ifdef HAS_I286
+void I286::set_address_mask(uint32_t mask)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->amask = mask;
+}
+
+uint32_t I286::get_address_mask()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->amask;
+}
+
+void I286::set_shutdown_flag(int shutdown)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->shutdown = shutdown;
+}
+
+int I286::get_shutdown_flag()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->shutdown;
+}
+#endif
+
+#define STATE_VERSION 3
+
+void I286::save_state(FILEIO* state_fio)
+{
+ state_fio->FputUint32(STATE_VERSION);
+ state_fio->FputInt32(this_device_id);
+
+ state_fio->Fwrite(opaque, sizeof(cpu_state), 1);
+}
+
+bool I286::load_state(FILEIO* state_fio)
+{
+ if(state_fio->FgetUint32() != STATE_VERSION) {
+ return false;
+ }
+ if(state_fio->FgetInt32() != this_device_id) {
+ return false;
+ }
+ state_fio->Fread(opaque, sizeof(cpu_state), 1);
+
+ // post process
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->pic = d_pic;
+ cpustate->program = d_mem;
+ cpustate->io = d_io;
+#ifdef I86_PSEUDO_BIOS
+ cpustate->bios = d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpustate->dma = d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ cpustate->emu = emu;
+ cpustate->debugger = d_debugger;
+ cpustate->program_stored = d_mem;
+ cpustate->io_stored = d_io;
+#endif
+ return true;
+}
+
--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Author : Takeda.Toshiya
+ Date : 2012.10.18-
+
+ [ i286 ]
+*/
+
+#ifndef _I286_H_
+#define _I286_H_
+
+#include "vm.h"
+#include "../emu.h"
+#include "device.h"
+
+#define SIG_I86_TEST 0
+#define SIG_I86_A20 1
+
+#ifdef USE_DEBUGGER
+class DEBUGGER;
+#endif
+
+class I286 : public DEVICE
+{
+private:
+ DEVICE *d_mem, *d_io, *d_pic;
+#ifdef I86_PSEUDO_BIOS
+ DEVICE *d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ DEVICE *d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ DEBUGGER *d_debugger;
+#endif
+ void *opaque;
+
+public:
+ I286(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+#ifdef I86_PSEUDO_BIOS
+ d_bios = NULL;
+#endif
+#ifdef SINGLE_MODE_DMA
+ d_dma = NULL;
+#endif
+#if defined(HAS_I86)
+ set_device_name(_T("i8086 CPU"));
+#elif defined(HAS_I88)
+ set_device_name(_T("i8088 CPU"));
+#elif defined(HAS_I186)
+ set_device_name(_T("i80186 CPU"));
+#elif defined(HAS_V30)
+ set_device_name(_T("V30 CPU"));
+#elif defined(HAS_I286)
+ set_device_name(_T("i80286 CPU"));
+#endif
+ }
+ ~I286() {}
+
+ // common functions
+ void initialize();
+ void release();
+ void reset();
+ int run(int icount);
+ void write_signal(int id, uint32_t data, uint32_t mask);
+ void set_intr_line(bool line, bool pending, uint32_t bit);
+ void set_extra_clock(int icount);
+ int get_extra_clock();
+ uint32_t get_pc();
+ uint32_t get_next_pc();
+#ifdef USE_DEBUGGER
+ void *get_debugger()
+ {
+ return d_debugger;
+ }
+ uint32_t get_debug_prog_addr_mask()
+ {
+#ifdef HAS_I286
+ return 0xffffff;
+#else
+ return 0xfffff;
+#endif
+ }
+ uint32_t get_debug_data_addr_mask()
+ {
+#ifdef HAS_I286
+ return 0xffffff;
+#else
+ return 0xfffff;
+#endif
+ }
+ void write_debug_data8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data8(uint32_t addr);
+ void write_debug_data16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data16(uint32_t addr);
+ void write_debug_io8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io8(uint32_t addr);
+ void write_debug_io16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io16(uint32_t addr);
+ bool write_debug_reg(const _TCHAR *reg, uint32_t data);
+ void get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
+ int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len);
+#endif
+ void save_state(FILEIO* state_fio);
+ bool load_state(FILEIO* state_fio);
+
+ // unique function
+ void set_context_mem(DEVICE* device)
+ {
+ d_mem = device;
+ }
+ void set_context_io(DEVICE* device)
+ {
+ d_io = device;
+ }
+ void set_context_intr(DEVICE* device)
+ {
+ d_pic = device;
+ }
+#ifdef I86_PSEUDO_BIOS
+ void set_context_bios(DEVICE* device)
+ {
+ d_bios = device;
+ }
+#endif
+#ifdef SINGLE_MODE_DMA
+ void set_context_dma(DEVICE* device)
+ {
+ d_dma = device;
+ }
+#endif
+#ifdef USE_DEBUGGER
+ void set_context_debugger(DEBUGGER* device)
+ {
+ d_debugger = device;
+ }
+#endif
+#ifdef HAS_I286
+ void set_address_mask(uint32_t mask);
+ uint32_t get_address_mask();
+ void set_shutdown_flag(int shutdown);
+ int get_shutdown_flag();
+#endif
+};
+
+#endif
--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Author : Takeda.Toshiya
+ Date : 2012.10.18-
+
+ [ i286 ]
+*/
+
+#include "i286.h"
+#ifdef USE_DEBUGGER
+#include "debugger.h"
+#endif
+
+/* ----------------------------------------------------------------------------
+ MAME i286
+---------------------------------------------------------------------------- */
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning( disable : 4018 )
+#pragma warning( disable : 4146 )
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4996 )
+#endif
+
+#if defined(HAS_I86)
+ #define CPU_MODEL i8086
+#elif defined(HAS_I88)
+ #define CPU_MODEL i8088
+#elif defined(HAS_I186)
+ #define CPU_MODEL i80186
+#elif defined(HAS_V30)
+ #define CPU_MODEL v30
+#elif defined(HAS_I286)
+ #define CPU_MODEL i80286
+#endif
+
+#ifndef __BIG_ENDIAN__
+#define LSB_FIRST
+#endif
+
+#ifndef INLINE
+#define INLINE inline
+#endif
+
+#define logerror(...)
+
+/*****************************************************************************/
+/* src/emu/devcpu.h */
+
+// CPU interface functions
+#define CPU_INIT_NAME(name) cpu_init_##name
+#define CPU_INIT(name) void* CPU_INIT_NAME(name)()
+#define CPU_INIT_CALL(name) CPU_INIT_NAME(name)()
+
+#define CPU_RESET_NAME(name) cpu_reset_##name
+#define CPU_RESET(name) void CPU_RESET_NAME(name)(cpu_state *cpustate)
+#define CPU_RESET_CALL(name) CPU_RESET_NAME(name)(cpustate)
+
+#define CPU_EXECUTE_NAME(name) cpu_execute_##name
+#define CPU_EXECUTE(name) int CPU_EXECUTE_NAME(name)(cpu_state *cpustate, int icount)
+#define CPU_EXECUTE_CALL(name) CPU_EXECUTE_NAME(name)(cpustate, icount)
+
+#define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
+#define CPU_DISASSEMBLE(name) int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t eip, const UINT8 *oprom)
+#define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(buffer, eip, oprom)
+
+/*****************************************************************************/
+/* src/emu/didisasm.h */
+
+// Disassembler constants
+const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
+const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
+const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
+const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
+const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
+const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
+
+/*****************************************************************************/
+/* src/emu/diexec.h */
+
+// I/O line states
+enum line_state
+{
+ CLEAR_LINE = 0, // clear (a fired or held) line
+ ASSERT_LINE, // assert an interrupt immediately
+ HOLD_LINE, // hold interrupt line until acknowledged
+ PULSE_LINE // pulse interrupt line instantaneously (only for NMI, RESET)
+};
+
+enum
+{
+ INPUT_LINE_IRQ = 0,
+ INPUT_LINE_NMI
+};
+
+/*****************************************************************************/
+/* src/emu/emucore.h */
+
+// constants for expression endianness
+enum endianness_t
+{
+ ENDIANNESS_LITTLE,
+ ENDIANNESS_BIG
+};
+
+// declare native endianness to be one or the other
+#ifdef LSB_FIRST
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
+#else
+const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
+#endif
+// endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
+#define ENDIAN_VALUE_LE_BE(endian,leval,beval) (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
+// endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
+#define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval) ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
+// endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
+#define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
+
+/*****************************************************************************/
+/* src/emu/memory.h */
+
+// offsets and addresses are 32-bit (for now...)
+typedef UINT32 offs_t;
+
+/*****************************************************************************/
+/* src/osd/osdcomm.h */
+
+/* Highly useful macro for compile-time knowledge of an array size */
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
+
+#if defined(HAS_I86) || defined(HAS_I88) || defined(HAS_I186) || defined(HAS_V30)
+#define cpu_state i8086_state
+#include "mame/emu/cpu/i86/i86.c"
+#elif defined(HAS_I286)
+#define cpu_state i80286_state
+#include "mame/emu/cpu/i86/i286.c"
+#endif
+#ifdef USE_DEBUGGER
+#ifdef HAS_V30
+#include "mame/emu/cpu/nec/necdasm.c"
+#else
+#include "mame/emu/cpu/i386/i386dasm.c"
+#endif
+#endif
+
+void I286::initialize()
+{
+ opaque = CPU_INIT_CALL(CPU_MODEL);
+
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->pic = d_pic;
+ cpustate->program = d_mem;
+ cpustate->io = d_io;
+#ifdef I86_PSEUDO_BIOS
+ cpustate->bios = d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpustate->dma = d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ cpustate->emu = emu;
+ cpustate->debugger = d_debugger;
+ cpustate->program_stored = d_mem;
+ cpustate->io_stored = d_io;
+
+ d_debugger->set_context_mem(d_mem);
+ d_debugger->set_context_io(d_io);
+#endif
+}
+
+void I286::release()
+{
+ free(opaque);
+}
+
+void I286::reset()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ int busreq = cpustate->busreq;
+
+ CPU_RESET_CALL(CPU_MODEL);
+
+ cpustate->pic = d_pic;
+ cpustate->program = d_mem;
+ cpustate->io = d_io;
+#ifdef I86_PSEUDO_BIOS
+ cpustate->bios = d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpustate->dma = d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ cpustate->emu = emu;
+ cpustate->debugger = d_debugger;
+ cpustate->program_stored = d_mem;
+ cpustate->io_stored = d_io;
+#endif
+ cpustate->busreq = busreq;
+}
+
+int I286::run(int icount)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return CPU_EXECUTE_CALL(CPU_MODEL);
+}
+
+void I286::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+
+ if(id == SIG_CPU_NMI) {
+ set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
+ } else if(id == SIG_CPU_IRQ) {
+ set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
+ } else if(id == SIG_CPU_BUSREQ) {
+ cpustate->busreq = (data & mask) ? 1 : 0;
+ } else if(id == SIG_I86_TEST) {
+ cpustate->test_state = (data & mask) ? 1 : 0;
+#ifdef HAS_I286
+ } else if(id == SIG_I86_A20) {
+ i80286_set_a20_line(cpustate, data & mask);
+#endif
+ }
+}
+
+void I286::set_intr_line(bool line, bool pending, uint32_t bit)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
+}
+
+void I286::set_extra_clock(int icount)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->extra_cycles += icount;
+}
+
+int I286::get_extra_clock()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->extra_cycles;
+}
+
+uint32_t I286::get_pc()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->prevpc;
+}
+
+uint32_t I286::get_next_pc()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->pc;
+}
+
+#ifdef USE_DEBUGGER
+void I286::write_debug_data8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem->write_data8w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_data8(uint32_t addr)
+{
+ int wait;
+ return d_mem->read_data8w(addr, &wait);
+}
+
+void I286::write_debug_data16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem->write_data16w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_data16(uint32_t addr)
+{
+ int wait;
+ return d_mem->read_data16w(addr, &wait);
+}
+
+void I286::write_debug_io8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io->write_io8w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_io8(uint32_t addr) {
+ int wait;
+ return d_io->read_io8w(addr, &wait);
+}
+
+void I286::write_debug_io16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io->write_io16w(addr, data, &wait);
+}
+
+uint32_t I286::read_debug_io16(uint32_t addr) {
+ int wait;
+ return d_io->read_io16w(addr, &wait);
+}
+
+bool I286::write_debug_reg(const _TCHAR *reg, uint32_t data)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ if(_tcsicmp(reg, _T("IP")) == 0) {
+ cpustate->pc = ((data & 0xffff) + cpustate->base[CS]) & AMASK;
+ CHANGE_PC(cpustate->pc);
+ } else if(_tcsicmp(reg, _T("AX")) == 0) {
+ cpustate->regs.w[AX] = data;
+ } else if(_tcsicmp(reg, _T("BX")) == 0) {
+ cpustate->regs.w[BX] = data;
+ } else if(_tcsicmp(reg, _T("CX")) == 0) {
+ cpustate->regs.w[CX] = data;
+ } else if(_tcsicmp(reg, _T("DX")) == 0) {
+ cpustate->regs.w[DX] = data;
+ } else if(_tcsicmp(reg, _T("SP")) == 0) {
+ cpustate->regs.w[SP] = data;
+ } else if(_tcsicmp(reg, _T("BP")) == 0) {
+ cpustate->regs.w[BP] = data;
+ } else if(_tcsicmp(reg, _T("SI")) == 0) {
+ cpustate->regs.w[SI] = data;
+ } else if(_tcsicmp(reg, _T("DI")) == 0) {
+ cpustate->regs.w[DI] = data;
+ } else if(_tcsicmp(reg, _T("AL")) == 0) {
+ cpustate->regs.b[AL] = data;
+ } else if(_tcsicmp(reg, _T("AH")) == 0) {
+ cpustate->regs.b[AH] = data;
+ } else if(_tcsicmp(reg, _T("BL")) == 0) {
+ cpustate->regs.b[BL] = data;
+ } else if(_tcsicmp(reg, _T("BH")) == 0) {
+ cpustate->regs.b[BH] = data;
+ } else if(_tcsicmp(reg, _T("CL")) == 0) {
+ cpustate->regs.b[CL] = data;
+ } else if(_tcsicmp(reg, _T("CH")) == 0) {
+ cpustate->regs.b[CH] = data;
+ } else if(_tcsicmp(reg, _T("DL")) == 0) {
+ cpustate->regs.b[DL] = data;
+ } else if(_tcsicmp(reg, _T("DH")) == 0) {
+ cpustate->regs.b[DH] = data;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void I286::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ my_stprintf_s(buffer, buffer_len,
+ _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]"),
+ cpustate->regs.w[AX], cpustate->regs.w[BX], cpustate->regs.w[CX], cpustate->regs.w[DX], cpustate->regs.w[SP], cpustate->regs.w[BP], cpustate->regs.w[SI], cpustate->regs.w[DI],
+ cpustate->sregs[DS], cpustate->sregs[ES], cpustate->sregs[SS], cpustate->sregs[CS], cpustate->pc - cpustate->base[CS],
+ OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
+ SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'));
+}
+
+int I286::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ UINT64 eip = pc - cpustate->base[CS];
+ UINT8 ops[16];
+ for(int i = 0; i < 16; i++) {
+ int wait;
+ ops[i] = d_mem->read_data8w(pc + i, &wait);
+ }
+ UINT8 *oprom = ops;
+
+#ifdef HAS_V30
+ return CPU_DISASSEMBLE_CALL(nec_generic) & DASMFLAG_LENGTHMASK;
+#else
+ return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
+#endif
+}
+#endif
+
+#ifdef HAS_I286
+void I286::set_address_mask(uint32_t mask)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->amask = mask;
+}
+
+uint32_t I286::get_address_mask()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->amask;
+}
+
+void I286::set_shutdown_flag(int shutdown)
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->shutdown = shutdown;
+}
+
+int I286::get_shutdown_flag()
+{
+ cpu_state *cpustate = (cpu_state *)opaque;
+ return cpustate->shutdown;
+}
+#endif
+
+#define STATE_VERSION 3
+
+void I286::save_state(FILEIO* state_fio)
+{
+ state_fio->FputUint32(STATE_VERSION);
+ state_fio->FputInt32(this_device_id);
+
+ state_fio->Fwrite(opaque, sizeof(cpu_state), 1);
+}
+
+bool I286::load_state(FILEIO* state_fio)
+{
+ if(state_fio->FgetUint32() != STATE_VERSION) {
+ return false;
+ }
+ if(state_fio->FgetInt32() != this_device_id) {
+ return false;
+ }
+ state_fio->Fread(opaque, sizeof(cpu_state), 1);
+
+ // post process
+ cpu_state *cpustate = (cpu_state *)opaque;
+ cpustate->pic = d_pic;
+ cpustate->program = d_mem;
+ cpustate->io = d_io;
+#ifdef I86_PSEUDO_BIOS
+ cpustate->bios = d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ cpustate->dma = d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ cpustate->emu = emu;
+ cpustate->debugger = d_debugger;
+ cpustate->program_stored = d_mem;
+ cpustate->io_stored = d_io;
+#endif
+ return true;
+}
+
--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Author : Takeda.Toshiya
+ Date : 2012.10.18-
+
+ [ i286 ]
+*/
+
+#ifndef _I286_H_
+#define _I286_H_
+
+#include "vm.h"
+#include "../emu.h"
+#include "device.h"
+
+#define SIG_I86_TEST 0
+#define SIG_I86_A20 1
+
+#ifdef USE_DEBUGGER
+class DEBUGGER;
+#endif
+
+class I286 : public DEVICE
+{
+private:
+ DEVICE *d_mem, *d_io, *d_pic;
+#ifdef I86_PSEUDO_BIOS
+ DEVICE *d_bios;
+#endif
+#ifdef SINGLE_MODE_DMA
+ DEVICE *d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ DEBUGGER *d_debugger;
+#endif
+ void *opaque;
+
+public:
+ I286(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+#ifdef I86_PSEUDO_BIOS
+ d_bios = NULL;
+#endif
+#ifdef SINGLE_MODE_DMA
+ d_dma = NULL;
+#endif
+#if defined(HAS_I86)
+ set_device_name(_T("i8086 CPU"));
+#elif defined(HAS_I88)
+ set_device_name(_T("i8088 CPU"));
+#elif defined(HAS_I186)
+ set_device_name(_T("i80186 CPU"));
+#elif defined(HAS_V30)
+ set_device_name(_T("V30 CPU"));
+#elif defined(HAS_I286)
+ set_device_name(_T("i80286 CPU"));
+#endif
+ }
+ ~I286() {}
+
+ // common functions
+ void initialize();
+ void release();
+ void reset();
+ int run(int icount);
+ void write_signal(int id, uint32_t data, uint32_t mask);
+ void set_intr_line(bool line, bool pending, uint32_t bit);
+ void set_extra_clock(int icount);
+ int get_extra_clock();
+ uint32_t get_pc();
+ uint32_t get_next_pc();
+#ifdef USE_DEBUGGER
+ void *get_debugger()
+ {
+ return d_debugger;
+ }
+ uint32_t get_debug_prog_addr_mask()
+ {
+#ifdef HAS_I286
+ return 0xffffff;
+#else
+ return 0xfffff;
+#endif
+ }
+ uint32_t get_debug_data_addr_mask()
+ {
+#ifdef HAS_I286
+ return 0xffffff;
+#else
+ return 0xfffff;
+#endif
+ }
+ void write_debug_data8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data8(uint32_t addr);
+ void write_debug_data16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data16(uint32_t addr);
+ void write_debug_io8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io8(uint32_t addr);
+ void write_debug_io16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io16(uint32_t addr);
+ bool write_debug_reg(const _TCHAR *reg, uint32_t data);
+ void get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
+ int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len);
+#endif
+ void save_state(FILEIO* state_fio);
+ bool load_state(FILEIO* state_fio);
+
+ // unique function
+ void set_context_mem(DEVICE* device)
+ {
+ d_mem = device;
+ }
+ void set_context_io(DEVICE* device)
+ {
+ d_io = device;
+ }
+ void set_context_intr(DEVICE* device)
+ {
+ d_pic = device;
+ }
+#ifdef I86_PSEUDO_BIOS
+ void set_context_bios(DEVICE* device)
+ {
+ d_bios = device;
+ }
+#endif
+#ifdef SINGLE_MODE_DMA
+ void set_context_dma(DEVICE* device)
+ {
+ d_dma = device;
+ }
+#endif
+#ifdef USE_DEBUGGER
+ void set_context_debugger(DEBUGGER* device)
+ {
+ d_debugger = device;
+ }
+#endif
+#ifdef HAS_I286
+ void set_address_mask(uint32_t mask);
+ uint32_t get_address_mask();
+ void set_shutdown_flag(int shutdown);
+ int get_shutdown_flag();
+#endif
+};
+
+#endif
--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Origin : MAME 0.142
+ Author : Takeda.Toshiya
+ Date : 2011.04.23-
+
+ [ i86/v30 ]
+*/
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning( disable : 4146 )
+#pragma warning( disable : 4996 )
+#endif
+
+#include "i86.h"
+#ifdef USE_DEBUGGER
+#include "debugger.h"
+#endif
+
+#define DIVIDE_FAULT 0
+#define NMI_INT_VECTOR 2
+#define OVERFLOW_TRAP 4
+#define BOUNDS_CHECK_FAULT 5
+#define ILLEGAL_INSTRUCTION 6
+#define GENERAL_PROTECTION_FAULT 13
+
+#define INT_REQ_BIT 1
+#define NMI_REQ_BIT 2
+
+typedef enum { ES, CS, SS, DS } SREGS;
+typedef enum { AX, CX, DX, BX, SP, BP, SI, DI } WREGS;
+
+typedef enum {
+#ifdef __BIG_ENDIAN__
+ AH, AL, CH, CL, DH, DL, BH, BL,
+ SPH, SPL, BPH, BPL, SIH, SIL, DIH, DIL,
+#else
+ AL, AH, CL, CH, DL, DH, BL, BH,
+ SPL, SPH, BPL, BPH, SIL, SIH, DIL, DIH,
+#endif
+} BREGS;
+
+static struct {
+ struct {
+ WREGS w[256];
+ BREGS b[256];
+ } reg;
+ struct {
+ WREGS w[256];
+ BREGS b[256];
+ } RM;
+} Mod_RM;
+
+static const uint8_t parity_table[256] = {
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+/************************************************************************/
+
+struct i80x86_timing {
+ uint8_t exception, iret; /* exception, IRET */
+ uint8_t int3, int_imm, into_nt, into_t; /* INTs */
+ uint8_t override; /* segment overrides */
+ uint8_t flag_ops, lahf, sahf; /* flag operations */
+ uint8_t aaa, aas, aam, aad; /* arithmetic adjusts */
+ uint8_t daa, das; /* decimal adjusts */
+ uint8_t cbw, cwd; /* sign extension */
+ uint8_t hlt, load_ptr, lea, nop, wait, xlat; /* misc */
+
+ uint8_t jmp_short, jmp_near, jmp_far; /* direct JMPs */
+ uint8_t jmp_r16, jmp_m16, jmp_m32; /* indirect JMPs */
+ uint8_t call_near, call_far; /* direct CALLs */
+ uint8_t call_r16, call_m16, call_m32; /* indirect CALLs */
+ uint8_t ret_near, ret_far, ret_near_imm, ret_far_imm; /* returns */
+ uint8_t jcc_nt, jcc_t, jcxz_nt, jcxz_t; /* conditional JMPs */
+ uint8_t loop_nt, loop_t, loope_nt, loope_t; /* loops */
+
+ uint8_t in_imm8, in_imm16, in_dx8, in_dx16; /* port reads */
+ uint8_t out_imm8, out_imm16, out_dx8, out_dx16; /* port writes */
+
+ uint8_t mov_rr8, mov_rm8, mov_mr8; /* move, 8-bit */
+ uint8_t mov_ri8, mov_mi8; /* move, 8-bit immediate */
+ uint8_t mov_rr16, mov_rm16, mov_mr16; /* move, 16-bit */
+ uint8_t mov_ri16, mov_mi16; /* move, 16-bit immediate */
+ uint8_t mov_am8, mov_am16, mov_ma8, mov_ma16; /* move, AL/AX memory */
+ uint8_t mov_sr, mov_sm, mov_rs, mov_ms; /* move, segment registers */
+ uint8_t xchg_rr8, xchg_rm8; /* exchange, 8-bit */
+ uint8_t xchg_rr16, xchg_rm16, xchg_ar16; /* exchange, 16-bit */
+
+ uint8_t push_r16, push_m16, push_seg, pushf; /* pushes */
+ uint8_t pop_r16, pop_m16, pop_seg, popf; /* pops */
+
+ uint8_t alu_rr8, alu_rm8, alu_mr8; /* ALU ops, 8-bit */
+ uint8_t alu_ri8, alu_mi8, alu_mi8_ro; /* ALU ops, 8-bit immediate */
+ uint8_t alu_rr16, alu_rm16, alu_mr16; /* ALU ops, 16-bit */
+ uint8_t alu_ri16, alu_mi16, alu_mi16_ro; /* ALU ops, 16-bit immediate */
+ uint8_t alu_r16i8, alu_m16i8, alu_m16i8_ro; /* ALU ops, 16-bit w/8-bit immediate */
+ uint8_t mul_r8, mul_r16, mul_m8, mul_m16; /* MUL */
+ uint8_t imul_r8, imul_r16, imul_m8, imul_m16; /* IMUL */
+ uint8_t div_r8, div_r16, div_m8, div_m16; /* DIV */
+ uint8_t idiv_r8, idiv_r16, idiv_m8, idiv_m16; /* IDIV */
+ uint8_t incdec_r8, incdec_r16, incdec_m8, incdec_m16; /* INC/DEC */
+ uint8_t negnot_r8, negnot_r16, negnot_m8, negnot_m16; /* NEG/NOT */
+
+ uint8_t rot_reg_1, rot_reg_base, rot_reg_bit; /* reg shift/rotate */
+ uint8_t rot_m8_1, rot_m8_base, rot_m8_bit; /* m8 shift/rotate */
+ uint8_t rot_m16_1, rot_m16_base, rot_m16_bit; /* m16 shift/rotate */
+
+ uint8_t cmps8, rep_cmps8_base, rep_cmps8_count; /* CMPS 8-bit */
+ uint8_t cmps16, rep_cmps16_base, rep_cmps16_count; /* CMPS 16-bit */
+ uint8_t scas8, rep_scas8_base, rep_scas8_count; /* SCAS 8-bit */
+ uint8_t scas16, rep_scas16_base, rep_scas16_count; /* SCAS 16-bit */
+ uint8_t lods8, rep_lods8_base, rep_lods8_count; /* LODS 8-bit */
+ uint8_t lods16, rep_lods16_base, rep_lods16_count; /* LODS 16-bit */
+ uint8_t stos8, rep_stos8_base, rep_stos8_count; /* STOS 8-bit */
+ uint8_t stos16, rep_stos16_base, rep_stos16_count; /* STOS 16-bit */
+ uint8_t movs8, rep_movs8_base, rep_movs8_count; /* MOVS 8-bit */
+ uint8_t movs16, rep_movs16_base, rep_movs16_count; /* MOVS 16-bit */
+
+ uint8_t ins8, rep_ins8_base, rep_ins8_count; /* (80186) INS 8-bit */
+ uint8_t ins16, rep_ins16_base, rep_ins16_count; /* (80186) INS 16-bit */
+ uint8_t outs8, rep_outs8_base, rep_outs8_count; /* (80186) OUTS 8-bit */
+ uint8_t outs16, rep_outs16_base, rep_outs16_count; /* (80186) OUTS 16-bit */
+ uint8_t push_imm, pusha, popa; /* (80186) PUSH immediate, PUSHA/POPA */
+ uint8_t imul_rri8, imul_rmi8; /* (80186) IMUL immediate 8-bit */
+ uint8_t imul_rri16, imul_rmi16; /* (80186) IMUL immediate 16-bit */
+ uint8_t enter0, enter1, enter_base, enter_count, leave; /* (80186) ENTER/LEAVE */
+ uint8_t bound; /* (80186) BOUND */
+};
+
+#if defined(HAS_I86)
+/* these come from the 8088 timings in OPCODE.LST, but with the
+ penalty for 16-bit memory accesses removed wherever possible */
+static const struct i80x86_timing timing = {
+ 51, 32, /* exception, IRET */
+ 2, 0, 4, 2, /* INTs */
+ 2, /* segment overrides */
+ 2, 4, 4, /* flag operations */
+ 4, 4, 83, 60, /* arithmetic adjusts */
+ 4, 4, /* decimal adjusts */
+ 2, 5, /* sign extension */
+ 2, 24, 2, 2, 3, 11, /* misc */
+
+ 15, 15, 15, /* direct JMPs */
+ 11, 18, 24, /* indirect JMPs */
+ 19, 28, /* direct CALLs */
+ 16, 21, 37, /* indirect CALLs */
+ 20, 32, 24, 31, /* returns */
+ 4, 16, 6, 18, /* conditional JMPs */
+ 5, 17, 6, 18, /* loops */
+
+ 10, 14, 8, 12, /* port reads */
+ 10, 14, 8, 12, /* port writes */
+
+ 2, 8, 9, /* move, 8-bit */
+ 4, 10, /* move, 8-bit immediate */
+ 2, 8, 9, /* move, 16-bit */
+ 4, 10, /* move, 16-bit immediate */
+ 10, 10, 10, 10, /* move, AL/AX memory */
+ 2, 8, 2, 9, /* move, segment registers */
+ 4, 17, /* exchange, 8-bit */
+ 4, 17, 3, /* exchange, 16-bit */
+
+ 15, 24, 14, 14, /* pushes */
+ 12, 25, 12, 12, /* pops */
+
+ 3, 9, 16, /* ALU ops, 8-bit */
+ 4, 17, 10, /* ALU ops, 8-bit immediate */
+ 3, 9, 16, /* ALU ops, 16-bit */
+ 4, 17, 10, /* ALU ops, 16-bit immediate */
+ 4, 17, 10, /* ALU ops, 16-bit w/8-bit immediate */
+ 70, 118, 76, 128, /* MUL */
+ 80, 128, 86, 138, /* IMUL */
+ 80, 144, 86, 154, /* DIV */
+ 101, 165, 107, 175, /* IDIV */
+ 3, 2, 15, 15, /* INC/DEC */
+ 3, 3, 16, 16, /* NEG/NOT */
+
+ 2, 8, 4, /* reg shift/rotate */
+ 15, 20, 4, /* m8 shift/rotate */
+ 15, 20, 4, /* m16 shift/rotate */
+
+ 22, 9, 21, /* CMPS 8-bit */
+ 22, 9, 21, /* CMPS 16-bit */
+ 15, 9, 14, /* SCAS 8-bit */
+ 15, 9, 14, /* SCAS 16-bit */
+ 12, 9, 11, /* LODS 8-bit */
+ 12, 9, 11, /* LODS 16-bit */
+ 11, 9, 10, /* STOS 8-bit */
+ 11, 9, 10, /* STOS 16-bit */
+ 18, 9, 17, /* MOVS 8-bit */
+ 18, 9, 17, /* MOVS 16-bit */
+};
+#else
+/* these come from the Intel 80186 datasheet */
+static const struct i80x86_timing timing = {
+ 45, 28, /* exception, IRET */
+ 0, 2, 4, 3, /* INTs */
+ 2, /* segment overrides */
+ 2, 2, 3, /* flag operations */
+ 8, 7, 19, 15, /* arithmetic adjusts */
+ 4, 4, /* decimal adjusts */
+ 2, 4, /* sign extension */
+ 2, 18, 6, 2, 6, 11, /* misc */
+
+ 14, 14, 14, /* direct JMPs */
+ 11, 17, 26, /* indirect JMPs */
+ 15, 23, /* direct CALLs */
+ 13, 19, 38, /* indirect CALLs */
+ 16, 22, 18, 25, /* returns */
+ 4, 13, 5, 15, /* conditional JMPs */
+ 6, 16, 6, 16, /* loops */
+
+ 10, 10, 8, 8, /* port reads */
+ 9, 9, 7, 7, /* port writes */
+
+ 2, 9, 12, /* move, 8-bit */
+ 3, 12, /* move, 8-bit immediate */
+ 2, 9, 12, /* move, 16-bit */
+ 4, 13, /* move, 16-bit immediate */
+ 8, 8, 9, 9, /* move, AL/AX memory */
+ 2, 11, 2, 11, /* move, segment registers */
+ 4, 17, /* exchange, 8-bit */
+ 4, 17, 3, /* exchange, 16-bit */
+
+ 10, 16, 9, 9, /* pushes */
+ 10, 20, 8, 8, /* pops */
+
+ 3, 10, 10, /* ALU ops, 8-bit */
+ 4, 16, 10, /* ALU ops, 8-bit immediate */
+ 3, 10, 10, /* ALU ops, 16-bit */
+ 4, 16, 10, /* ALU ops, 16-bit immediate */
+ 4, 16, 10, /* ALU ops, 16-bit w/8-bit immediate */
+ 26, 35, 32, 41, /* MUL */
+ 25, 34, 31, 40, /* IMUL */
+ 29, 38, 35, 44, /* DIV */
+ 44, 53, 50, 59, /* IDIV */
+ 3, 3, 15, 15, /* INC/DEC */
+ 3, 3, 10, 10, /* NEG/NOT */
+
+ 2, 5, 1, /* reg shift/rotate */
+ 15, 17, 1, /* m8 shift/rotate */
+ 15, 17, 1, /* m16 shift/rotate */
+
+ 22, 5, 22, /* CMPS 8-bit */
+ 22, 5, 22, /* CMPS 16-bit */
+ 15, 5, 15, /* SCAS 8-bit */
+ 15, 5, 15, /* SCAS 16-bit */
+ 12, 6, 11, /* LODS 8-bit */
+ 12, 6, 11, /* LODS 16-bit */
+ 10, 6, 9, /* STOS 8-bit */
+ 10, 6, 9, /* STOS 16-bit */
+ 14, 8, 8, /* MOVS 8-bit */
+ 14, 8, 8, /* MOVS 16-bit */
+
+ 14, 8, 8, /* (80186) INS 8-bit */
+ 14, 8, 8, /* (80186) INS 16-bit */
+ 14, 8, 8, /* (80186) OUTS 8-bit */
+ 14, 8, 8, /* (80186) OUTS 16-bit */
+ 14, 68, 83, /* (80186) PUSH immediate, PUSHA/POPA */
+ 22, 29, /* (80186) IMUL immediate 8-bit */
+ 25, 32, /* (80186) IMUL immediate 16-bit */
+ 15, 25, 4, 16, 8, /* (80186) ENTER/LEAVE */
+ 33, /* (80186) BOUND */
+};
+#endif
+
+/************************************************************************/
+
+#define SetTF(x) (TF = (x))
+#define SetIF(x) (IF = (x))
+#define SetDF(x) (DirVal = (x) ? -1 : 1)
+#define SetMD(x) (MF = (x))
+
+#define SetOFW_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
+#define SetOFB_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
+#define SetOFW_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
+#define SetOFB_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
+
+#define SetCFB(x) (CarryVal = (x) & 0x100)
+#define SetCFW(x) (CarryVal = (x) & 0x10000)
+#define SetAF(x, y, z) (AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
+#define SetSF(x) (SignVal = (x))
+#define SetZF(x) (ZeroVal = (x))
+#define SetPF(x) (ParityVal = (x))
+
+#define SetSZPF_Byte(x) (ParityVal = SignVal = ZeroVal = (int8_t)(x))
+#define SetSZPF_Word(x) (ParityVal = SignVal = ZeroVal = (int16_t)(x))
+
+#define ADDB(dst, src) { unsigned res = (dst) + (src); SetCFB(res); SetOFB_Add(res, src, dst); SetAF(res, src, dst); SetSZPF_Byte(res); dst = (uint8_t)res; }
+#define ADDW(dst, src) { unsigned res = (dst) + (src); SetCFW(res); SetOFW_Add(res, src, dst); SetAF(res, src, dst); SetSZPF_Word(res); dst = (uint16_t)res; }
+
+#define SUBB(dst, src) { unsigned res = (dst) - (src); SetCFB(res); SetOFB_Sub(res, src, dst); SetAF(res, src, dst); SetSZPF_Byte(res); dst = (uint8_t)res; }
+#define SUBW(dst, src) { unsigned res = (dst) - (src); SetCFW(res); SetOFW_Sub(res, src, dst); SetAF(res, src, dst); SetSZPF_Word(res); dst = (uint16_t)res; }
+
+#define ORB(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
+#define ORW(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
+
+#define ANDB(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
+#define ANDW(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
+
+#define XORB(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
+#define XORW(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
+
+#define CF (CarryVal != 0)
+#define SF (SignVal < 0)
+#define ZF (ZeroVal == 0)
+#define PF parity_table[ParityVal]
+#define AF (AuxVal != 0)
+#define OF (OverVal != 0)
+#define DF (DirVal < 0)
+#define MD (MF != 0)
+
+/************************************************************************/
+
+#define AMASK 0xfffff
+
+#define read_mem_byte(a) d_mem->read_data8((a) & AMASK)
+#define read_mem_word(a) d_mem->read_data16((a) & AMASK)
+#define write_mem_byte(a, d) d_mem->write_data8((a) & AMASK, (d))
+#define write_mem_word(a, d) d_mem->write_data16((a) & AMASK, (d))
+
+#define read_port_byte(a) d_io->read_io8(a)
+#define read_port_word(a) d_io->read_io16(a)
+#define write_port_byte(a, d) d_io->write_io8((a), (d))
+#define write_port_word(a, d) d_io->write_io16((a), (d))
+
+/************************************************************************/
+
+#define SegBase(Seg) (sregs[Seg] << 4)
+
+#define DefaultSeg(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? prefix_seg : Seg)
+#define DefaultBase(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? base[prefix_seg] : base[Seg])
+
+#define GetMemB(Seg, Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK))
+#define GetMemW(Seg, Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK))
+#define PutMemB(Seg, Off, x) write_mem_byte((DefaultBase(Seg) + (Off)) & AMASK, (x))
+#define PutMemW(Seg, Off, x) write_mem_word((DefaultBase(Seg) + (Off)) & AMASK, (x))
+
+#define ReadByte(ea) (read_mem_byte((ea) & AMASK))
+#define ReadWord(ea) (read_mem_word((ea) & AMASK))
+#define WriteByte(ea, val) write_mem_byte((ea) & AMASK, val);
+#define WriteWord(ea, val) write_mem_word((ea) & AMASK, val);
+
+#define FETCH read_mem_byte(pc++)
+#define FETCHOP read_mem_byte(pc++)
+#define FETCHWORD(var) { var = read_mem_word(pc); pc += 2; }
+#define PUSH(val) { regs.w[SP] -= 2; WriteWord(((base[SS] + regs.w[SP]) & AMASK), val); }
+#define POP(var) { regs.w[SP] += 2; var = ReadWord(((base[SS] + ((regs.w[SP]-2) & 0xffff)) & AMASK)); }
+
+/************************************************************************/
+
+#define CompressFlags() (uint16_t)(CF | (PF << 2) | (AF << 4) | (ZF << 6) | (SF << 7) | (TF << 8) | (IF << 9) | (DF << 10) | (OF << 11) | (MD << 15))
+
+#define ExpandFlags(f) { \
+ CarryVal = (f) & 1; \
+ ParityVal = !((f) & 4); \
+ AuxVal = (f) & 0x10; \
+ ZeroVal = !((f) & 0x40); \
+ SignVal = ((f) & 0x80) ? -1 : 0; \
+ TF = ((f) & 0x100) >> 8; \
+ IF = ((f) & 0x200) >> 9; \
+ MF = ((f) & 0x8000) >> 15; \
+ DirVal = ((f) & 0x400) ? -1 : 1; \
+ OverVal = (f) & 0x800; \
+}
+
+/************************************************************************/
+
+#define RegWord(ModRM) regs.w[Mod_RM.reg.w[ModRM]]
+#define RegByte(ModRM) regs.b[Mod_RM.reg.b[ModRM]]
+
+#define GetRMWord(ModRM) \
+ ((ModRM) >= 0xc0 ? regs.w[Mod_RM.RM.w[ModRM]] : (GetEA(ModRM), ReadWord(ea)))
+
+#define PutbackRMWord(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.w[Mod_RM.RM.w[ModRM]] = val; \
+ } else { \
+ WriteWord(ea, val); \
+ } \
+}
+
+#define GetNextRMWord ( \
+ ReadWord(ea + 2) \
+)
+
+#define GetRMWordOffset(offs) ( \
+ ReadWord(ea - eo + (uint16_t)(eo + offs)) \
+)
+
+#define GetRMByteOffset(offs) ( \
+ ReadByte(ea - eo + (uint16_t)(eo + offs)) \
+)
+
+#define PutRMWord(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.w[Mod_RM.RM.w[ModRM]] = val; \
+ } else { \
+ GetEA(ModRM); \
+ WriteWord(ea, val); \
+ } \
+}
+
+#define PutRMWordOffset(offs, val) \
+ WriteWord(ea - eo + (uint16_t)(eo + offs), val)
+
+#define PutRMByteOffset(offs, val) \
+ WriteByte(ea - eo + (uint16_t)(eo + offs), val)
+
+#define PutImmRMWord(ModRM) { \
+ uint16_t val; \
+ if (ModRM >= 0xc0) { \
+ FETCHWORD(regs.w[Mod_RM.RM.w[ModRM]]) \
+ } else { \
+ GetEA(ModRM); \
+ FETCHWORD(val) \
+ WriteWord(ea, val); \
+ } \
+}
+
+#define GetRMByte(ModRM) \
+ ((ModRM) >= 0xc0 ? regs.b[Mod_RM.RM.b[ModRM]] : (GetEA(ModRM), ReadByte(ea)))
+
+#define PutRMByte(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.b[Mod_RM.RM.b[ModRM]] = val; \
+ } else { \
+ GetEA(ModRM); \
+ WriteByte(ea, val); \
+ } \
+}
+
+#define PutImmRMByte(ModRM) { \
+ if (ModRM >= 0xc0) { \
+ regs.b[Mod_RM.RM.b[ModRM]] = FETCH; \
+ } else { \
+ GetEA(ModRM); \
+ WriteByte(ea, FETCH); \
+ } \
+}
+
+#define PutbackRMByte(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.b[Mod_RM.RM.b[ModRM]] = val; \
+ } else { \
+ WriteByte(ea, val); \
+ } \
+}
+
+#define DEF_br8(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegByte(ModRM); \
+ unsigned dst = GetRMByte(ModRM)
+
+#define DEF_wr16(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegWord(ModRM); \
+ unsigned dst = GetRMWord(ModRM)
+
+#define DEF_r8b(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegByte(ModRM); \
+ unsigned src = GetRMByte(ModRM)
+
+#define DEF_r16w(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegWord(ModRM); \
+ unsigned src = GetRMWord(ModRM)
+
+#define DEF_ald8(dst, src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = regs.b[AL]
+
+#define DEF_axd16(dst, src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = regs.w[AX]; \
+ src += (FETCH << 8)
+
+/************************************************************************/
+
+#ifndef INLINE
+#define INLINE inline
+#endif
+
+#define offs_t UINT32
+
+// Disassembler constants
+const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
+const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
+const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
+const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
+const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
+const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
+
+/* Highly useful macro for compile-time knowledge of an array size */
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
+
+int necv_dasm_one(_TCHAR *buffer, UINT32 eip, const UINT8 *oprom);
+
+void I86::initialize()
+{
+ static const BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH};
+
+ for(int i = 0; i < 256; i++) {
+ Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
+ Mod_RM.reg.w[i] = (WREGS)((i & 0x38) >> 3);
+ }
+ for(int i = 0xc0; i < 0x100; i++) {
+ Mod_RM.RM.w[i] = (WREGS)(i & 7);
+ Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
+ }
+#ifdef USE_DEBUGGER
+ d_mem_stored = d_mem;
+ d_io_stored = d_io;
+ d_debugger->set_context_mem(d_mem);
+ d_debugger->set_context_io(d_io);
+#endif
+}
+
+void I86::reset()
+{
+ for(int i = 0; i < 8; i++) {
+ regs.w[i] = 0;
+ }
+ sregs[CS] = 0xf000;
+ sregs[SS] = sregs[DS] = sregs[ES] = 0;
+
+ base[CS] = SegBase(CS);
+ base[SS] = base[DS] = base[ES] = 0;
+
+ ea = 0;
+ eo = 0;
+ AuxVal = OverVal = SignVal = ZeroVal = CarryVal = 0;
+ DirVal = 1;
+ ParityVal = TF = IF = MF = 0;
+
+ icount = extra_icount = 0;
+ int_state = 0;
+ test_state = false;
+ halted = false;
+
+ pc = 0xffff0 & AMASK;
+ flags = 0;
+ ExpandFlags(flags);
+#ifdef HAS_V30
+ SetMD(1);
+#endif
+ seg_prefix = false;
+}
+
+int I86::run(int clock)
+{
+ /* return now if BUSREQ */
+ if(busreq) {
+#ifdef SINGLE_MODE_DMA
+ if(d_dma) {
+ d_dma->do_dma();
+ }
+#endif
+ if(clock == -1) {
+ int passed_icount = max(1, extra_icount);
+ // this is main cpu, icount is not used
+ /*icount = */extra_icount = 0;
+ return passed_icount;
+ } else {
+ icount += clock;
+ int first_icount = icount;
+
+ /* adjust for any interrupts that came in */
+ icount -= extra_icount;
+ extra_icount = 0;
+
+ /* if busreq is raised, spin cpu while remained clock */
+ if(icount > 0) {
+ icount = 0;
+ }
+ return first_icount - icount;
+ }
+ }
+
+ if(clock == -1) {
+ /* run only one opcode */
+ icount = -extra_icount;
+ extra_icount = 0;
+#ifdef USE_DEBUGGER
+ run_one_opecode_debugger();
+#else
+ run_one_opecode();
+#endif
+ return -icount;
+ } else {
+ icount += clock;
+ int first_icount = icount;
+
+ /* adjust for any interrupts that came in */
+ icount -= extra_icount;
+ extra_icount = 0;
+
+ /* run cpu while given clocks */
+ while(icount > 0 && !busreq) {
+#ifdef USE_DEBUGGER
+ run_one_opecode_debugger();
+#else
+ run_one_opecode();
+#endif
+ }
+ /* if busreq is raised, spin cpu while remained clock */
+ if(icount > 0 && busreq) {
+ icount = 0;
+ }
+ return first_icount - icount;
+ }
+}
+
+#ifdef USE_DEBUGGER
+void I86::run_one_opecode_debugger()
+{
+ bool now_debugging = d_debugger->now_debugging;
+ if(now_debugging) {
+ d_debugger->check_break_points(pc);
+ if(d_debugger->now_suspended) {
+ emu->mute_sound();
+ while(d_debugger->now_debugging && d_debugger->now_suspended) {
+ emu->sleep(10);
+ }
+ }
+ if(d_debugger->now_debugging) {
+ d_mem = d_io = d_debugger;
+ } else {
+ now_debugging = false;
+ }
+
+ run_one_opecode();
+ if(now_debugging) {
+ if(!d_debugger->now_going) {
+ d_debugger->now_suspended = true;
+ }
+ d_mem = d_mem_stored;
+ d_io = d_io_stored;
+ }
+ } else {
+ run_one_opecode();
+ }
+}
+#endif
+
+void I86::run_one_opecode()
+{
+ seg_prefix = false;
+#ifdef _JX
+ // ugly patch for PC/JX hardware diagnostics :-(
+#ifdef TIMER_HACK
+ if(pc == 0xff040) pc = 0xff04a;
+ if(pc == 0xff17d) pc = 0xff18f;
+#endif
+#ifdef KEYBOARD_HACK
+ if(pc == 0xfa909) { regs.b[BH] = read_port_byte(0xa1); pc = 0xfa97c; }
+ if(pc == 0xff6e1) { regs.b[AL] = 0x0d; pc += 2; }
+#endif
+#endif
+ instruction(FETCHOP);
+ if(int_state & NMI_REQ_BIT) {
+ if(halted) {
+ pc++;
+ halted = false;
+ }
+ int_state &= ~NMI_REQ_BIT;
+ interrupt(NMI_INT_VECTOR);
+ } else if((int_state & INT_REQ_BIT) && IF) {
+ if(halted) {
+ pc++;
+ halted = false;
+ }
+ interrupt(-1);
+ }
+#ifdef SINGLE_MODE_DMA
+ if(d_dma) {
+ d_dma->do_dma();
+ }
+#endif
+ icount -= extra_icount;
+ extra_icount = 0;
+}
+
+void I86::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ if(id == SIG_CPU_NMI) {
+ if(data & mask) {
+ int_state |= NMI_REQ_BIT;
+ } else {
+ int_state &= ~NMI_REQ_BIT;
+ }
+ } else if(id == SIG_CPU_BUSREQ) {
+ busreq = ((data & mask) != 0);
+ } else if(id == SIG_I86_TEST) {
+ test_state = ((data & mask) != 0);
+ }
+}
+
+void I86::set_intr_line(bool line, bool pending, uint32_t bit)
+{
+ if(line) {
+ int_state |= INT_REQ_BIT;
+ } else {
+ int_state &= ~INT_REQ_BIT;
+ }
+}
+
+#ifdef USE_DEBUGGER
+void I86::write_debug_data8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem_stored->write_data8w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_data8(uint32_t addr)
+{
+ int wait;
+ return d_mem_stored->read_data8w(addr, &wait);
+}
+
+void I86::write_debug_data16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem_stored->write_data16w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_data16(uint32_t addr)
+{
+ int wait;
+ return d_mem_stored->read_data16w(addr, &wait);
+}
+
+void I86::write_debug_io8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io_stored->write_io8w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_io8(uint32_t addr) {
+ int wait;
+ return d_io_stored->read_io8w(addr, &wait);
+}
+
+void I86::write_debug_io16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io_stored->write_io16w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_io16(uint32_t addr) {
+ int wait;
+ return d_io_stored->read_io16w(addr, &wait);
+}
+
+bool I86::write_debug_reg(const _TCHAR *reg, uint32_t data)
+{
+ if(_tcsicmp(reg, _T("IP")) == 0) {
+ pc = ((data & 0xffff) + base[CS]) & AMASK;
+ } else if(_tcsicmp(reg, _T("AX")) == 0) {
+ regs.w[AX] = data;
+ } else if(_tcsicmp(reg, _T("BX")) == 0) {
+ regs.w[BX] = data;
+ } else if(_tcsicmp(reg, _T("CX")) == 0) {
+ regs.w[CX] = data;
+ } else if(_tcsicmp(reg, _T("DX")) == 0) {
+ regs.w[DX] = data;
+ } else if(_tcsicmp(reg, _T("SP")) == 0) {
+ regs.w[SP] = data;
+ } else if(_tcsicmp(reg, _T("BP")) == 0) {
+ regs.w[BP] = data;
+ } else if(_tcsicmp(reg, _T("SI")) == 0) {
+ regs.w[SI] = data;
+ } else if(_tcsicmp(reg, _T("DI")) == 0) {
+ regs.w[DI] = data;
+ } else if(_tcsicmp(reg, _T("AL")) == 0) {
+ regs.b[AL] = data;
+ } else if(_tcsicmp(reg, _T("AH")) == 0) {
+ regs.b[AH] = data;
+ } else if(_tcsicmp(reg, _T("BL")) == 0) {
+ regs.b[BL] = data;
+ } else if(_tcsicmp(reg, _T("BH")) == 0) {
+ regs.b[BH] = data;
+ } else if(_tcsicmp(reg, _T("CL")) == 0) {
+ regs.b[CL] = data;
+ } else if(_tcsicmp(reg, _T("CH")) == 0) {
+ regs.b[CH] = data;
+ } else if(_tcsicmp(reg, _T("DL")) == 0) {
+ regs.b[DL] = data;
+ } else if(_tcsicmp(reg, _T("DH")) == 0) {
+ regs.b[DH] = data;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void I86::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
+{
+ my_stprintf_s(buffer, buffer_len,
+ _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]"),
+ regs.w[AX], regs.w[BX], regs.w[CX], regs.w[DX], regs.w[SP], regs.w[BP], regs.w[SI], regs.w[DI], sregs[DS], sregs[ES], sregs[SS], sregs[CS], (uint16_t)(pc - base[CS]),
+ OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), IF ? _T('I') : _T('-'), TF ? _T('T') : _T('-'),
+ SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'));
+}
+
+int I86::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
+{
+ UINT32 eip = (UINT32)(uint16_t)(pc - base[CS]);
+ UINT8 ops[16];
+ for(int i = 0; i < 16; i++) {
+ int wait;
+ ops[i] = d_mem->read_data8w(pc + i, &wait);
+ }
+ return necv_dasm_one(buffer, eip, ops) & DASMFLAG_LENGTHMASK;
+}
+#endif
+
+void I86::interrupt(int int_num)
+{
+ unsigned dest_seg, dest_off;
+ uint16_t ip = pc - base[CS];
+
+ if(int_num == -1) {
+ int_num = d_pic->get_intr_ack() & 0xff;
+ int_state &= ~INT_REQ_BIT;
+ }
+ dest_off = ReadWord(int_num * 4);
+ dest_seg = ReadWord(int_num * 4 + 2);
+
+ _pushf();
+ TF = IF = 0;
+ PUSH(sregs[CS]);
+ PUSH(ip);
+ sregs[CS] = (uint16_t)dest_seg;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + dest_off) & AMASK;
+ icount -= timing.exception;
+}
+
+void I86::trap()
+{
+ instruction(FETCHOP);
+ interrupt(1);
+}
+
+unsigned I86::GetEA(unsigned ModRM)
+{
+ switch(ModRM) {
+ case 0x00: case 0x08: case 0x10: case 0x18: case 0x20: case 0x28: case 0x30: case 0x38:
+ icount -= 7; eo = (uint16_t)(regs.w[BX] + regs.w[SI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x01: case 0x09: case 0x11: case 0x19: case 0x21: case 0x29: case 0x31: case 0x39:
+ icount -= 8; eo = (uint16_t)(regs.w[BX] + regs.w[DI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x02: case 0x0a: case 0x12: case 0x1a: case 0x22: case 0x2a: case 0x32: case 0x3a:
+ icount -= 8; eo = (uint16_t)(regs.w[BP] + regs.w[SI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x03: case 0x0b: case 0x13: case 0x1b: case 0x23: case 0x2b: case 0x33: case 0x3b:
+ icount -= 7; eo = (uint16_t)(regs.w[BP] + regs.w[DI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x04: case 0x0c: case 0x14: case 0x1c: case 0x24: case 0x2c: case 0x34: case 0x3c:
+ icount -= 5; eo = regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x05: case 0x0d: case 0x15: case 0x1d: case 0x25: case 0x2d: case 0x35: case 0x3d:
+ icount -= 5; eo = regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x06: case 0x0e: case 0x16: case 0x1e: case 0x26: case 0x2e: case 0x36: case 0x3e:
+ icount -= 6; eo = FETCHOP; eo += FETCHOP << 8; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x07: case 0x0f: case 0x17: case 0x1f: case 0x27: case 0x2f: case 0x37: case 0x3f:
+ icount -= 5; eo = regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+
+ case 0x40: case 0x48: case 0x50: case 0x58: case 0x60: case 0x68: case 0x70: case 0x78:
+ icount -= 11; eo = (uint16_t)(regs.w[BX] + regs.w[SI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x41: case 0x49: case 0x51: case 0x59: case 0x61: case 0x69: case 0x71: case 0x79:
+ icount -= 12; eo = (uint16_t)(regs.w[BX] + regs.w[DI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x42: case 0x4a: case 0x52: case 0x5a: case 0x62: case 0x6a: case 0x72: case 0x7a:
+ icount -= 12; eo = (uint16_t)(regs.w[BP] + regs.w[SI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x43: case 0x4b: case 0x53: case 0x5b: case 0x63: case 0x6b: case 0x73: case 0x7b:
+ icount -= 11; eo = (uint16_t)(regs.w[BP] + regs.w[DI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x44: case 0x4c: case 0x54: case 0x5c: case 0x64: case 0x6c: case 0x74: case 0x7c:
+ icount -= 9; eo = (uint16_t)(regs.w[SI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x45: case 0x4d: case 0x55: case 0x5d: case 0x65: case 0x6d: case 0x75: case 0x7d:
+ icount -= 9; eo = (uint16_t)(regs.w[DI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x46: case 0x4e: case 0x56: case 0x5e: case 0x66: case 0x6e: case 0x76: case 0x7e:
+ icount -= 9; eo = (uint16_t)(regs.w[BP] + (int8_t)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x47: case 0x4f: case 0x57: case 0x5f: case 0x67: case 0x6f: case 0x77: case 0x7f:
+ icount -= 9; eo = (uint16_t)(regs.w[BX] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+
+ case 0x80: case 0x88: case 0x90: case 0x98: case 0xa0: case 0xa8: case 0xb0: case 0xb8:
+ icount -= 11; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX] + regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x81: case 0x89: case 0x91: case 0x99: case 0xa1: case 0xa9: case 0xb1: case 0xb9:
+ icount -= 12; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX] + regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x82: case 0x8a: case 0x92: case 0x9a: case 0xa2: case 0xaa: case 0xb2: case 0xba:
+ icount -= 12; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP] + regs.w[SI]; ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + (uint16_t)eo; return ea;
+ case 0x83: case 0x8b: case 0x93: case 0x9b: case 0xa3: case 0xab: case 0xb3: case 0xbb:
+ icount -= 11; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP] + regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(SS) + (uint16_t)eo; return ea;
+ case 0x84: case 0x8c: case 0x94: case 0x9c: case 0xa4: case 0xac: case 0xb4: case 0xbc:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x85: case 0x8d: case 0x95: case 0x9d: case 0xa5: case 0xad: case 0xb5: case 0xbd:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x86: case 0x8e: case 0x96: case 0x9e: case 0xa6: case 0xae: case 0xb6: case 0xbe:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP]; ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + (uint16_t)eo; return ea;
+ case 0x87: case 0x8f: case 0x97: case 0x9f: case 0xa7: case 0xaf: case 0xb7: case 0xbf:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ }
+ return 0;
+}
+
+void I86::rotate_shift_byte(unsigned ModRM, unsigned count)
+{
+ unsigned src = (unsigned)GetRMByte(ModRM);
+ unsigned dst = src;
+
+ if(count == 0) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;
+ } else if(count == 1) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL eb, 1 */
+ CarryVal = src & 0x80;
+ dst = (src << 1) + CF;
+ PutbackRMByte(ModRM, dst);
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 1: /* ROR eb, 1 */
+ CarryVal = src & 0x01;
+ dst = ((CF << 8) + src) >> 1;
+ PutbackRMByte(ModRM, dst);
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 2: /* RCL eb, 1 */
+ dst = (src << 1) + CF;
+ PutbackRMByte(ModRM, dst);
+ SetCFB(dst);
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 3: /* RCR eb, 1 */
+ dst = ((CF << 8) + src) >> 1;
+ PutbackRMByte(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 4: /* SHL eb, 1 */
+ case 6:
+ dst = src << 1;
+ PutbackRMByte(ModRM, dst);
+ SetCFB(dst);
+ OverVal = (src ^ dst) & 0x80;
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 5: /* SHR eb, 1 */
+ dst = src >> 1;
+ PutbackRMByte(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = src & 0x80;
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 7: /* SAR eb, 1 */
+ dst = ((int8_t)src) >> 1;
+ PutbackRMByte(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = 0;
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ } else {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m8_bit;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL eb, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x80;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 1: /* ROR eb, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 7);
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 2: /* RCL eb, count */
+ for(; count > 0; count--) {
+ dst = (dst << 1) + CF;
+ SetCFB(dst);
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 3: /* RCR eb, count */
+ for(; count > 0; count--) {
+ dst = (CF << 8) + dst;
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 4: /* SHL eb, count */
+ case 6:
+ dst <<= count;
+ SetCFB(dst);
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 5: /* SHR eb, count */
+ dst >>= count - 1;
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ SetSZPF_Byte(dst);
+ AuxVal = 1;
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 7: /* SAR eb, count */
+ dst = ((int8_t)dst) >> (count - 1);
+ CarryVal = dst & 0x01;
+ dst = ((int8_t)((uint8_t)dst)) >> 1;
+ SetSZPF_Byte(dst);
+ AuxVal = 1;
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ }
+}
+
+void I86::rotate_shift_word(unsigned ModRM, unsigned count)
+{
+ unsigned src = GetRMWord(ModRM);
+ unsigned dst = src;
+
+ if(count == 0) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;
+ } else if(count == 1) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL ew, 1 */
+ CarryVal = src & 0x8000;
+ dst = (src << 1) + CF;
+ PutbackRMWord(ModRM, dst);
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 1: /* ROR ew, 1 */
+ CarryVal = src & 0x01;
+ dst = ((CF << 16) + src) >> 1;
+ PutbackRMWord(ModRM, dst);
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 2: /* RCL ew, 1 */
+ dst = (src << 1) + CF;
+ PutbackRMWord(ModRM, dst);
+ SetCFW(dst);
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 3: /* RCR ew, 1 */
+ dst = ((CF << 16) + src) >> 1;
+ PutbackRMWord(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 4: /* SHL ew, 1 */
+ case 6:
+ dst = src << 1;
+ PutbackRMWord(ModRM, dst);
+ SetCFW(dst);
+ OverVal = (src ^ dst) & 0x8000;
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 5: /* SHR ew, 1 */
+ dst = src >> 1;
+ PutbackRMWord(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = src & 0x8000;
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 7: /* SAR ew, 1 */
+ dst = ((int16_t)src) >> 1;
+ PutbackRMWord(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = 0;
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ } else {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m16_bit;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL ew, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x8000;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 1: /* ROR ew, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 15);
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 2: /* RCL ew, count */
+ for(; count > 0; count--) {
+ dst = (dst << 1) + CF;
+ SetCFW(dst);
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 3: /* RCR ew, count */
+ for(; count > 0; count--) {
+ dst = dst + (CF << 16);
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 4: /* SHL ew, count */
+ case 6:
+ dst <<= count;
+ SetCFW(dst);
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 5: /* SHR ew, count */
+ dst >>= count - 1;
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ SetSZPF_Word(dst);
+ AuxVal = 1;
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 7: /* SAR ew, count */
+ dst = ((int16_t)dst) >> (count - 1);
+ CarryVal = dst & 0x01;
+ dst = ((int16_t)((uint16_t)dst)) >> 1;
+ SetSZPF_Word(dst);
+ AuxVal = 1;
+ PutbackRMWord(ModRM, dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ }
+}
+
+void I86::instruction(uint8_t code)
+{
+ prevpc = pc - 1;
+
+ switch(code) {
+ case 0x00: _add_br8(); break;
+ case 0x01: _add_wr16(); break;
+ case 0x02: _add_r8b(); break;
+ case 0x03: _add_r16w(); break;
+ case 0x04: _add_ald8(); break;
+ case 0x05: _add_axd16(); break;
+ case 0x06: _push_es(); break;
+ case 0x07: _pop_es(); break;
+ case 0x08: _or_br8(); break;
+ case 0x09: _or_wr16(); break;
+ case 0x0a: _or_r8b(); break;
+ case 0x0b: _or_r16w(); break;
+ case 0x0c: _or_ald8(); break;
+ case 0x0d: _or_axd16(); break;
+ case 0x0e: _push_cs(); break;
+#if defined(HAS_V30)
+ case 0x0f: _0fpre(); break;
+#else
+ case 0x0f: _invalid(); break;
+#endif
+ case 0x10: _adc_br8(); break;
+ case 0x11: _adc_wr16(); break;
+ case 0x12: _adc_r8b(); break;
+ case 0x13: _adc_r16w(); break;
+ case 0x14: _adc_ald8(); break;
+ case 0x15: _adc_axd16(); break;
+ case 0x16: _push_ss(); break;
+ case 0x17: _pop_ss(); break;
+ case 0x18: _sbb_br8(); break;
+ case 0x19: _sbb_wr16(); break;
+ case 0x1a: _sbb_r8b(); break;
+ case 0x1b: _sbb_r16w(); break;
+ case 0x1c: _sbb_ald8(); break;
+ case 0x1d: _sbb_axd16(); break;
+ case 0x1e: _push_ds(); break;
+ case 0x1f: _pop_ds(); break;
+ case 0x20: _and_br8(); break;
+ case 0x21: _and_wr16(); break;
+ case 0x22: _and_r8b(); break;
+ case 0x23: _and_r16w(); break;
+ case 0x24: _and_ald8(); break;
+ case 0x25: _and_axd16(); break;
+ case 0x26: _es(); break;
+ case 0x27: _daa(); break;
+ case 0x28: _sub_br8(); break;
+ case 0x29: _sub_wr16(); break;
+ case 0x2a: _sub_r8b(); break;
+ case 0x2b: _sub_r16w(); break;
+ case 0x2c: _sub_ald8(); break;
+ case 0x2d: _sub_axd16(); break;
+ case 0x2e: _cs(); break;
+ case 0x2f: _das(); break;
+ case 0x30: _xor_br8(); break;
+ case 0x31: _xor_wr16(); break;
+ case 0x32: _xor_r8b(); break;
+ case 0x33: _xor_r16w(); break;
+ case 0x34: _xor_ald8(); break;
+ case 0x35: _xor_axd16(); break;
+ case 0x36: _ss(); break;
+ case 0x37: _aaa(); break;
+ case 0x38: _cmp_br8(); break;
+ case 0x39: _cmp_wr16(); break;
+ case 0x3a: _cmp_r8b(); break;
+ case 0x3b: _cmp_r16w(); break;
+ case 0x3c: _cmp_ald8(); break;
+ case 0x3d: _cmp_axd16(); break;
+ case 0x3e: _ds(); break;
+ case 0x3f: _aas(); break;
+ case 0x40: _inc_ax(); break;
+ case 0x41: _inc_cx(); break;
+ case 0x42: _inc_dx(); break;
+ case 0x43: _inc_bx(); break;
+ case 0x44: _inc_sp(); break;
+ case 0x45: _inc_bp(); break;
+ case 0x46: _inc_si(); break;
+ case 0x47: _inc_di(); break;
+ case 0x48: _dec_ax(); break;
+ case 0x49: _dec_cx(); break;
+ case 0x4a: _dec_dx(); break;
+ case 0x4b: _dec_bx(); break;
+ case 0x4c: _dec_sp(); break;
+ case 0x4d: _dec_bp(); break;
+ case 0x4e: _dec_si(); break;
+ case 0x4f: _dec_di(); break;
+ case 0x50: _push_ax(); break;
+ case 0x51: _push_cx(); break;
+ case 0x52: _push_dx(); break;
+ case 0x53: _push_bx(); break;
+ case 0x54: _push_sp(); break;
+ case 0x55: _push_bp(); break;
+ case 0x56: _push_si(); break;
+ case 0x57: _push_di(); break;
+ case 0x58: _pop_ax(); break;
+ case 0x59: _pop_cx(); break;
+ case 0x5a: _pop_dx(); break;
+ case 0x5b: _pop_bx(); break;
+ case 0x5c: _pop_sp(); break;
+ case 0x5d: _pop_bp(); break;
+ case 0x5e: _pop_si(); break;
+ case 0x5f: _pop_di(); break;
+#if defined(HAS_V30)
+ case 0x60: _pusha(); break;
+ case 0x61: _popa(); break;
+ case 0x62: _bound(); break;
+#else
+ case 0x60: _invalid(); break;
+ case 0x61: _invalid(); break;
+ case 0x62: _invalid(); break;
+#endif
+ case 0x63: _invalid(); break;
+#if defined(HAS_V30)
+ case 0x64: _repc(0); break;
+ case 0x65: _repc(1); break;
+#else
+ case 0x64: _invalid(); break;
+ case 0x65: _invalid(); break;
+#endif
+ case 0x66: _invalid(); break;
+ case 0x67: _invalid(); break;
+#if defined(HAS_V30)
+ case 0x68: _push_d16(); break;
+ case 0x69: _imul_d16(); break;
+ case 0x6a: _push_d8(); break;
+ case 0x6b: _imul_d8(); break;
+ case 0x6c: _insb(); break;
+ case 0x6d: _insw(); break;
+ case 0x6e: _outsb(); break;
+ case 0x6f: _outsw(); break;
+#else
+ case 0x68: _invalid(); break;
+ case 0x69: _invalid(); break;
+ case 0x6a: _invalid(); break;
+ case 0x6b: _invalid(); break;
+ case 0x6c: _invalid(); break;
+ case 0x6d: _invalid(); break;
+ case 0x6e: _invalid(); break;
+ case 0x6f: _invalid(); break;
+#endif
+ case 0x70: _jo(); break;
+ case 0x71: _jno(); break;
+ case 0x72: _jb(); break;
+ case 0x73: _jnb(); break;
+ case 0x74: _jz(); break;
+ case 0x75: _jnz(); break;
+ case 0x76: _jbe(); break;
+ case 0x77: _jnbe(); break;
+ case 0x78: _js(); break;
+ case 0x79: _jns(); break;
+ case 0x7a: _jp(); break;
+ case 0x7b: _jnp(); break;
+ case 0x7c: _jl(); break;
+ case 0x7d: _jnl(); break;
+ case 0x7e: _jle(); break;
+ case 0x7f: _jnle(); break;
+ case 0x80: _80pre(); break;
+ case 0x81: _81pre(); break;
+ case 0x82: _82pre(); break;
+ case 0x83: _83pre(); break;
+ case 0x84: _test_br8(); break;
+ case 0x85: _test_wr16(); break;
+ case 0x86: _xchg_br8(); break;
+ case 0x87: _xchg_wr16(); break;
+ case 0x88: _mov_br8(); break;
+ case 0x89: _mov_wr16(); break;
+ case 0x8a: _mov_r8b(); break;
+ case 0x8b: _mov_r16w(); break;
+ case 0x8c: _mov_wsreg(); break;
+ case 0x8d: _lea(); break;
+ case 0x8e: _mov_sregw(); break;
+ case 0x8f: _popw(); break;
+ case 0x90: _nop(); break;
+ case 0x91: _xchg_axcx(); break;
+ case 0x92: _xchg_axdx(); break;
+ case 0x93: _xchg_axbx(); break;
+ case 0x94: _xchg_axsp(); break;
+ case 0x95: _xchg_axbp(); break;
+ case 0x96: _xchg_axsi(); break;
+ case 0x97: _xchg_axdi(); break;
+ case 0x98: _cbw(); break;
+ case 0x99: _cwd(); break;
+ case 0x9a: _call_far(); break;
+ case 0x9b: _wait(); break;
+ case 0x9c: _pushf(); break;
+ case 0x9d: _popf(); break;
+ case 0x9e: _sahf(); break;
+ case 0x9f: _lahf(); break;
+ case 0xa0: _mov_aldisp(); break;
+ case 0xa1: _mov_axdisp(); break;
+ case 0xa2: _mov_dispal(); break;
+ case 0xa3: _mov_dispax(); break;
+ case 0xa4: _movsb(); break;
+ case 0xa5: _movsw(); break;
+ case 0xa6: _cmpsb(); break;
+ case 0xa7: _cmpsw(); break;
+ case 0xa8: _test_ald8(); break;
+ case 0xa9: _test_axd16(); break;
+ case 0xaa: _stosb(); break;
+ case 0xab: _stosw(); break;
+ case 0xac: _lodsb(); break;
+ case 0xad: _lodsw(); break;
+ case 0xae: _scasb(); break;
+ case 0xaf: _scasw(); break;
+ case 0xb0: _mov_ald8(); break;
+ case 0xb1: _mov_cld8(); break;
+ case 0xb2: _mov_dld8(); break;
+ case 0xb3: _mov_bld8(); break;
+ case 0xb4: _mov_ahd8(); break;
+ case 0xb5: _mov_chd8(); break;
+ case 0xb6: _mov_dhd8(); break;
+ case 0xb7: _mov_bhd8(); break;
+ case 0xb8: _mov_axd16(); break;
+ case 0xb9: _mov_cxd16(); break;
+ case 0xba: _mov_dxd16(); break;
+ case 0xbb: _mov_bxd16(); break;
+ case 0xbc: _mov_spd16(); break;
+ case 0xbd: _mov_bpd16(); break;
+ case 0xbe: _mov_sid16(); break;
+ case 0xbf: _mov_did16(); break;
+#if defined(HAS_V30)
+ case 0xc0: _rotshft_bd8(); break;
+ case 0xc1: _rotshft_wd8(); break;
+#else
+ case 0xc0: _invalid(); break;
+ case 0xc1: _invalid(); break;
+#endif
+ case 0xc2: _ret_d16(); break;
+ case 0xc3: _ret(); break;
+ case 0xc4: _les_dw(); break;
+ case 0xc5: _lds_dw(); break;
+ case 0xc6: _mov_bd8(); break;
+ case 0xc7: _mov_wd16(); break;
+#if defined(HAS_V30)
+ case 0xc8: _enter(); break;
+ case 0xc9: _leav(); break; /* _leave() */
+#else
+ case 0xc8: _invalid(); break;
+ case 0xc9: _invalid(); break;
+#endif
+ case 0xca: _retf_d16(); break;
+ case 0xcb: _retf(); break;
+ case 0xcc: _int3(); break;
+ case 0xcd: _int(); break;
+ case 0xce: _into(); break;
+ case 0xcf: _iret(); break;
+ case 0xd0: _rotshft_b(); break;
+ case 0xd1: _rotshft_w(); break;
+ case 0xd2: _rotshft_bcl(); break;
+ case 0xd3: _rotshft_wcl(); break;
+ case 0xd4: _aam(); break;
+ case 0xd5: _aad(); break;
+#if defined(HAS_V30)
+ case 0xd6: _setalc(); break;
+#else
+ case 0xd6: _invalid(); break;
+#endif
+ case 0xd7: _xlat(); break;
+ case 0xd8: _escape(); break;
+ case 0xd9: _escape(); break;
+ case 0xda: _escape(); break;
+ case 0xdb: _escape(); break;
+ case 0xdc: _escape(); break;
+ case 0xdd: _escape(); break;
+ case 0xde: _escape(); break;
+ case 0xdf: _escape(); break;
+ case 0xe0: _loopne(); break;
+ case 0xe1: _loope(); break;
+ case 0xe2: _loop(); break;
+ case 0xe3: _jcxz(); break;
+ case 0xe4: _inal(); break;
+ case 0xe5: _inax(); break;
+ case 0xe6: _outal(); break;
+ case 0xe7: _outax(); break;
+ case 0xe8: _call_d16(); break;
+ case 0xe9: _jmp_d16(); break;
+ case 0xea: _jmp_far(); break;
+ case 0xeb: _jmp_d8(); break;
+ case 0xec: _inaldx(); break;
+ case 0xed: _inaxdx(); break;
+ case 0xee: _outdxal(); break;
+ case 0xef: _outdxax(); break;
+ case 0xf0: _lock(); break;
+ case 0xf1: _invalid(); break;
+ case 0xf2: _repne(); break;
+ case 0xf3: _repe(); break;
+ case 0xf4: _hlt(); break;
+ case 0xf5: _cmc(); break;
+ case 0xf6: _f6pre(); break;
+ case 0xf7: _f7pre(); break;
+ case 0xf8: _clc(); break;
+ case 0xf9: _stc(); break;
+ case 0xfa: _cli(); break;
+ case 0xfb: _sti(); break;
+ case 0xfc: _cld(); break;
+ case 0xfd: _std(); break;
+ case 0xfe: _fepre(); break;
+ case 0xff: _ffpre(); break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default: __assume(0);
+#endif
+ }
+}
+
+inline void I86::_add_br8() /* Opcode 0x00 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_add_wr16() /* Opcode 0x01 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_add_r8b() /* Opcode 0x02 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ADDB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_add_r16w() /* Opcode 0x03 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ADDW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_add_ald8() /* Opcode 0x04 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ADDB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_add_axd16() /* Opcode 0x05 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ADDW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_es() /* Opcode 0x06 */
+{
+ icount -= timing.push_seg;
+ PUSH(sregs[ES]);
+}
+
+inline void I86::_pop_es() /* Opcode 0x07 */
+{
+ POP(sregs[ES]);
+ base[ES] = SegBase(ES);
+ icount -= timing.pop_seg;
+}
+
+inline void I86::_or_br8() /* Opcode 0x08 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_or_wr16() /* Opcode 0x09 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_or_r8b() /* Opcode 0x0a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ORB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_or_r16w() /* Opcode 0x0b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ORW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_or_ald8() /* Opcode 0x0c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ORB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_or_axd16() /* Opcode 0x0d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ORW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_cs() /* Opcode 0x0e */
+{
+ icount -= timing.push_seg;
+ PUSH(sregs[CS]);
+}
+
+#if defined(HAS_V30)
+inline void I86::_0fpre() /* Opcode 0x0f */
+{
+ static const uint16_t bytes[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
+ };
+ unsigned code = FETCH;
+ unsigned ModRM;
+ unsigned tmp;
+ unsigned tmp2;
+
+ switch(code) {
+ case 0x10: /* 0F 10 47 30 - TEST1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 3;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 12;
+ }
+ tmp2 = regs.b[CL] & 7;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x11: /* 0F 11 47 30 - TEST1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 3;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 12;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x12: /* 0F 12 [mod:000:r/m] - CLR1 reg/m8, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 14;
+ }
+ tmp2 = regs.b[CL] & 7;
+ tmp &= ~bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x13: /* 0F 13 [mod:000:r/m] - CLR1 reg/m16, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 14;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ tmp &= ~bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x14: /* 0F 14 47 30 - SET1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 13;
+ }
+ tmp2 = regs.b[CL] & 7;
+ tmp |= bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x15: /* 0F 15 C6 - SET1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 13;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ tmp |= bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x16: /* 0F 16 C6 - NOT1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 18;
+ }
+ tmp2 = regs.b[CL] & 7;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x17: /* 0F 17 C6 - NOT1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 18;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x18: /* 0F 18 XX - TEST1 [bx+30h], 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 13;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x19: /* 0F 19 XX - TEST1 [bx+30h], 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 13;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x1a: /* 0F 1A 06 - CLR1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 6;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 15;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 7;
+ tmp &= ~bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x1B: /* 0F 1B 06 - CLR1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 6;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 15;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ tmp &= ~bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x1C: /* 0F 1C 47 30 - SET1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 14;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 7;
+ tmp |= bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x1D: /* 0F 1D C6 - SET1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 14;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ tmp |= bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x1e: /* 0F 1e C6 - NOT1 si, 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 19;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 7;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x1f: /* 0F 1f C6 - NOT1 si, 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 19;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x20: /* 0F 20 59 - add4s */
+ {
+ /* length in words ! */
+ int count = (regs.b[CL] + 1) / 2;
+ unsigned di = regs.w[DI];
+ unsigned si = regs.w[SI];
+
+ ZeroVal = 1;
+ CarryVal = 0; /* NOT ADC */
+ for(int i = 0; i < count; i++) {
+ 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 + CarryVal;
+ CarryVal = result > 99 ? 1 : 0;
+ result = result % 100;
+ v1 = ((result / 10) << 4) | (result % 10);
+ PutMemB(ES, di, v1);
+ if(v1) {
+ ZeroVal = 0;
+ }
+ si++;
+ di++;
+ }
+ OverVal = CarryVal;
+ icount -= 7 + 19 * count;
+ }
+ break;
+ case 0x22: /* 0F 22 59 - sub4s */
+ {
+ int count = (regs.b[CL] + 1) / 2;
+ unsigned di = regs.w[DI];
+ unsigned si = regs.w[SI];
+
+ ZeroVal = 1;
+ CarryVal = 0; /* NOT ADC */
+ for(int i = 0; i < count; i++) {
+ tmp = GetMemB(ES, di);
+ tmp2 = GetMemB(DS, si);
+ int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
+ int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
+ if(v1 < (v2 + CarryVal)) {
+ v1 += 100;
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 1;
+ } else {
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 0;
+ }
+ v1 = ((result / 10) << 4) | (result % 10);
+ PutMemB(ES, di, v1);
+ if(v1) {
+ ZeroVal = 0;
+ }
+ si++;
+ di++;
+ }
+ OverVal = CarryVal;
+ icount -= 7 + 19 * count;
+ }
+ break;
+ case 0x25:
+ icount -= 16;
+ break;
+ case 0x26: /* 0F 22 59 - cmp4s */
+ {
+ int count = (regs.b[CL] + 1) / 2;
+ unsigned di = regs.w[DI];
+ unsigned si = regs.w[SI];
+
+ ZeroVal = 1;
+ CarryVal = 0; /* NOT ADC */
+ for(int i = 0; i < count; i++) {
+ tmp = GetMemB(ES, di);
+ tmp2 = GetMemB(DS, si);
+ int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
+ int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
+ if(v1 < (v2 + CarryVal)) {
+ v1 += 100;
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 1;
+ } else {
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 0;
+ }
+ v1 = ((result / 10) << 4) | (result % 10);
+ /* PutMemB(ES, di, v1); /* no store, only compare */
+ if(v1) {
+ ZeroVal = 0;
+ }
+ si++;
+ di++;
+ }
+ OverVal = CarryVal;
+ icount -= 7 + 19 * (regs.b[CL] + 1);
+ }
+ break;
+ case 0x28: /* 0F 28 C7 - ROL4 bh */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 25;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 28;
+ }
+ tmp <<= 4;
+ tmp |= regs.b[AL] & 0xf;
+ regs.b[AL] = (regs.b[AL] & 0xf0) | ((tmp >> 8) & 0xf);
+ tmp &= 0xff;
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x29: /* 0F 29 C7 - ROL4 bx */
+ ModRM = FETCH;
+ break;
+ case 0x2A: /* 0F 2a c2 - ROR4 bh */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 29;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 33;
+ }
+ tmp2 = (regs.b[AL] & 0xf) << 4;
+ regs.b[AL] = (regs.b[AL] & 0xf0) | (tmp & 0xf);
+ tmp = tmp2 | (tmp >> 4);
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x2B: /* 0F 2b c2 - ROR4 bx */
+ ModRM = FETCH;
+ break;
+ case 0x2D: /* 0Fh 2Dh < 1111 1RRR> */
+ ModRM = FETCH;
+ icount -= 15;
+ break;
+ case 0x31: /* 0F 31 [mod:reg:r/m] - INS reg8, reg8 or INS reg8, imm4 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 29;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 33;
+ }
+ break;
+ case 0x33: /* 0F 33 [mod:reg:r/m] - EXT reg8, reg8 or EXT reg8, imm4 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 29;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 33;
+ }
+ break;
+ case 0x91:
+ icount -= 12;
+ break;
+ case 0x94:
+ ModRM = FETCH;
+ icount -= 11;
+ break;
+ case 0x95:
+ ModRM = FETCH;
+ icount -= 11;
+ break;
+ case 0xbe:
+ icount -= 2;
+ break;
+ case 0xe0:
+ ModRM = FETCH;
+ icount -= 12;
+ break;
+ case 0xf0:
+ ModRM = FETCH;
+ icount -= 12;
+ break;
+ case 0xff: /* 0F ff imm8 - BRKEM */
+ ModRM = FETCH;
+ icount -= 38;
+ interrupt(ModRM);
+ break;
+ }
+}
+#endif
+
+inline void I86::_adc_br8() /* Opcode 0x10 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src += CF;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_adc_wr16() /* Opcode 0x11 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src += CF;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_adc_r8b() /* Opcode 0x12 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src += CF;
+ ADDB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_adc_r16w() /* Opcode 0x13 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src += CF;
+ ADDW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_adc_ald8() /* Opcode 0x14 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ src += CF;
+ ADDB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_adc_axd16() /* Opcode 0x15 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ src += CF;
+ ADDW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_ss() /* Opcode 0x16 */
+{
+ PUSH(sregs[SS]);
+ icount -= timing.push_seg;
+}
+
+inline void I86::_pop_ss() /* Opcode 0x17 */
+{
+ POP(sregs[SS]);
+ base[SS] = SegBase(SS);
+ icount -= timing.pop_seg;
+ instruction(FETCHOP); /* no interrupt before next instruction */
+}
+
+inline void I86::_sbb_br8() /* Opcode 0x18 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src += CF;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_sbb_wr16() /* Opcode 0x19 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src += CF;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_sbb_r8b() /* Opcode 0x1a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src += CF;
+ SUBB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_sbb_r16w() /* Opcode 0x1b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src += CF;
+ SUBW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_sbb_ald8() /* Opcode 0x1c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ src += CF;
+ SUBB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_sbb_axd16() /* Opcode 0x1d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ src += CF;
+ SUBW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_ds() /* Opcode 0x1e */
+{
+ PUSH(sregs[DS]);
+ icount -= timing.push_seg;
+}
+
+inline void I86::_pop_ds() /* Opcode 0x1f */
+{
+ POP(sregs[DS]);
+ base[DS] = SegBase(DS);
+ icount -= timing.push_seg;
+}
+
+inline void I86::_and_br8() /* Opcode 0x20 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ANDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_and_wr16() /* Opcode 0x21 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ANDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_and_r8b() /* Opcode 0x22 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_and_r16w() /* Opcode 0x23 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_and_ald8() /* Opcode 0x24 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ANDB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_and_axd16() /* Opcode 0x25 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ANDW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_es() /* Opcode 0x26 */
+{
+ seg_prefix = true;
+ prefix_seg = ES;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_daa() /* Opcode 0x27 */
+{
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ int tmp;
+ regs.b[AL] = tmp = regs.b[AL] + 6;
+ AuxVal = 1;
+ CarryVal |= tmp & 0x100;
+ }
+
+ if(CF || (regs.b[AL] > 0x9f)) {
+ regs.b[AL] += 0x60;
+ CarryVal = 1;
+ }
+
+ SetSZPF_Byte(regs.b[AL]);
+ icount -= timing.daa;
+}
+
+inline void I86::_sub_br8() /* Opcode 0x28 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_sub_wr16() /* Opcode 0x29 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_sub_r8b() /* Opcode 0x2a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_sub_r16w() /* Opcode 0x2b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_sub_ald8() /* Opcode 0x2c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ SUBB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_sub_axd16() /* Opcode 0x2d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ SUBW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_cs() /* Opcode 0x2e */
+{
+ seg_prefix = true;
+ prefix_seg = CS;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_das() /* Opcode 0x2f */
+{
+ uint8_t tmpAL = regs.b[AL];
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ int tmp;
+ regs.b[AL] = tmp = regs.b[AL] - 6;
+ AuxVal = 1;
+ CarryVal |= tmp & 0x100;
+ }
+
+ if(CF || (tmpAL > 0x9f)) {
+ regs.b[AL] -= 0x60;
+ CarryVal = 1;
+ }
+
+ SetSZPF_Byte(regs.b[AL]);
+ icount -= timing.das;
+}
+
+inline void I86::_xor_br8() /* Opcode 0x30 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ XORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_xor_wr16() /* Opcode 0x31 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ XORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_xor_r8b() /* Opcode 0x32 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ XORB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_xor_r16w() /* Opcode 0x33 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ XORW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_xor_ald8() /* Opcode 0x34 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ XORB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_xor_axd16() /* Opcode 0x35 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ XORW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_ss() /* Opcode 0x36 */
+{
+ seg_prefix = true;
+ prefix_seg = SS;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_aaa() /* Opcode 0x37 */
+{
+ uint8_t ALcarry = 1;
+ if(regs.b[AL]>0xf9) {
+ ALcarry = 2;
+ }
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ regs.b[AL] += 6;
+ regs.b[AH] += ALcarry;
+ AuxVal = 1;
+ CarryVal = 1;
+ } else {
+ AuxVal = 0;
+ CarryVal = 0;
+ }
+ regs.b[AL] &= 0x0F;
+ icount -= timing.aaa;
+}
+
+inline void I86::_cmp_br8() /* Opcode 0x38 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst, src);
+}
+
+inline void I86::_cmp_wr16() /* Opcode 0x39 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst, src);
+}
+
+inline void I86::_cmp_r8b() /* Opcode 0x3a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst, src);
+}
+
+inline void I86::_cmp_r16w() /* Opcode 0x3b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst, src);
+}
+
+inline void I86::_cmp_ald8() /* Opcode 0x3c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ SUBB(dst, src);
+}
+
+inline void I86::_cmp_axd16() /* Opcode 0x3d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ SUBW(dst, src);
+}
+
+inline void I86::_ds() /* Opcode 0x3e */
+{
+ seg_prefix = true;
+ prefix_seg = DS;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_aas() /* Opcode 0x3f */
+{
+ uint8_t ALcarry = 1;
+ if(regs.b[AL] > 0xf9) {
+ ALcarry = 2;
+ }
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ regs.b[AL] -= 6;
+ regs.b[AH] -= 1;
+ AuxVal = 1;
+ CarryVal = 1;
+ } else {
+ AuxVal = 0;
+ CarryVal = 0;
+ }
+ regs.b[AL] &= 0x0F;
+ icount -= timing.aas;
+}
+
+#define IncWordReg(Reg) { \
+ unsigned tmp = (unsigned)regs.w[Reg]; \
+ unsigned tmp1 = tmp + 1; \
+ SetOFW_Add(tmp1, tmp, 1); \
+ SetAF(tmp1, tmp, 1); \
+ SetSZPF_Word(tmp1); \
+ regs.w[Reg] = tmp1; \
+ icount -= timing.incdec_r16; \
+}
+
+inline void I86::_inc_ax() /* Opcode 0x40 */
+{
+ IncWordReg(AX);
+}
+
+inline void I86::_inc_cx() /* Opcode 0x41 */
+{
+ IncWordReg(CX);
+}
+
+inline void I86::_inc_dx() /* Opcode 0x42 */
+{
+ IncWordReg(DX);
+}
+
+inline void I86::_inc_bx() /* Opcode 0x43 */
+{
+ IncWordReg(BX);
+}
+
+inline void I86::_inc_sp() /* Opcode 0x44 */
+{
+ IncWordReg(SP);
+}
+
+inline void I86::_inc_bp() /* Opcode 0x45 */
+{
+ IncWordReg(BP);
+}
+
+inline void I86::_inc_si() /* Opcode 0x46 */
+{
+ IncWordReg(SI);
+}
+
+inline void I86::_inc_di() /* Opcode 0x47 */
+{
+ IncWordReg(DI);
+}
+
+#define DecWordReg(Reg) { \
+ unsigned tmp = (unsigned)regs.w[Reg]; \
+ unsigned tmp1 = tmp - 1; \
+ SetOFW_Sub(tmp1, 1, tmp); \
+ SetAF(tmp1, tmp, 1); \
+ SetSZPF_Word(tmp1); \
+ regs.w[Reg] = tmp1; \
+ icount -= timing.incdec_r16; \
+}
+
+inline void I86::_dec_ax() /* Opcode 0x48 */
+{
+ DecWordReg(AX);
+}
+
+inline void I86::_dec_cx() /* Opcode 0x49 */
+{
+ DecWordReg(CX);
+}
+
+inline void I86::_dec_dx() /* Opcode 0x4a */
+{
+ DecWordReg(DX);
+}
+
+inline void I86::_dec_bx() /* Opcode 0x4b */
+{
+ DecWordReg(BX);
+}
+
+inline void I86::_dec_sp() /* Opcode 0x4c */
+{
+ DecWordReg(SP);
+}
+
+inline void I86::_dec_bp() /* Opcode 0x4d */
+{
+ DecWordReg(BP);
+}
+
+inline void I86::_dec_si() /* Opcode 0x4e */
+{
+ DecWordReg(SI);
+}
+
+inline void I86::_dec_di() /* Opcode 0x4f */
+{
+ DecWordReg(DI);
+}
+
+inline void I86::_push_ax() /* Opcode 0x50 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[AX]);
+}
+
+inline void I86::_push_cx() /* Opcode 0x51 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[CX]);
+}
+
+inline void I86::_push_dx() /* Opcode 0x52 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[DX]);
+}
+
+inline void I86::_push_bx() /* Opcode 0x53 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[BX]);
+}
+
+inline void I86::_push_sp() /* Opcode 0x54 */
+{
+ unsigned tmp = regs.w[SP];
+
+ icount -= timing.push_r16;
+ PUSH(tmp - 2);
+}
+
+inline void I86::_push_bp() /* Opcode 0x55 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[BP]);
+}
+
+inline void I86::_push_si() /* Opcode 0x56 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[SI]);
+}
+
+inline void I86::_push_di() /* Opcode 0x57 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[DI]);
+}
+
+inline void I86::_pop_ax() /* Opcode 0x58 */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[AX]);
+}
+
+inline void I86::_pop_cx() /* Opcode 0x59 */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[CX]);
+}
+
+inline void I86::_pop_dx() /* Opcode 0x5a */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[DX]);
+}
+
+inline void I86::_pop_bx() /* Opcode 0x5b */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[BX]);
+}
+
+inline void I86::_pop_sp() /* Opcode 0x5c */
+{
+ unsigned tmp;
+
+ icount -= timing.pop_r16;
+ POP(tmp);
+ regs.w[SP] = tmp;
+}
+
+inline void I86::_pop_bp() /* Opcode 0x5d */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[BP]);
+}
+
+inline void I86::_pop_si() /* Opcode 0x5e */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[SI]);
+}
+
+inline void I86::_pop_di() /* Opcode 0x5f */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[DI]);
+}
+
+inline void I86::_pusha() /* Opcode 0x60 */
+{
+ unsigned tmp = regs.w[SP];
+
+ icount -= timing.pusha;
+ PUSH(regs.w[AX]);
+ PUSH(regs.w[CX]);
+ PUSH(regs.w[DX]);
+ PUSH(regs.w[BX]);
+ PUSH(tmp);
+ PUSH(regs.w[BP]);
+ PUSH(regs.w[SI]);
+ PUSH(regs.w[DI]);
+}
+
+inline void I86::_popa() /* Opcode 0x61 */
+{
+ unsigned tmp;
+
+ icount -= timing.popa;
+ POP(regs.w[DI]);
+ POP(regs.w[SI]);
+ POP(regs.w[BP]);
+ POP(tmp);
+ POP(regs.w[BX]);
+ POP(regs.w[DX]);
+ POP(regs.w[CX]);
+ POP(regs.w[AX]);
+}
+
+inline void I86::_bound() /* Opcode 0x62 */
+{
+ unsigned ModRM = FETCHOP;
+ int low = (int16_t)GetRMWord(ModRM);
+ int high = (int16_t)GetNextRMWord;
+ int tmp = (int16_t)RegWord(ModRM);
+ if(tmp < low || tmp>high) {
+ pc -= (seg_prefix ? 3 : 2);
+ interrupt(BOUNDS_CHECK_FAULT);
+ }
+ icount -= timing.bound;
+}
+
+inline void I86::_repc(int flagval)
+{
+#ifdef HAS_V30
+ unsigned next = FETCHOP;
+ unsigned count = regs.w[CX];
+
+ switch(next) {
+ case 0x26: /* ES: */
+ seg_prefix = true;
+ prefix_seg = ES;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x2e: /* CS: */
+ seg_prefix = true;
+ prefix_seg = CS;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x36: /* SS: */
+ seg_prefix = true;
+ prefix_seg = SS;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x3e: /* DS: */
+ seg_prefix = true;
+ prefix_seg = DS;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x6c: /* REP INSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _insb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6d: /* REP INSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _insw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6e: /* REP OUTSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _outsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6f: /* REP OUTSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _outsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa4: /* REP MOVSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _movsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa5: /* REP MOVSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _movsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa6: /* REP(N)E CMPSB */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _cmpsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa7: /* REP(N)E CMPSW */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _cmpsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaa: /* REP STOSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _stosb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xab: /* REP STOSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _stosw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xac: /* REP LODSB */
+ icount -= 9;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _lodsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xad: /* REP LODSW */
+ icount -= 9;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _lodsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xae: /* REP(N)E SCASB */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _scasb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaf: /* REP(N)E SCASW */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _scasw();
+ }
+ regs.w[CX] = count;
+ break;
+ default:
+ instruction(next);
+ }
+#endif
+}
+
+inline void I86::_push_d16() /* Opcode 0x68 */
+{
+ unsigned tmp = FETCH;
+ icount -= timing.push_imm;
+ tmp += FETCH << 8;
+ PUSH(tmp);
+}
+
+inline void I86::_imul_d16() /* Opcode 0x69 */
+{
+ DEF_r16w(dst, src);
+ unsigned src2 = FETCH;
+ src += (FETCH << 8);
+ icount -= (ModRM >= 0xc0) ? timing.imul_rri16 : timing.imul_rmi16;
+ dst = (int32_t)((int16_t)src) * (int32_t)((int16_t)src2);
+ CarryVal = OverVal = (((int32_t)dst) >> 15 != 0) && (((int32_t)dst) >> 15 != -1);
+ RegWord(ModRM) = (uint16_t)dst;
+}
+
+inline void I86::_push_d8() /* Opcode 0x6a */
+{
+ unsigned tmp = (uint16_t)((int16_t)((int8_t)FETCH));
+ icount -= timing.push_imm;
+ PUSH(tmp);
+}
+
+inline void I86::_imul_d8() /* Opcode 0x6b */
+{
+ DEF_r16w(dst, src);
+ unsigned src2 = (uint16_t)((int16_t)((int8_t)FETCH));
+ icount -= (ModRM >= 0xc0) ? timing.imul_rri8 : timing.imul_rmi8;
+ dst = (int32_t)((int16_t)src) * (int32_t)((int16_t)src2);
+ CarryVal = OverVal = (((int32_t)dst) >> 15 != 0) && (((int32_t)dst) >> 15 != -1);
+ RegWord(ModRM) = (uint16_t)dst;
+}
+
+inline void I86::_insb() /* Opcode 0x6c */
+{
+ icount -= timing.ins8;
+ PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
+ regs.w[DI] += DirVal;
+}
+
+inline void I86::_insw() /* Opcode 0x6d */
+{
+ icount -= timing.ins16;
+ PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
+ regs.w[DI] += 2 * DirVal;
+}
+
+inline void I86::_outsb() /* Opcode 0x6e */
+{
+ icount -= timing.outs8;
+ write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
+ regs.w[SI] += DirVal; /* GOL 11/27/01 */
+}
+
+inline void I86::_outsw() /* Opcode 0x6f */
+{
+ icount -= timing.outs16;
+ write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
+ regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
+}
+
+inline void I86::_jo() /* Opcode 0x70 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(OF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jno() /* Opcode 0x71 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!OF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jb() /* Opcode 0x72 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(CF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnb() /* Opcode 0x73 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!CF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jz() /* Opcode 0x74 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnz() /* Opcode 0x75 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jbe() /* Opcode 0x76 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(CF || ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnbe() /* Opcode 0x77 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!(CF || ZF)) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_js() /* Opcode 0x78 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(SF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jns() /* Opcode 0x79 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!SF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jp() /* Opcode 0x7a */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(PF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnp() /* Opcode 0x7b */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!PF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jl() /* Opcode 0x7c */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if((SF!= OF) && !ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnl() /* Opcode 0x7d */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(ZF || (SF == OF)) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jle() /* Opcode 0x7e */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(ZF || (SF!= OF)) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnle() /* Opcode 0x7f */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if((SF == OF) && !ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_80pre() /* Opcode 0x80 */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD eb, d8 */
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 1: /* OR eb, d8 */
+ ORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 2: /* ADC eb, d8 */
+ src += CF;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 3: /* SBB eb, b8 */
+ src += CF;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 4: /* AND eb, d8 */
+ ANDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 5: /* SUB eb, d8 */
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 6: /* XOR eb, d8 */
+ XORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 7: /* CMP eb, d8 */
+ SUBB(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_81pre() /* Opcode 0x81 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = FETCH;
+ src += (FETCH << 8);
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD ew, d16 */
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 1: /* OR ew, d16 */
+ ORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 2: /* ADC ew, d16 */
+ src += CF;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 3: /* SBB ew, d16 */
+ src += CF;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 4: /* AND ew, d16 */
+ ANDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 5: /* SUB ew, d16 */
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 6: /* XOR ew, d16 */
+ XORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 7: /* CMP ew, d16 */
+ SUBW(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_82pre() /* Opcode 0x82 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD eb, d8 */
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 1: /* OR eb, d8 */
+ ORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 2: /* ADC eb, d8 */
+ src += CF;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 3: /* SBB eb, d8 */
+ src += CF;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 4: /* AND eb, d8 */
+ ANDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 5: /* SUB eb, d8 */
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 6: /* XOR eb, d8 */
+ XORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 7: /* CMP eb, d8 */
+ SUBB(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_83pre() /* Opcode 0x83 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = (uint16_t)((int16_t)((int8_t)FETCH));
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD ew, d16 */
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 1: /* OR ew, d16 */
+ ORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 2: /* ADC ew, d16 */
+ src += CF;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 3: /* SBB ew, d16 */
+ src += CF;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 4: /* AND ew, d16 */
+ ANDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 5: /* SUB ew, d16 */
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 6: /* XOR ew, d16 */
+ XORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 7: /* CMP ew, d16 */
+ SUBW(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_test_br8() /* Opcode 0x84 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst, src);
+}
+
+inline void I86::_test_wr16() /* Opcode 0x85 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst, src);
+}
+
+inline void I86::_xchg_br8() /* Opcode 0x86 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
+ RegByte(ModRM) = dst;
+ PutbackRMByte(ModRM, src);
+}
+
+inline void I86::_xchg_wr16() /* Opcode 0x87 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
+ RegWord(ModRM) = dst;
+ PutbackRMWord(ModRM, src);
+}
+
+inline void I86::_mov_br8() /* Opcode 0x88 */
+{
+ unsigned ModRM = FETCH;
+ uint8_t src = RegByte(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;
+ PutRMByte(ModRM, src);
+}
+
+inline void I86::_mov_wr16() /* Opcode 0x89 */
+{
+ unsigned ModRM = FETCH;
+ uint16_t src = RegWord(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;
+ PutRMWord(ModRM, src);
+}
+
+inline void I86::_mov_r8b() /* Opcode 0x8a */
+{
+ unsigned ModRM = FETCH;
+ uint8_t src = GetRMByte(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;
+ RegByte(ModRM) = src;
+}
+
+inline void I86::_mov_r16w() /* Opcode 0x8b */
+{
+ unsigned ModRM = FETCH;
+ uint16_t src = GetRMWord(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;
+ RegWord(ModRM) = src;
+}
+
+inline void I86::_mov_wsreg() /* Opcode 0x8c */
+{
+ unsigned ModRM = FETCH;
+ icount -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;
+ if(ModRM & 0x20) {
+ return; /* 1xx is invalid */
+ }
+ PutRMWord(ModRM, sregs[(ModRM & 0x38) >> 3]);
+}
+
+inline void I86::_lea() /* Opcode 0x8d */
+{
+ unsigned ModRM = FETCH;
+ icount -= timing.lea;
+ GetEA(ModRM);
+ RegWord(ModRM) = eo; /* effective offset (no segment part) */
+}
+
+inline void I86::_mov_sregw() /* Opcode 0x8e */
+{
+ unsigned ModRM = FETCH;
+ uint16_t src = GetRMWord(ModRM);
+
+ icount -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;
+ switch((ModRM >> 3) & 7) {
+ case 0: /* mov es, ew */
+ sregs[ES] = src;
+ base[ES] = SegBase(ES);
+ break;
+ case 1: /* mov cs, ew */
+ break; /* doesn't do a jump far */
+ case 2: /* mov ss, ew */
+ sregs[SS] = src;
+ base[SS] = SegBase(SS); /* no interrupt allowed before next instr */
+ instruction(FETCHOP);
+ break;
+ case 3: /* mov ds, ew */
+ sregs[DS] = src;
+ base[DS] = SegBase(DS);
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_popw() /* Opcode 0x8f */
+{
+ unsigned ModRM = FETCH;
+ uint16_t tmp;
+ POP(tmp);
+ icount -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;
+ PutRMWord(ModRM, tmp);
+}
+
+#define XchgAXReg(Reg) { \
+ uint16_t tmp; \
+ tmp = regs.w[Reg]; \
+ regs.w[Reg] = regs.w[AX]; \
+ regs.w[AX] = tmp; \
+ icount -= timing.xchg_ar16; \
+}
+
+inline void I86::_nop() /* Opcode 0x90 */
+{
+ /* this is XchgAXReg(AX); */
+ icount -= timing.nop;
+}
+
+inline void I86::_xchg_axcx() /* Opcode 0x91 */
+{
+ XchgAXReg(CX);
+}
+
+inline void I86::_xchg_axdx() /* Opcode 0x92 */
+{
+ XchgAXReg(DX);
+}
+
+inline void I86::_xchg_axbx() /* Opcode 0x93 */
+{
+ XchgAXReg(BX);
+}
+
+inline void I86::_xchg_axsp() /* Opcode 0x94 */
+{
+ XchgAXReg(SP);
+}
+
+inline void I86::_xchg_axbp() /* Opcode 0x95 */
+{
+ XchgAXReg(BP);
+}
+
+inline void I86::_xchg_axsi() /* Opcode 0x96 */
+{
+ XchgAXReg(SI);
+}
+
+inline void I86::_xchg_axdi() /* Opcode 0x97 */
+{
+ XchgAXReg(DI);
+}
+
+inline void I86::_cbw() /* Opcode 0x98 */
+{
+ icount -= timing.cbw;
+ regs.b[AH] = (regs.b[AL] & 0x80) ? 0xff : 0;
+}
+
+inline void I86::_cwd() /* Opcode 0x99 */
+{
+ icount -= timing.cwd;
+ regs.w[DX] = (regs.b[AH] & 0x80) ? 0xffff : 0;
+}
+
+inline void I86::_call_far() /* Opcode 0x9a */
+{
+ unsigned tmp, tmp2;
+ uint16_t ip;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ ip = pc - base[CS];
+ PUSH(sregs[CS]);
+ PUSH(ip);
+ sregs[CS] = (uint16_t)tmp2;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + (uint16_t)tmp) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _retf();
+ }
+#endif
+ icount -= timing.call_far;
+}
+
+inline void I86::_wait() /* Opcode 0x9b */
+{
+ if(test_state) {
+ pc--;
+ }
+ icount -= timing.wait;
+}
+
+inline void I86::_pushf() /* Opcode 0x9c */
+{
+ unsigned tmp;
+ icount -= timing.pushf;
+
+ tmp = CompressFlags();
+ PUSH(tmp | 0xf000);
+}
+
+inline void I86::_popf() /* Opcode 0x9d */
+{
+ unsigned tmp;
+ POP(tmp);
+ icount -= timing.popf;
+ ExpandFlags(tmp);
+
+ if(TF) {
+ trap();
+ }
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if(IF && (int_state & INT_REQ_BIT)) {
+ interrupt(-1);
+ }
+}
+
+inline void I86::_sahf() /* Opcode 0x9e */
+{
+ unsigned tmp = (CompressFlags() & 0xff00) | (regs.b[AH] & 0xd5);
+ icount -= timing.sahf;
+ ExpandFlags(tmp);
+}
+
+inline void I86::_lahf() /* Opcode 0x9f */
+{
+ regs.b[AH] = CompressFlags() & 0xff;
+ icount -= timing.lahf;
+}
+
+inline void I86::_mov_aldisp() /* Opcode 0xa0 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_am8;
+ regs.b[AL] = GetMemB(DS, addr);
+}
+
+inline void I86::_mov_axdisp() /* Opcode 0xa1 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_am16;
+ regs.w[AX] = GetMemW(DS, addr);
+}
+
+inline void I86::_mov_dispal() /* Opcode 0xa2 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_ma8;
+ PutMemB(DS, addr, regs.b[AL]);
+}
+
+inline void I86::_mov_dispax() /* Opcode 0xa3 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_ma16;
+ PutMemW(DS, addr, regs.w[AX]);
+}
+
+inline void I86::_movsb() /* Opcode 0xa4 */
+{
+ uint8_t tmp = GetMemB(DS, regs.w[SI]);
+ PutMemB(ES, regs.w[DI], tmp);
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.movs8;
+}
+
+inline void I86::_movsw() /* Opcode 0xa5 */
+{
+ uint16_t tmp = GetMemW(DS, regs.w[SI]);
+ PutMemW(ES, regs.w[DI], tmp);
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.movs16;
+}
+
+inline void I86::_cmpsb() /* Opcode 0xa6 */
+{
+ unsigned dst = GetMemB(ES, regs.w[DI]);
+ unsigned src = GetMemB(DS, regs.w[SI]);
+ SUBB(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.cmps8;
+}
+
+inline void I86::_cmpsw() /* Opcode 0xa7 */
+{
+ unsigned dst = GetMemW(ES, regs.w[DI]);
+ unsigned src = GetMemW(DS, regs.w[SI]);
+ SUBW(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.cmps16;
+}
+
+inline void I86::_test_ald8() /* Opcode 0xa8 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ANDB(dst, src);
+}
+
+inline void I86::_test_axd16() /* Opcode 0xa9 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ANDW(dst, src);
+}
+
+inline void I86::_stosb() /* Opcode 0xaa */
+{
+ PutMemB(ES, regs.w[DI], regs.b[AL]);
+ regs.w[DI] += DirVal;
+ icount -= timing.stos8;
+}
+
+inline void I86::_stosw() /* Opcode 0xab */
+{
+ PutMemW(ES, regs.w[DI], regs.w[AX]);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.stos16;
+}
+
+inline void I86::_lodsb() /* Opcode 0xac */
+{
+ regs.b[AL] = GetMemB(DS, regs.w[SI]);
+ regs.w[SI] += DirVal;
+ icount -= timing.lods8;
+}
+
+inline void I86::_lodsw() /* Opcode 0xad */
+{
+ regs.w[AX] = GetMemW(DS, regs.w[SI]);
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.lods16;
+}
+
+inline void I86::_scasb() /* Opcode 0xae */
+{
+ unsigned src = GetMemB(ES, regs.w[DI]);
+ unsigned dst = regs.b[AL];
+ SUBB(dst, src);
+ regs.w[DI] += DirVal;
+ icount -= timing.scas8;
+}
+
+inline void I86::_scasw() /* Opcode 0xaf */
+{
+ unsigned src = GetMemW(ES, regs.w[DI]);
+ unsigned dst = regs.w[AX];
+ SUBW(dst, src);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.scas16;
+}
+
+inline void I86::_mov_ald8() /* Opcode 0xb0 */
+{
+ regs.b[AL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_cld8() /* Opcode 0xb1 */
+{
+ regs.b[CL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_dld8() /* Opcode 0xb2 */
+{
+ regs.b[DL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_bld8() /* Opcode 0xb3 */
+{
+ regs.b[BL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_ahd8() /* Opcode 0xb4 */
+{
+ regs.b[AH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_chd8() /* Opcode 0xb5 */
+{
+ regs.b[CH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_dhd8() /* Opcode 0xb6 */
+{
+ regs.b[DH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_bhd8() /* Opcode 0xb7 */
+{
+ regs.b[BH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_axd16() /* Opcode 0xb8 */
+{
+ regs.b[AL] = FETCH;
+ regs.b[AH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_cxd16() /* Opcode 0xb9 */
+{
+ regs.b[CL] = FETCH;
+ regs.b[CH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_dxd16() /* Opcode 0xba */
+{
+ regs.b[DL] = FETCH;
+ regs.b[DH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_bxd16() /* Opcode 0xbb */
+{
+ regs.b[BL] = FETCH;
+ regs.b[BH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_spd16() /* Opcode 0xbc */
+{
+ regs.b[SPL] = FETCH;
+ regs.b[SPH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_bpd16() /* Opcode 0xbd */
+{
+ regs.b[BPL] = FETCH;
+ regs.b[BPH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_sid16() /* Opcode 0xbe */
+{
+ regs.b[SIL] = FETCH;
+ regs.b[SIH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_did16() /* Opcode 0xbf */
+{
+ regs.b[DIL] = FETCH;
+ regs.b[DIH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_rotshft_bd8() /* Opcode 0xc0 */
+{
+ unsigned ModRM = FETCH;
+ unsigned count = FETCH;
+
+ rotate_shift_byte(ModRM, count);
+}
+
+inline void I86::_rotshft_wd8() /* Opcode 0xc1 */
+{
+ unsigned ModRM = FETCH;
+ unsigned count = FETCH;
+
+ rotate_shift_word(ModRM, count);
+}
+
+inline void I86::_ret_d16() /* Opcode 0xc2 */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+ POP(pc);
+ pc = (pc + base[CS]) & AMASK;
+ regs.w[SP] += count;
+ icount -= timing.ret_near_imm;
+}
+
+inline void I86::_ret() /* Opcode 0xc3 */
+{
+ POP(pc);
+ pc = (pc + base[CS]) & AMASK;
+ icount -= timing.ret_near;
+}
+
+inline void I86::_les_dw() /* Opcode 0xc4 */
+{
+ unsigned ModRM = FETCH;
+ uint16_t tmp = GetRMWord(ModRM);
+ RegWord(ModRM) = tmp;
+ sregs[ES] = GetNextRMWord;
+ base[ES] = SegBase(ES);
+ icount -= timing.load_ptr;
+}
+
+inline void I86::_lds_dw() /* Opcode 0xc5 */
+{
+ unsigned ModRM = FETCH;
+ uint16_t tmp = GetRMWord(ModRM);
+ RegWord(ModRM) = tmp;
+ sregs[DS] = GetNextRMWord;
+ base[DS] = SegBase(DS);
+ icount -= timing.load_ptr;
+}
+
+inline void I86::_mov_bd8() /* Opcode 0xc6 */
+{
+ unsigned ModRM = FETCH;
+ icount -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;
+ PutImmRMByte(ModRM);
+}
+
+inline void I86::_mov_wd16() /* Opcode 0xc7 */
+{
+ unsigned ModRM = FETCH;
+ icount -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;
+ PutImmRMWord(ModRM);
+}
+
+inline void I86::_enter() /* Opcode 0xc8 */
+{
+ unsigned nb = FETCH;
+ unsigned i, level;
+
+ nb += FETCH << 8;
+ level = FETCH;
+ icount -= (level == 0) ? timing.enter0 : (level == 1) ? timing.enter1 : timing.enter_base + level * timing.enter_count;
+ PUSH(regs.w[BP]);
+ regs.w[BP] = regs.w[SP];
+ regs.w[SP] -= nb;
+ for(i = 1; i < level; i++) {
+ PUSH(GetMemW(SS, regs.w[BP] - i * 2));
+ }
+ if(level) {
+ PUSH(regs.w[BP]);
+ }
+}
+
+inline void I86::_leav() /* Opcode 0xc9 */
+{
+ icount -= timing.leave;
+ regs.w[SP] = regs.w[BP];
+ POP(regs.w[BP]);
+}
+
+inline void I86::_retf_d16() /* Opcode 0xca */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+ POP(pc);
+ POP(sregs[CS]);
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ regs.w[SP] += count;
+ icount -= timing.ret_far_imm;
+}
+
+inline void I86::_retf() /* Opcode 0xcb */
+{
+ POP(pc);
+ POP(sregs[CS]);
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ icount -= timing.ret_far;
+}
+
+inline void I86::_int3() /* Opcode 0xcc */
+{
+ icount -= timing.int3;
+ interrupt(3);
+}
+
+inline void I86::_int() /* Opcode 0xcd */
+{
+ unsigned int_num = FETCH;
+ icount -= timing.int_imm;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_int_i86(int_num, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ return;
+ }
+#endif
+ interrupt(int_num);
+}
+
+inline void I86::_into() /* Opcode 0xce */
+{
+ if(OF) {
+ icount -= timing.into_t;
+ interrupt(OVERFLOW_TRAP);
+ } else {
+ icount -= timing.into_nt;
+ }
+}
+
+inline void I86::_iret() /* Opcode 0xcf */
+{
+ icount -= timing.iret;
+ POP(pc);
+ POP(sregs[CS]);
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ _popf();
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if(IF && (int_state & INT_REQ_BIT)) {
+ interrupt(-1);
+ }
+}
+
+inline void I86::_rotshft_b() /* Opcode 0xd0 */
+{
+ rotate_shift_byte(FETCHOP, 1);
+}
+
+inline void I86::_rotshft_w() /* Opcode 0xd1 */
+{
+ rotate_shift_word(FETCHOP, 1);
+}
+
+inline void I86::_rotshft_bcl() /* Opcode 0xd2 */
+{
+ rotate_shift_byte(FETCHOP, regs.b[CL]);
+}
+
+inline void I86::_rotshft_wcl() /* Opcode 0xd3 */
+{
+ rotate_shift_word(FETCHOP, regs.b[CL]);
+}
+
+/* OB: Opcode works on NEC V-Series but not the Variants */
+/* one could specify any byte value as operand but the NECs */
+/* always substitute 0x0a. */
+inline void I86::_aam() /* Opcode 0xd4 */
+{
+ unsigned mult = FETCH;
+ icount -= timing.aam;
+ if(mult == 0) {
+ interrupt(DIVIDE_FAULT);
+ } else {
+ regs.b[AH] = regs.b[AL] / mult;
+ regs.b[AL] %= mult;
+ SetSZPF_Word(regs.w[AX]);
+ }
+}
+
+inline void I86::_aad() /* Opcode 0xd5 */
+{
+ unsigned mult = FETCH;
+ icount -= timing.aad;
+#ifdef HAS_V30
+ regs.b[AL] = regs.b[AH] * 10 + regs.b[AL];
+#else
+ regs.b[AL] = regs.b[AH] * mult + regs.b[AL];
+#endif
+ regs.b[AH] = 0;
+ SetZF(regs.b[AL]);
+ SetPF(regs.b[AL]);
+ SignVal = 0;
+}
+
+inline void I86::_setalc() /* Opcode 0xd6 */
+{
+ regs.b[AL] = (CF) ? 0xff : 0x00;
+ icount -= 3;
+}
+
+inline void I86::_xlat() /* Opcode 0xd7 */
+{
+ unsigned dest = regs.w[BX] + regs.b[AL];
+ icount -= timing.xlat;
+ regs.b[AL] = GetMemB(DS, dest);
+}
+
+inline void I86::_escape() /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
+{
+ unsigned ModRM = FETCH;
+ icount -= timing.nop;
+ GetRMByte(ModRM);
+}
+
+inline void I86::_loopne() /* Opcode 0xe0 */
+{
+ int disp = (int)((int8_t)FETCH);
+ unsigned tmp = regs.w[CX] - 1;
+ regs.w[CX] = tmp;
+ if(!ZF && tmp) {
+ icount -= timing.loop_t;
+ pc += disp;
+ } else {
+ icount -= timing.loop_nt;
+ }
+}
+
+inline void I86::_loope() /* Opcode 0xe1 */
+{
+ int disp = (int)((int8_t)FETCH);
+ unsigned tmp = regs.w[CX] - 1;
+ regs.w[CX] = tmp;
+ if(ZF && tmp) {
+ icount -= timing.loope_t;
+ pc += disp;
+ } else {
+ icount -= timing.loope_nt;
+ }
+}
+
+inline void I86::_loop() /* Opcode 0xe2 */
+{
+ int disp = (int)((int8_t)FETCH);
+ unsigned tmp = regs.w[CX] - 1;
+ regs.w[CX] = tmp;
+ if(tmp) {
+ icount -= timing.loop_t;
+ pc += disp;
+ } else {
+ icount -= timing.loop_nt;
+ }
+}
+
+inline void I86::_jcxz() /* Opcode 0xe3 */
+{
+ int disp = (int)((int8_t)FETCH);
+ if(regs.w[CX] == 0) {
+ icount -= timing.jcxz_t;
+ pc += disp;
+ } else {
+ icount -= timing.jcxz_nt;
+ }
+}
+
+inline void I86::_inal() /* Opcode 0xe4 */
+{
+ unsigned port = FETCH;
+ icount -= timing.in_imm8;
+ regs.b[AL] = read_port_byte(port);
+}
+
+inline void I86::_inax() /* Opcode 0xe5 */
+{
+ unsigned port = FETCH;
+ icount -= timing.in_imm16;
+ regs.w[AX] = read_port_word(port);
+}
+
+inline void I86::_outal() /* Opcode 0xe6 */
+{
+ unsigned port = FETCH;
+ icount -= timing.out_imm8;
+ write_port_byte(port, regs.b[AL]);
+}
+
+inline void I86::_outax() /* Opcode 0xe7 */
+{
+ unsigned port = FETCH;
+ icount -= timing.out_imm16;
+ write_port_word(port, regs.w[AX]);
+}
+
+inline void I86::_call_d16() /* Opcode 0xe8 */
+{
+ uint16_t ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = pc - base[CS];
+ PUSH(ip);
+ ip += tmp;
+ pc = (ip + base[CS]) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _ret();
+ }
+#endif
+ icount -= timing.call_near;
+}
+
+inline void I86::_jmp_d16() /* Opcode 0xe9 */
+{
+ uint16_t ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = pc - base[CS] + tmp;
+ pc = (ip + base[CS]) & AMASK;
+ icount -= timing.jmp_near;
+}
+
+inline void I86::_jmp_far() /* Opcode 0xea */
+{
+ unsigned tmp, tmp1;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp1 = FETCH;
+ tmp1 += FETCH << 8;
+
+ sregs[CS] = (uint16_t)tmp1;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + tmp) & AMASK;
+ icount -= timing.jmp_far;
+}
+
+inline void I86::_jmp_d8() /* Opcode 0xeb */
+{
+ int tmp = (int)((int8_t)FETCH);
+ pc += tmp;
+ icount -= timing.jmp_short;
+}
+
+inline void I86::_inaldx() /* Opcode 0xec */
+{
+ icount -= timing.in_dx8;
+ regs.b[AL] = read_port_byte(regs.w[DX]);
+}
+
+inline void I86::_inaxdx() /* Opcode 0xed */
+{
+ unsigned port = regs.w[DX];
+ icount -= timing.in_dx16;
+ regs.w[AX] = read_port_word(port);
+}
+
+inline void I86::_outdxal() /* Opcode 0xee */
+{
+ icount -= timing.out_dx8;
+ write_port_byte(regs.w[DX], regs.b[AL]);
+}
+
+inline void I86::_outdxax() /* Opcode 0xef */
+{
+ unsigned port = regs.w[DX];
+ icount -= timing.out_dx16;
+ write_port_word(port, regs.w[AX]);
+}
+
+/* I think thats not a V20 instruction...*/
+inline void I86::_lock() /* Opcode 0xf0 */
+{
+ icount -= timing.nop;
+ instruction(FETCHOP); /* un-interruptible */
+}
+
+inline void I86::_rep(int flagval)
+{
+ /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the
+ loop to continue for CMPS and SCAS instructions. */
+
+ unsigned next = FETCHOP;
+ unsigned count = regs.w[CX];
+
+ switch(next) {
+ case 0x26: /* ES: */
+ seg_prefix = true;
+ prefix_seg = ES;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+ case 0x2e: /* CS: */
+ seg_prefix = true;
+ prefix_seg = CS;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+ case 0x36: /* SS: */
+ seg_prefix = true;
+ prefix_seg = SS;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+ case 0x3e: /* DS: */
+ seg_prefix = true;
+ prefix_seg = DS;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+#ifndef HAS_I86
+ case 0x6c: /* REP INSB */
+ icount -= timing.rep_ins8_base;
+ for(; count > 0; count--) {
+ PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
+ regs.w[DI] += DirVal;
+ icount -= timing.rep_ins8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6d: /* REP INSW */
+ icount -= timing.rep_ins16_base;
+ for(; count > 0; count--) {
+ PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.rep_ins16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6e: /* REP OUTSB */
+ icount -= timing.rep_outs8_base;
+ for(; count > 0; count--) {
+ write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
+ regs.w[SI] += DirVal; /* GOL 11/27/01 */
+ icount -= timing.rep_outs8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6f: /* REP OUTSW */
+ icount -= timing.rep_outs16_base;
+ for(; count > 0; count--) {
+ write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
+ regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
+ icount -= timing.rep_outs16_count;
+ }
+ regs.w[CX] = count;
+ break;
+#endif
+ case 0xa4: /* REP MOVSB */
+ icount -= timing.rep_movs8_base;
+ for(; count > 0; count--) {
+ uint8_t tmp;
+ tmp = GetMemB(DS, regs.w[SI]);
+ PutMemB(ES, regs.w[DI], tmp);
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.rep_movs8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa5: /* REP MOVSW */
+ icount -= timing.rep_movs16_base;
+ for(; count > 0; count--) {
+ uint16_t tmp;
+ tmp = GetMemW(DS, regs.w[SI]);
+ PutMemW(ES, regs.w[DI], tmp);
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.rep_movs16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa6: /* REP(N)E CMPSB */
+ icount -= timing.rep_cmps8_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned dst, src;
+ dst = GetMemB(ES, regs.w[DI]);
+ src = GetMemB(DS, regs.w[SI]);
+ SUBB(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.rep_cmps8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa7: /* REP(N)E CMPSW */
+ icount -= timing.rep_cmps16_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned dst, src;
+ dst = GetMemW(ES, regs.w[DI]);
+ src = GetMemW(DS, regs.w[SI]);
+ SUBW(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.rep_cmps16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaa: /* REP STOSB */
+ icount -= timing.rep_stos8_base;
+ for(; count > 0; count--) {
+ PutMemB(ES, regs.w[DI], regs.b[AL]);
+ regs.w[DI] += DirVal;
+ icount -= timing.rep_stos8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xab: /* REP STOSW */
+ icount -= timing.rep_stos16_base;
+ for(; count > 0; count--) {
+ PutMemW(ES, regs.w[DI], regs.w[AX]);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.rep_stos16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xac: /* REP LODSB */
+ icount -= timing.rep_lods8_base;
+ for(; count > 0; count--) {
+ regs.b[AL] = GetMemB(DS, regs.w[SI]);
+ regs.w[SI] += DirVal;
+ icount -= timing.rep_lods8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xad: /* REP LODSW */
+ icount -= timing.rep_lods16_base;
+ for(; count > 0; count--) {
+ regs.w[AX] = GetMemW(DS, regs.w[SI]);
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.rep_lods16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xae: /* REP(N)E SCASB */
+ icount -= timing.rep_scas8_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned src, dst;
+ src = GetMemB(ES, regs.w[DI]);
+ dst = regs.b[AL];
+ SUBB(dst, src);
+ regs.w[DI] += DirVal;
+ icount -= timing.rep_scas8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaf: /* REP(N)E SCASW */
+ icount -= timing.rep_scas16_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned src, dst;
+ src = GetMemW(ES, regs.w[DI]);
+ dst = regs.w[AX];
+ SUBW(dst, src);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.rep_scas16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ default:
+ instruction(next);
+ }
+}
+
+inline void I86::_repne() /* Opcode 0xf2 */
+{
+ _rep(0);
+}
+
+inline void I86::_repe() /* Opcode 0xf3 */
+{
+ _rep(1);
+}
+
+inline void I86::_hlt() /* Opcode 0xf4 */
+{
+ pc--;
+ halted = true;
+ icount -= 2;
+}
+
+inline void I86::_cmc() /* Opcode 0xf5 */
+{
+ icount -= timing.flag_ops;
+ CarryVal = !CF;
+}
+
+inline void I86::_f6pre() /* Opcode 0xf6 */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = (unsigned)GetRMByte(ModRM);
+ unsigned tmp2;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* TEST Eb, data8 */
+ case 1: /* ??? */
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ tmp &= FETCH;
+
+ CarryVal = OverVal = AuxVal = 0;
+ SetSZPF_Byte(tmp);
+ break;
+
+ case 2: /* NOT Eb */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ PutbackRMByte(ModRM, ~tmp);
+ break;
+
+ case 3: /* NEG Eb */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ tmp2 = 0;
+ SUBB(tmp2, tmp);
+ PutbackRMByte(ModRM, tmp2);
+ break;
+
+ case 4: /* MUL AL, Eb */
+ icount -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;
+ {
+ uint16_t result;
+
+ tmp2 = regs.b[AL];
+
+ SetSF((int8_t)tmp2);
+ SetPF(tmp2);
+
+ result = (uint16_t)tmp2 * tmp;
+ regs.w[AX] = (uint16_t)result;
+
+ SetZF(regs.w[AX]);
+ CarryVal = OverVal = (regs.b[AH] != 0);
+ }
+ break;
+
+ case 5: /* IMUL AL, Eb */
+ icount -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;
+ {
+ int16_t result;
+
+ tmp2 = (unsigned)regs.b[AL];
+
+ SetSF((int8_t)tmp2);
+ SetPF(tmp2);
+
+ result = (int16_t)((int8_t)tmp2) * (int16_t)((int8_t)tmp);
+ regs.w[AX] = (uint16_t)result;
+
+ SetZF(regs.w[AX]);
+ CarryVal = OverVal = (result >> 7 != 0) && (result >> 7 != -1);
+ }
+ break;
+
+ case 6: /* DIV AL, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;
+ {
+ uint16_t result;
+
+ result = regs.w[AX];
+
+ if(tmp) {
+ if((result / tmp) > 0xff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.b[AH] = result % tmp;
+ regs.b[AL] = result / tmp;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+ case 7: /* IDIV AL, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;
+ {
+ int16_t result;
+
+ result = regs.w[AX];
+
+ if(tmp) {
+ tmp2 = result % (int16_t)((int8_t)tmp);
+
+ if((result /= (int16_t)((int8_t)tmp)) > 0xff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.b[AL] = (uint8_t)result;
+ regs.b[AH] = tmp2;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_f7pre() /* Opcode 0xf7 */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMWord(ModRM);
+ unsigned tmp2;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* TEST Ew, data16 */
+ case 1: /* ??? */
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ tmp &= tmp2;
+
+ CarryVal = OverVal = AuxVal = 0;
+ SetSZPF_Word(tmp);
+ break;
+
+ case 2: /* NOT Ew */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp = ~tmp;
+ PutbackRMWord(ModRM, tmp);
+ break;
+
+ case 3: /* NEG Ew */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp2 = 0;
+ SUBW(tmp2, tmp);
+ PutbackRMWord(ModRM, tmp2);
+ break;
+
+ case 4: /* MUL AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;
+ {
+ uint32_t result;
+ tmp2 = regs.w[AX];
+
+ SetSF((int16_t)tmp2);
+ SetPF(tmp2);
+
+ result = (uint32_t)tmp2 * tmp;
+ regs.w[AX] = (uint16_t)result;
+ result >>= 16;
+ regs.w[DX] = result;
+
+ SetZF(regs.w[AX] | regs.w[DX]);
+ CarryVal = OverVal = (regs.w[DX] != 0);
+ }
+ break;
+
+ case 5: /* IMUL AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;
+ {
+ int32_t result;
+
+ tmp2 = regs.w[AX];
+
+ SetSF((int16_t)tmp2);
+ SetPF(tmp2);
+
+ result = (int32_t)((int16_t)tmp2) * (int32_t)((int16_t)tmp);
+ CarryVal = OverVal = (result >> 15 != 0) && (result >> 15 != -1);
+
+ regs.w[AX] = (uint16_t)result;
+ result = (uint16_t)(result >> 16);
+ regs.w[DX] = result;
+
+ SetZF(regs.w[AX] | regs.w[DX]);
+ }
+ break;
+
+ case 6: /* DIV AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;
+ {
+ uint32_t result;
+
+ result = (regs.w[DX] << 16) + regs.w[AX];
+
+ if(tmp) {
+ tmp2 = result % tmp;
+ if((result / tmp) > 0xffff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.w[DX] = tmp2;
+ result /= tmp;
+ regs.w[AX] = result;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+ case 7: /* IDIV AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;
+ {
+ int32_t result;
+
+ result = (regs.w[DX] << 16) + regs.w[AX];
+
+ if(tmp) {
+ tmp2 = result % (int32_t)((int16_t)tmp);
+ if((result /= (int32_t)((int16_t)tmp)) > 0xffff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.w[AX] = result;
+ regs.w[DX] = tmp2;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_clc() /* Opcode 0xf8 */
+{
+ icount -= timing.flag_ops;
+ CarryVal = 0;
+}
+
+inline void I86::_stc() /* Opcode 0xf9 */
+{
+ icount -= timing.flag_ops;
+ CarryVal = 1;
+}
+
+inline void I86::_cli() /* Opcode 0xfa */
+{
+ icount -= timing.flag_ops;
+ SetIF(0);
+}
+
+inline void I86::_sti() /* Opcode 0xfb */
+{
+ icount -= timing.flag_ops;
+ SetIF(1);
+ instruction(FETCHOP); /* no interrupt before next instruction */
+
+ /* if an interrupt is pending, signal an interrupt */
+ if(IF && (int_state & INT_REQ_BIT)) {
+ interrupt(-1);
+ }
+}
+
+inline void I86::_cld() /* Opcode 0xfc */
+{
+ icount -= timing.flag_ops;
+ SetDF(0);
+}
+
+inline void I86::_std() /* Opcode 0xfd */
+{
+ icount -= timing.flag_ops;
+ SetDF(1);
+}
+
+inline void I86::_fepre() /* Opcode 0xfe */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMByte(ModRM);
+ unsigned tmp1;
+
+ icount -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;
+ if((ModRM & 0x38) == 0) {
+ /* INC eb */
+ tmp1 = tmp + 1;
+ SetOFB_Add(tmp1, tmp, 1);
+ } else {
+ /* DEC eb */
+ tmp1 = tmp - 1;
+ SetOFB_Sub(tmp1, 1, tmp);
+ }
+ SetAF(tmp1, tmp, 1);
+ SetSZPF_Byte(tmp1);
+ PutbackRMByte(ModRM, (uint8_t)tmp1);
+}
+
+inline void I86::_ffpre() /* Opcode 0xff */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned tmp;
+ unsigned tmp1;
+ uint16_t ip;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* INC ew */
+ icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp + 1;
+ SetOFW_Add(tmp1, tmp, 1);
+ SetAF(tmp1, tmp, 1);
+ SetSZPF_Word(tmp1);
+ PutbackRMWord(ModRM, (uint16_t)tmp1);
+ break;
+ case 1: /* DEC ew */
+ icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp - 1;
+ SetOFW_Sub(tmp1, 1, tmp);
+ SetAF(tmp1, tmp, 1);
+ SetSZPF_Word(tmp1);
+ PutbackRMWord(ModRM, (uint16_t)tmp1);
+ break;
+ case 2: /* CALL ew */
+ icount -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;
+ tmp = GetRMWord(ModRM);
+ ip = pc - base[CS];
+ PUSH(ip);
+ pc = (base[CS] + (uint16_t)tmp) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _ret();
+ }
+#endif
+ break;
+ case 3: /* CALL FAR ea */
+ icount -= timing.call_m32;
+ tmp = sregs[CS]; /* need to skip displacements of ea */
+ tmp1 = GetRMWord(ModRM);
+ ip = pc - base[CS];
+ PUSH(tmp);
+ PUSH(ip);
+ sregs[CS] = GetNextRMWord;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + tmp1) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _ret();
+ }
+#endif
+ break;
+ case 4: /* JMP ea */
+ icount -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;
+ ip = GetRMWord(ModRM);
+ pc = (base[CS] + ip) & AMASK;
+ break;
+ case 5: /* JMP FAR ea */
+ icount -= timing.jmp_m32;
+ pc = GetRMWord(ModRM);
+ sregs[CS] = GetNextRMWord;
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ break;
+ case 6: /* PUSH ea */
+ icount -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;
+ tmp = GetRMWord(ModRM);
+ PUSH(tmp);
+ break;
+ case 7: /* invalid ??? */
+ icount -= 10;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_invalid()
+{
+ /* i8086/i8088 ignore an invalid opcode. */
+ /* i80186/i80188 probably also ignore an invalid opcode. */
+ icount -= 10;
+}
+
+/*
+ NEC V-series Disassembler
+
+ Originally Written for i386 by Ville Linde
+ Converted to NEC-V by Aaron Giles
+*/
+
+enum
+{
+ PARAM_REG8 = 1, /* 8-bit register */
+ PARAM_REG16, /* 16-bit register */
+ PARAM_REG2_8, /* 8-bit register */
+ PARAM_REG2_16, /* 16-bit register */
+ PARAM_RM8, /* 8-bit memory or register */
+ PARAM_RM16, /* 16-bit memory or register */
+ PARAM_RMPTR8, /* 8-bit memory or register */
+ PARAM_RMPTR16, /* 16-bit memory or register */
+ PARAM_I3, /* 3-bit immediate */
+ PARAM_I4, /* 4-bit immediate */
+ PARAM_I8, /* 8-bit signed immediate */
+ PARAM_I16, /* 16-bit signed immediate */
+ PARAM_UI8, /* 8-bit unsigned immediate */
+ PARAM_IMM, /* 16-bit immediate */
+ PARAM_ADDR, /* 16:16 address */
+ PARAM_REL8, /* 8-bit PC-relative displacement */
+ PARAM_REL16, /* 16-bit PC-relative displacement */
+ PARAM_MEM_OFFS, /* 16-bit mem offset */
+ PARAM_SREG, /* segment register */
+ PARAM_SFREG, /* V25/V35 special function register */
+ PARAM_1, /* used by shift/rotate instructions */
+ PARAM_AL,
+ PARAM_CL,
+ PARAM_DL,
+ PARAM_BL,
+ PARAM_AH,
+ PARAM_CH,
+ PARAM_DH,
+ PARAM_BH,
+ PARAM_AW,
+ PARAM_CW,
+ PARAM_DW,
+ PARAM_BW,
+ PARAM_SP,
+ PARAM_BP,
+ PARAM_IX,
+ PARAM_IY
+};
+
+enum
+{
+ MODRM = 1,
+ GROUP,
+ FPU,
+ TWO_BYTE,
+ PREFIX,
+ SEG_PS,
+ SEG_DS0,
+ SEG_DS1,
+ SEG_SS
+};
+
+struct I386_OPCODE {
+ _TCHAR mnemonic[32];
+ UINT32 flags;
+ UINT32 param1;
+ UINT32 param2;
+ UINT32 param3;
+ offs_t dasm_flags;
+};
+
+struct GROUP_OP {
+ _TCHAR mnemonic[32];
+ const I386_OPCODE *opcode;
+};
+
+static const UINT8 *opcode_ptr;
+static const UINT8 *opcode_ptr_base;
+
+static const I386_OPCODE necv_opcode_table1[256] =
+{
+ // 0x00
+ {_T("add"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("add"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("add"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("add"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("add"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("add"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ds1"), 0, 0, 0, 0 },
+ {_T("pop ds1"), 0, 0, 0, 0 },
+ {_T("or"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("or"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("or"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("or"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("or"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("or"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ps"), 0, 0, 0, 0 },
+ {_T("two_byte"), TWO_BYTE, 0, 0, 0 },
+ // 0x10
+ {_T("addc"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("addc"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("addc"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("addc"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("addc"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("addc"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ss"), 0, 0, 0, 0 },
+ {_T("pop ss"), 0, 0, 0, 0 },
+ {_T("subc"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("subc"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("subc"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("subc"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("subc"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("subc"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ds0"), 0, 0, 0, 0 },
+ {_T("pop ds0"), 0, 0, 0, 0 },
+ // 0x20
+ {_T("and"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("and"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("and"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("and"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("and"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("and"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ds1:"), SEG_DS1, 0, 0, 0 },
+ {_T("adj4a"), 0, 0, 0, 0 },
+ {_T("sub"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("sub"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("sub"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("sub"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("sub"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("sub"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ps:"), SEG_PS, 0, 0, 0 },
+ {_T("adj4s"), 0, 0, 0, 0 },
+ // 0x30
+ {_T("xor"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("xor"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("xor"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("xor"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("xor"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("xor"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ss:"), SEG_SS, 0, 0, 0 },
+ {_T("adjba"), 0, 0, 0, 0 },
+ {_T("cmp"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("cmp"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("cmp"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("cmp"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("cmp"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("cmp"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ds0:"), SEG_DS0, 0, 0, 0 },
+ {_T("adjbs"), 0, 0, 0, 0 },
+ // 0x40
+ {_T("inc"), 0, PARAM_AW, 0, 0 },
+ {_T("inc"), 0, PARAM_CW, 0, 0 },
+ {_T("inc"), 0, PARAM_DW, 0, 0 },
+ {_T("inc"), 0, PARAM_BW, 0, 0 },
+ {_T("inc"), 0, PARAM_SP, 0, 0 },
+ {_T("inc"), 0, PARAM_BP, 0, 0 },
+ {_T("inc"), 0, PARAM_IX, 0, 0 },
+ {_T("inc"), 0, PARAM_IY, 0, 0 },
+ {_T("dec"), 0, PARAM_AW, 0, 0 },
+ {_T("dec"), 0, PARAM_CW, 0, 0 },
+ {_T("dec"), 0, PARAM_DW, 0, 0 },
+ {_T("dec"), 0, PARAM_BW, 0, 0 },
+ {_T("dec"), 0, PARAM_SP, 0, 0 },
+ {_T("dec"), 0, PARAM_BP, 0, 0 },
+ {_T("dec"), 0, PARAM_IX, 0, 0 },
+ {_T("dec"), 0, PARAM_IY, 0, 0 },
+ // 0x50
+ {_T("push"), 0, PARAM_AW, 0, 0 },
+ {_T("push"), 0, PARAM_CW, 0, 0 },
+ {_T("push"), 0, PARAM_DW, 0, 0 },
+ {_T("push"), 0, PARAM_BW, 0, 0 },
+ {_T("push"), 0, PARAM_SP, 0, 0 },
+ {_T("push"), 0, PARAM_BP, 0, 0 },
+ {_T("push"), 0, PARAM_IX, 0, 0 },
+ {_T("push"), 0, PARAM_IY, 0, 0 },
+ {_T("pop"), 0, PARAM_AW, 0, 0 },
+ {_T("pop"), 0, PARAM_CW, 0, 0 },
+ {_T("pop"), 0, PARAM_DW, 0, 0 },
+ {_T("pop"), 0, PARAM_BW, 0, 0 },
+ {_T("pop"), 0, PARAM_SP, 0, 0 },
+ {_T("pop"), 0, PARAM_BP, 0, 0 },
+ {_T("pop"), 0, PARAM_IX, 0, 0 },
+ {_T("pop"), 0, PARAM_IY, 0, 0 },
+ // 0x60
+ {_T("push r"), 0, 0, 0, 0 },
+ {_T("pop r"), 0, 0, 0, 0 },
+ {_T("chkind"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("brkn"), 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
+ {_T("repnc"), PREFIX, 0, 0, 0 },
+ {_T("repc"), PREFIX, 0, 0, 0 },
+ {_T("fpo2 0"), 0, 0, 0, 0 }, /* for a coprocessor that was never made */
+ {_T("fpo2 1"), 0, 0, 0, 0 }, /* for a coprocessor that was never made */
+ {_T("push"), 0, PARAM_IMM, 0, 0 },
+ {_T("mul"), MODRM, PARAM_REG16, PARAM_RM16, PARAM_IMM },
+ {_T("push"), 0, PARAM_I8, 0, 0 },
+ {_T("mul"), MODRM, PARAM_REG16, PARAM_RM16, PARAM_I8 },
+ {_T("inmb"), 0, 0, 0, 0 },
+ {_T("inmw"), 0, 0, 0, 0 },
+ {_T("outmb"), 0, 0, 0, 0 },
+ {_T("outmw"), 0, 0, 0, 0 },
+ // 0x70
+ {_T("bv"), 0, PARAM_REL8, 0, 0 },
+ {_T("bnv"), 0, PARAM_REL8, 0, 0 },
+ {_T("bc"), 0, PARAM_REL8, 0, 0 },
+ {_T("bnc"), 0, PARAM_REL8, 0, 0 },
+ {_T("be"), 0, PARAM_REL8, 0, 0 },
+ {_T("bne"), 0, PARAM_REL8, 0, 0 },
+ {_T("bnh"), 0, PARAM_REL8, 0, 0 },
+ {_T("bh"), 0, PARAM_REL8, 0, 0 },
+ {_T("bn"), 0, PARAM_REL8, 0, 0 },
+ {_T("bp"), 0, PARAM_REL8, 0, 0 },
+ {_T("bpe"), 0, PARAM_REL8, 0, 0 },
+ {_T("bpo"), 0, PARAM_REL8, 0, 0 },
+ {_T("blt"), 0, PARAM_REL8, 0, 0 },
+ {_T("bge"), 0, PARAM_REL8, 0, 0 },
+ {_T("ble"), 0, PARAM_REL8, 0, 0 },
+ {_T("bgt"), 0, PARAM_REL8, 0, 0 },
+ // 0x80
+ {_T("immb"), GROUP, 0, 0, 0 },
+ {_T("immw"), GROUP, 0, 0, 0 },
+ {_T("immb"), GROUP, 0, 0, 0 },
+ {_T("immws"), GROUP, 0, 0, 0 },
+ {_T("test"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("test"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("xch"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("xch"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("mov"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("mov"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("mov"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_RM16, PARAM_SREG, 0 },
+ {_T("ldea"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_SREG, PARAM_RM16, 0 },
+ {_T("pop"), MODRM, PARAM_RM16, 0, 0 },
+ // 0x90
+ {_T("nop"), 0, 0, 0, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_CW, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_DW, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_BW, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_SP, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_BP, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_IX, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_IY, 0 },
+ {_T("cvtbw"), 0, 0, 0, 0 },
+ {_T("cvtwl"), 0, 0, 0, 0 },
+ {_T("call"), 0, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("poll"), 0, 0, 0, 0 },
+ {_T("push psw"), 0, 0, 0, 0 },
+ {_T("pop psw"), 0, 0, 0, 0 },
+ {_T("mov psw,ah"), 0, 0, 0, 0 },
+ {_T("mov ah,psw"), 0, 0, 0, 0 },
+ // 0xa0
+ {_T("mov"), 0, PARAM_AL, PARAM_MEM_OFFS, 0 },
+ {_T("mov"), 0, PARAM_AW, PARAM_MEM_OFFS, 0 },
+ {_T("mov"), 0, PARAM_MEM_OFFS, PARAM_AL, 0 },
+ {_T("mov"), 0, PARAM_MEM_OFFS, PARAM_AW, 0 },
+ {_T("movbkb"), 0, 0, 0, 0 },
+ {_T("movbkw"), 0, 0, 0, 0 },
+ {_T("cmpbkb"), 0, 0, 0, 0 },
+ {_T("cmpbkw"), 0, 0, 0, 0 },
+ {_T("test"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("test"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("stmb"), 0, 0, 0, 0 },
+ {_T("stmw"), 0, 0, 0, 0 },
+ {_T("ldmb"), 0, 0, 0, 0 },
+ {_T("ldmw"), 0, 0, 0, 0 },
+ {_T("cmpmb"), 0, 0, 0, 0 },
+ {_T("cmpmw"), 0, 0, 0, 0 },
+ // 0xb0
+ {_T("mov"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_CL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_DL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_BL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_AH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_CH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_DH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_BH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_CW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_DW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_BW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_SP, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_BP, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_IX, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_IY, PARAM_IMM, 0 },
+ // 0xc0
+ {_T("shiftbi"), GROUP, 0, 0, 0 },
+ {_T("shiftwi"), GROUP, 0, 0, 0 },
+ {_T("ret"), 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("ret"), 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("mov ds1,"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov ds0,"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("mov"), MODRM, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("prepare"), 0, PARAM_I16, PARAM_UI8, 0 },
+ {_T("dispose"), 0, 0, 0, 0 },
+ {_T("retf"), 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("retf"), 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("brk 3"), 0, 0, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("brk"), 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("brkv"), 0, 0, 0, 0 },
+ {_T("reti"), 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ // 0xd0
+ {_T("shiftb"), GROUP, 0, 0, 0 },
+ {_T("shiftw"), GROUP, 0, 0, 0 },
+ {_T("shiftbv"), GROUP, 0, 0, 0 },
+ {_T("shiftwv"), GROUP, 0, 0, 0 },
+ {_T("cvtbd"), 0, PARAM_I8, 0, 0 },
+ {_T("cvtdb"), 0, PARAM_I8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("trans"), 0, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ // 0xe0
+ {_T("dbnzne"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("dbnze"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("dbnz"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("bcwz"), 0, PARAM_REL8, 0, 0 },
+ {_T("in"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("in"), 0, PARAM_AW, PARAM_UI8, 0 },
+ {_T("out"), 0, PARAM_UI8, PARAM_AL, 0 },
+ {_T("out"), 0, PARAM_UI8, PARAM_AW, 0 },
+ {_T("call"), 0, PARAM_REL16, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("br"), 0, PARAM_REL16, 0, 0 },
+ {_T("br"), 0, PARAM_ADDR, 0, 0 },
+ {_T("br"), 0, PARAM_REL8, 0, 0 },
+ {_T("in"), 0, PARAM_AL, PARAM_DW, 0 },
+ {_T("in"), 0, PARAM_AW, PARAM_DW, 0 },
+ {_T("out"), 0, PARAM_DW, PARAM_AL, 0 },
+ {_T("out"), 0, PARAM_DW, PARAM_AW, 0 },
+ // 0xf0
+ {_T("buslock"), PREFIX, 0, 0, 0 },
+ {_T("brks"), 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
+ {_T("repne"), PREFIX, 0, 0, 0 },
+ {_T("rep"), PREFIX, 0, 0, 0 },
+ {_T("halt"), 0, 0, 0, 0 },
+ {_T("not1 cy"), 0, 0, 0, 0 },
+ {_T("group1b"), GROUP, 0, 0, 0 },
+ {_T("group1w"), GROUP, 0, 0, 0 },
+ {_T("clr1 cy"), 0, 0, 0, 0 },
+ {_T("set1 cy"), 0, 0, 0, 0 },
+ {_T("di"), 0, 0, 0, 0 },
+ {_T("ei"), 0, 0, 0, 0 },
+ {_T("clr1 dir"), 0, 0, 0, 0 },
+ {_T("set1 dir"), 0, 0, 0, 0 },
+ {_T("group2b"), GROUP, 0, 0, 0 },
+ {_T("group2w"), GROUP, 0, 0, 0 }
+};
+
+static const I386_OPCODE necv_opcode_table2[256] =
+{
+ // 0x00
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x10
+ {_T("test1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("test1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("test1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("test1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ // 0x20
+ {_T("add4s"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("sub4s"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("movspa"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("cmp4s"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("rol4"), MODRM, PARAM_RMPTR8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ror4"), MODRM, PARAM_RMPTR8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("brkcs"), MODRM, PARAM_REG2_16, 0, 0, DASMFLAG_STEP_OVER}, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x30
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ins"), MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ext"), MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ins"), MODRM, PARAM_REG2_8, PARAM_I4, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ext"), MODRM, PARAM_REG2_8, PARAM_I4, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x40
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x50
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x60
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x70
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x80
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x90
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("retrbi"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("fint"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("tsksw"), MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
+ {_T("movspb"), MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("btclr"), 0, PARAM_SFREG, PARAM_I3, PARAM_REL8 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("stop"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xa0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xb0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xc0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xd0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xe0
+ {_T("brkxa"), 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xf0
+ {_T("retxa"), 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("brkem"), 0, PARAM_UI8, 0, 0 } /* V20,30,40,50 only */
+};
+
+static const I386_OPCODE immb_table[8] =
+{
+ {_T("add"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("or"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("addc"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("subc"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("and"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("sub"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("xor"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("cmp"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }
+};
+
+static const I386_OPCODE immw_table[8] =
+{
+ {_T("add"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("or"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("addc"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("subc"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("and"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("sub"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("xor"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("cmp"), 0, PARAM_RMPTR16, PARAM_IMM, 0 }
+};
+
+static const I386_OPCODE immws_table[8] =
+{
+ {_T("add"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("or"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("addc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("subc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("and"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("sub"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("xor"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("cmp"), 0, PARAM_RMPTR16, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftbi_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("ror"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("shl"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("shr"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("???"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("shra"), 0, PARAM_RMPTR8, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftwi_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("ror"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("shl"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("shr"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("???"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("shra"), 0, PARAM_RMPTR16, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftb_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("ror"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("shl"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("shr"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("???"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("shra"), 0, PARAM_RMPTR8, PARAM_1, 0 }
+};
+
+static const I386_OPCODE shiftw_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("ror"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("shl"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("shr"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("???"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("shra"), 0, PARAM_RMPTR16, PARAM_1, 0 }
+};
+
+static const I386_OPCODE shiftbv_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("ror"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("shl"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("shr"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("???"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("shra"), 0, PARAM_RMPTR8, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE shiftwv_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("ror"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("shl"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("shr"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("???"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("shra"), 0, PARAM_RMPTR16, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE group1b_table[8] =
+{
+ {_T("test"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("not"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("neg"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("mulu"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("mul"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("divu"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("div"), 0, PARAM_RMPTR8, 0, 0 }
+};
+
+static const I386_OPCODE group1w_table[8] =
+{
+ {_T("test"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("not"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("neg"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("mulu"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("mul"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("divu"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("div"), 0, PARAM_RMPTR16, 0, 0 }
+};
+
+static const I386_OPCODE group2b_table[8] =
+{
+ {_T("inc"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("dec"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group2w_table[8] =
+{
+ {_T("inc"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("dec"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("call"), 0, PARAM_RMPTR16, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("call far ptr "),0, PARAM_RM16, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("br"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("br far ptr "),0, PARAM_RM16, 0, 0 },
+ {_T("push"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 }
+};
+
+static const GROUP_OP group_op_table[] =
+{
+ {_T("immb"), immb_table },
+ {_T("immw"), immw_table },
+ {_T("immws"), immws_table },
+ {_T("shiftbi"), shiftbi_table },
+ {_T("shiftwi"), shiftwi_table },
+ {_T("shiftb"), shiftb_table },
+ {_T("shiftw"), shiftw_table },
+ {_T("shiftbv"), shiftbv_table },
+ {_T("shiftwv"), shiftwv_table },
+ {_T("group1b"), group1b_table },
+ {_T("group1w"), group1w_table },
+ {_T("group2b"), group2b_table },
+ {_T("group2w"), group2w_table }
+};
+
+
+
+static const _TCHAR *const nec_reg[8] = { _T("aw"), _T("cw"), _T("dw"), _T("bw"), _T("sp"), _T("bp"), _T("ix"), _T("iy") };
+static const _TCHAR *const nec_reg8[8] = { _T("al"), _T("cl"), _T("dl"), _T("bl"), _T("ah"), _T("ch"), _T("dh"), _T("bh") };
+static const _TCHAR *const nec_sreg[8] = { _T("ds1"), _T("ps"), _T("ss"), _T("ds0"), _T("???"), _T("???"), _T("???"), _T("???") };
+static const _TCHAR *const nec_sfreg[256] =
+{
+ /* 0x00 */
+ _T("p0"), _T("pm0"), _T("pmc0"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("p1"), _T("pm1"), _T("pmc1"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x10 */
+ _T("p2"), _T("pm2"), _T("pmc2"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x20 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x30 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("pt"), _T("???"), _T("???"), _T("pmt"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x40 */
+ _T("intm"), _T("???"), _T("???"), _T("???"), _T("ems0"), _T("ems1"), _T("ems2"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("exic0"), _T("exic1"), _T("exic2"), _T("???"),
+ /* 0x50 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x60 */
+ _T("rxb0"), _T("???"), _T("txb0"), _T("???"), _T("???"), _T("srms0"), _T("stms0"), _T("???"),
+ _T("scm0"), _T("scc0"), _T("brg0"), _T("scs0"), _T("seic0"), _T("sric0"), _T("stic0"), _T("???"),
+ /* 0x70 */
+ _T("rxb1"), _T("???"), _T("txb1"), _T("???"), _T("???"), _T("srms1"), _T("stms1"), _T("???"),
+ _T("scm1"), _T("scc1"), _T("brg1"), _T("scs1"), _T("seic1"), _T("sric1"), _T("stic1"), _T("???"),
+ /* 0x80 */
+ _T("tm0"), _T("???"), _T("md0"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("tm1"), _T("???"), _T("md1"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x90 */
+ _T("tmc0"), _T("tmc1"), _T("???"), _T("???"), _T("tmms0"), _T("tmms1"), _T("tmms2"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("tmic0"), _T("tmic1"), _T("tmic2"), _T("???"),
+ /* 0xa0 */
+ _T("dmac0"), _T("dmam0"), _T("dmac1"), _T("dmam1"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("dic0"), _T("dic1"), _T("???"), _T("???"),
+ /* 0xb0 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0xc0 */
+ _T("sar0l"), _T("sar0m"), _T("sar0h"), _T("???"), _T("dar0l"), _T("dar0m"), _T("dar0h"), _T("???"),
+ _T("tc0l"), _T("tc0h"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0xd0 */
+ _T("sar1l"), _T("sar1m"), _T("sar1h"), _T("???"), _T("dar1l"), _T("dar1m"), _T("dar1h"), _T("???"),
+ _T("tc1l"), _T("tc1h"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0xe0 */
+ _T("stbc"), _T("rfm"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("wtc"), _T("???"), _T("flag"), _T("prc"), _T("tbic"), _T("???"), _T("???"), _T("irqs"),
+ /* 0xf0 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("ispr"), _T("???"), _T("???"), _T("idb")
+};
+
+static UINT32 pc;
+static UINT8 modrm;
+static UINT32 segment;
+static offs_t dasm_flags;
+static _TCHAR modrm_string[256];
+
+#define MODRM_REG1 ((modrm >> 3) & 0x7)
+#define MODRM_REG2 (modrm & 0x7)
+
+#define MAX_LENGTH 8
+
+INLINE UINT8 FETCHD(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > MAX_LENGTH)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCHD16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > MAX_LENGTH)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+static _TCHAR *hexstring(UINT32 value, int digits)
+{
+ static _TCHAR buffer[20];
+ buffer[0] = _T('0');
+ if (digits) {
+ _stprintf(&buffer[1], _T("%0*Xh"), digits, value);
+ } else {
+ _stprintf(&buffer[1], _T("%Xh"), value);
+ }
+ return (buffer[1] >= _T('0') && buffer[1] <= _T('9')) ? &buffer[1] : &buffer[0];
+}
+
+static _TCHAR *shexstring(UINT32 value, int digits, int always)
+{
+ static _TCHAR buffer[20];
+ if (value >= 0x80000000) {
+ _stprintf(buffer, _T("-%s"), hexstring(-value, digits));
+ } else if (always) {
+ _stprintf(buffer, _T("+%s"), hexstring(value, digits));
+ } else {
+ return hexstring(value, digits);
+ }
+ return buffer;
+}
+
+static void handle_modrm(_TCHAR* s)
+{
+ INT8 disp8;
+ INT16 disp16;
+ UINT8 mod, rm;
+
+ modrm = FETCHD();
+ mod = (modrm >> 6) & 0x3;
+ rm = (modrm & 0x7);
+
+ if( modrm >= 0xc0 )
+ return;
+
+ switch(segment)
+ {
+ case SEG_PS: s += _stprintf( s, _T("ps:") ); break;
+ case SEG_DS0: s += _stprintf( s, _T("ds0:") ); break;
+ case SEG_DS1: s += _stprintf( s, _T("ds1:") ); break;
+ case SEG_SS: s += _stprintf( s, _T("ss:") ); break;
+ }
+
+ s += _stprintf( s, _T("[") );
+ switch( rm )
+ {
+ case 0: s += _stprintf( s, _T("bw+ix") ); break;
+ case 1: s += _stprintf( s, _T("bw+iy") ); break;
+ case 2: s += _stprintf( s, _T("bp+ix") ); break;
+ case 3: s += _stprintf( s, _T("bp+iy") ); break;
+ case 4: s += _stprintf( s, _T("ix") ); break;
+ case 5: s += _stprintf( s, _T("iy") ); break;
+ case 6:
+ if( mod == 0 ) {
+ disp16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), hexstring((unsigned) (UINT16) disp16, 0) );
+ } else {
+ s += _stprintf( s, _T("bp") );
+ }
+ break;
+ case 7: s += _stprintf( s, _T("bw") ); break;
+ }
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ s += _stprintf( s, _T("%s"), shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), shexstring((INT32)disp16, 0, TRUE) );
+ }
+ s += _stprintf( s, _T("]") );
+}
+
+static _TCHAR* handle_param(_TCHAR* s, UINT32 param)
+{
+ UINT8 i8;
+ UINT16 i16;
+ UINT16 ptr;
+ UINT32 addr;
+ INT8 d8;
+ INT16 d16;
+
+ switch(param)
+ {
+ case PARAM_REG8:
+ s += _stprintf( s, _T("%s"), nec_reg8[MODRM_REG1] );
+ break;
+
+ case PARAM_REG16:
+ s += _stprintf( s, _T("%s"), nec_reg[MODRM_REG1] );
+ break;
+
+ case PARAM_REG2_8:
+ s += _stprintf( s, _T("%s"), nec_reg8[MODRM_REG2] );
+ break;
+
+ case PARAM_REG2_16:
+ s += _stprintf( s, _T("%s"), nec_reg[MODRM_REG2] );
+ break;
+
+ case PARAM_RM8:
+ case PARAM_RMPTR8:
+ if( modrm >= 0xc0 ) {
+ s += _stprintf( s, _T("%s"), nec_reg8[MODRM_REG2] );
+ } else {
+ if (param == PARAM_RMPTR8)
+ s += _stprintf( s, _T("byte ptr ") );
+ s += _stprintf( s, _T("%s"), modrm_string );
+ }
+ break;
+
+ case PARAM_RM16:
+ case PARAM_RMPTR16:
+ if( modrm >= 0xc0 ) {
+ s += _stprintf( s, _T("%s"), nec_reg[MODRM_REG2] );
+ } else {
+ if (param == PARAM_RMPTR16)
+ s += _stprintf( s, _T("word ptr ") );
+ s += _stprintf( s, _T("%s"), modrm_string );
+ }
+ break;
+
+ case PARAM_I3:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%d"), i8 & 0x07 );
+ break;
+
+ case PARAM_I4:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%d"), i8 & 0x0f );
+ break;
+
+ case PARAM_I8:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%s"), shexstring((INT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_I16:
+ i16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), shexstring((INT16)i16, 0, FALSE) );
+ break;
+
+ case PARAM_UI8:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%s"), shexstring((UINT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_IMM:
+ i16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), hexstring(i16, 0) );
+ break;
+
+ case PARAM_ADDR:
+ addr = FETCHD16();
+ ptr = FETCHD16();
+ s += _stprintf( s, _T("%s:"), hexstring(ptr, 4) );
+ s += _stprintf( s, _T("%s"), hexstring(addr, 0) );
+ break;
+
+ case PARAM_REL16:
+ /* make sure to keep the relative offset within the segment */
+ d16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), hexstring((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF), 0) );
+ break;
+
+ case PARAM_REL8:
+ d8 = FETCHD();
+ s += _stprintf( s, _T("%s"), hexstring(pc + d8, 0) );
+ break;
+
+ case PARAM_MEM_OFFS:
+ switch(segment)
+ {
+ case SEG_PS: s += _stprintf( s, _T("ps:") ); break;
+ case SEG_DS0: s += _stprintf( s, _T("ds0:") ); break;
+ case SEG_DS1: s += _stprintf( s, _T("ds1:") ); break;
+ case SEG_SS: s += _stprintf( s, _T("ss:") ); break;
+ }
+
+ i16 = FETCHD16();
+ s += _stprintf( s, _T("[%s]"), hexstring(i16, 0) );
+ break;
+
+ case PARAM_SREG:
+ s += _stprintf( s, _T("%s"), nec_sreg[MODRM_REG1] );
+ break;
+
+ case PARAM_SFREG:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%s"), nec_sfreg[i8] );
+ break;
+
+ case PARAM_1:
+ s += _stprintf( s, _T("1") );
+ break;
+
+ case PARAM_AL: s += _stprintf( s, _T("al") ); break;
+ case PARAM_CL: s += _stprintf( s, _T("cl") ); break;
+ case PARAM_DL: s += _stprintf( s, _T("dl") ); break;
+ case PARAM_BL: s += _stprintf( s, _T("bl") ); break;
+ case PARAM_AH: s += _stprintf( s, _T("ah") ); break;
+ case PARAM_CH: s += _stprintf( s, _T("ch") ); break;
+ case PARAM_DH: s += _stprintf( s, _T("dh") ); break;
+ case PARAM_BH: s += _stprintf( s, _T("bh") ); break;
+
+ case PARAM_AW: s += _stprintf( s, _T("aw") ); break;
+ case PARAM_CW: s += _stprintf( s, _T("cw") ); break;
+ case PARAM_DW: s += _stprintf( s, _T("dw") ); break;
+ case PARAM_BW: s += _stprintf( s, _T("bw") ); break;
+ case PARAM_SP: s += _stprintf( s, _T("sp") ); break;
+ case PARAM_BP: s += _stprintf( s, _T("bp") ); break;
+ case PARAM_IX: s += _stprintf( s, _T("ix") ); break;
+ case PARAM_IY: s += _stprintf( s, _T("iy") ); break;
+ }
+ return s;
+}
+
+static void handle_fpu(_TCHAR *s, UINT8 op1, UINT8 op2)
+{
+ switch (op1 & 0x7)
+ {
+ case 0: // Group D8
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fadd dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fmul dword ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("fcom dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fcomp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fsub dword ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fsubr dword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fdiv dword ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fdivr dword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fadd st(0),st(%d)"), op2 & 0x7); break;
+ case 1: _stprintf(s, _T("fcom st(0),st(%d)"), op2 & 0x7); break;
+ case 2: _stprintf(s, _T("fsub st(0),st(%d)"), op2 & 0x7); break;
+ case 3: _stprintf(s, _T("fdiv st(0),st(%d)"), op2 & 0x7); break;
+ case 4: _stprintf(s, _T("fmul st(0),st(%d)"), op2 & 0x7); break;
+ case 5: _stprintf(s, _T("fcomp st(0),st(%d)"), op2 & 0x7); break;
+ case 6: _stprintf(s, _T("fsubr st(0),st(%d)"), op2 & 0x7); break;
+ case 7: _stprintf(s, _T("fdivr st(0),st(%d)"), op2 & 0x7); break;
+ }
+ }
+ break;
+ }
+
+ case 1: // Group D9
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fld dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fst dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fstp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fldenv word ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fldcw word ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fstenv word ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fstcw word ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fld st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fxch st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x10: _stprintf(s, _T("fnop")); break;
+ case 0x20: _stprintf(s, _T("fchs")); break;
+ case 0x21: _stprintf(s, _T("fabs")); break;
+ case 0x24: _stprintf(s, _T("ftst")); break;
+ case 0x25: _stprintf(s, _T("fxam")); break;
+ case 0x28: _stprintf(s, _T("fld1")); break;
+ case 0x29: _stprintf(s, _T("fldl2t")); break;
+ case 0x2a: _stprintf(s, _T("fldl2e")); break;
+ case 0x2b: _stprintf(s, _T("fldpi")); break;
+ case 0x2c: _stprintf(s, _T("fldlg2")); break;
+ case 0x2d: _stprintf(s, _T("fldln2")); break;
+ case 0x2e: _stprintf(s, _T("fldz")); break;
+ case 0x30: _stprintf(s, _T("f2xm1")); break;
+ case 0x31: _stprintf(s, _T("fyl2x")); break;
+ case 0x32: _stprintf(s, _T("fptan")); break;
+ case 0x33: _stprintf(s, _T("fpatan")); break;
+ case 0x34: _stprintf(s, _T("fxtract")); break;
+ case 0x35: _stprintf(s, _T("fprem1")); break;
+ case 0x36: _stprintf(s, _T("fdecstp")); break;
+ case 0x37: _stprintf(s, _T("fincstp")); break;
+ case 0x38: _stprintf(s, _T("fprem")); break;
+ case 0x39: _stprintf(s, _T("fyl2xp1")); break;
+ case 0x3a: _stprintf(s, _T("fsqrt")); break;
+ case 0x3b: _stprintf(s, _T("fsincos")); break;
+ case 0x3c: _stprintf(s, _T("frndint")); break;
+ case 0x3d: _stprintf(s, _T("fscale")); break;
+ case 0x3e: _stprintf(s, _T("fsin")); break;
+ case 0x3f: _stprintf(s, _T("fcos")); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 2: // Group DA
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fiadd dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fimul dword ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("ficom dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("ficomp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fisub dword ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fisubr dword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fidiv dword ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fidivr dword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fcmovb st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fcmove st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ _stprintf(s, _T("fcmovbe st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ _stprintf(s, _T("fcmovu st(0),st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+
+ }
+ }
+ break;
+ }
+
+ case 3: // Group DB
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fild dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fist dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fistp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("??? (FPU)")); break;
+ case 5: _stprintf(s, _T("fld tword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("??? (FPU)")); break;
+ case 7: _stprintf(s, _T("fstp tword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fcmovnb st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fcmovne st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ _stprintf(s, _T("fcmovnbe st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ _stprintf(s, _T("fcmovnu st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x22: _stprintf(s, _T("fclex")); break;
+ case 0x23: _stprintf(s, _T("finit")); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fucomi st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fcomi st(0),st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 4: // Group DC
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fadd qword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fmul qword ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("fcom qword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fcomp qword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fsub qword ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fsubr qword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fdiv qword ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fdivr qword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fadd st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fmul st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ _stprintf(s, _T("fsubr st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fsub st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fdivr st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ _stprintf(s, _T("fdiv st(%d),st(0)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 5: // Group DD
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fld qword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fst qword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fstp qword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("frstor %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("??? (FPU)")); break;
+ case 6: _stprintf(s, _T("fsave %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fstsw word ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("ffree st(%d)"), op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ _stprintf(s, _T("fst st(%d)"), op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ _stprintf(s, _T("fstp st(%d)"), op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ _stprintf(s, _T("fucom st(%d), st(0)"), op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fucomp st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 6: // Group DE
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fiadd word ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fimul word ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("ficom word ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("ficomp word ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fisub word ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fisubr word ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fidiv word ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fidivr word ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("faddp st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fmulp st(%d)"), op2 & 0x7); break;
+
+ case 0x19: _stprintf(s, _T("fcompp")); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ _stprintf(s, _T("fsubrp st(%d)"), op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fsubp st(%d)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fdivrp st(%d), st(0)"), op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ _stprintf(s, _T("fdivp st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 7: // Group DF
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fild word ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fist word ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fistp word ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fbld %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fild qword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fbstp %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fistp qword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x20: _stprintf(s, _T("fstsw aw")); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fucomip st(%d)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fcomip st(%d),st(0)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void decode_opcode(_TCHAR *s, const I386_OPCODE *op, UINT8 op1 )
+{
+ int i;
+ UINT8 op2;
+
+ switch( op->flags )
+ {
+ case TWO_BYTE:
+ op2 = FETCHD();
+ decode_opcode( s, &necv_opcode_table2[op2], op1 );
+ return;
+
+ case SEG_PS:
+ case SEG_DS0:
+ case SEG_DS1:
+ case SEG_SS:
+ segment = op->flags;
+ op2 = FETCHD();
+ decode_opcode( s, &necv_opcode_table1[op2], op1 );
+ return;
+
+ case PREFIX:
+ s += _stprintf( s, _T("%-8s"), op->mnemonic );
+ op2 = FETCHD();
+ decode_opcode( s, &necv_opcode_table1[op2], op1 );
+ return;
+
+ case GROUP:
+ handle_modrm( modrm_string );
+ for( i=0; i < ARRAY_LENGTH(group_op_table); i++ ) {
+ if( _tcscmp(op->mnemonic, group_op_table[i].mnemonic) == 0 )
+ {
+ decode_opcode( s, &group_op_table[i].opcode[MODRM_REG1], op1 );
+ return;
+ }
+ }
+ goto handle_unknown;
+
+ case FPU:
+ op2 = FETCHD();
+ handle_fpu( s, op1, op2);
+ return;
+
+ case MODRM:
+ handle_modrm( modrm_string );
+ break;
+ }
+
+ s += _stprintf( s, _T("%-8s"), op->mnemonic );
+ dasm_flags = op->dasm_flags;
+
+ if( op->param1 != 0 ) {
+ s = handle_param( s, op->param1 );
+ }
+
+ if( op->param2 != 0 ) {
+ s += _stprintf( s, _T(",") );
+ s = handle_param( s, op->param2 );
+ }
+
+ if( op->param3 != 0 ) {
+ s += _stprintf( s, _T(",") );
+ s = handle_param( s, op->param3 );
+ }
+ return;
+
+handle_unknown:
+ _stprintf(s, _T("???"));
+}
+
+int necv_dasm_one(_TCHAR *buffer, UINT32 eip, const UINT8 *oprom)
+{
+ UINT8 op;
+
+ opcode_ptr = opcode_ptr_base = oprom;
+ pc = eip;
+ dasm_flags = 0;
+ segment = 0;
+
+ op = FETCHD();
+
+ decode_opcode( buffer, &necv_opcode_table1[op], op );
+ return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED;
+}
+
+#define STATE_VERSION 1
+
+void I86::save_state(FILEIO* state_fio)
+{
+ state_fio->FputUint32(STATE_VERSION);
+ state_fio->FputInt32(this_device_id);
+
+ state_fio->Fwrite(®s, sizeof(regs), 1);
+ state_fio->FputUint32(pc);
+ state_fio->FputUint32(prevpc);
+ state_fio->Fwrite(base, sizeof(base), 1);
+ state_fio->Fwrite(sregs, sizeof(sregs), 1);
+ state_fio->FputUint16(flags);
+ state_fio->FputInt32(AuxVal);
+ state_fio->FputInt32(OverVal);
+ state_fio->FputInt32(SignVal);
+ state_fio->FputInt32(ZeroVal);
+ state_fio->FputInt32(CarryVal);
+ state_fio->FputInt32(DirVal);
+ state_fio->FputUint8(ParityVal);
+ state_fio->FputUint8(TF);
+ state_fio->FputUint8(IF);
+ state_fio->FputUint8(MF);
+ state_fio->FputInt32(int_state);
+ state_fio->FputBool(test_state);
+ state_fio->FputBool(busreq);
+ state_fio->FputBool(halted);
+ state_fio->FputInt32(icount);
+ state_fio->FputInt32(extra_icount);
+ state_fio->FputBool(seg_prefix);
+ state_fio->FputUint8(prefix_seg);
+ state_fio->FputUint32(ea);
+ state_fio->FputUint16(eo);
+ state_fio->FputUint8(ea_seg);
+}
+
+bool I86::load_state(FILEIO* state_fio)
+{
+ if(state_fio->FgetUint32() != STATE_VERSION) {
+ return false;
+ }
+ if(state_fio->FgetInt32() != this_device_id) {
+ return false;
+ }
+ state_fio->Fread(®s, sizeof(regs), 1);
+ pc = state_fio->FgetUint32();
+ prevpc = state_fio->FgetUint32();
+ state_fio->Fread(base, sizeof(base), 1);
+ state_fio->Fread(sregs, sizeof(sregs), 1);
+ flags = state_fio->FgetUint16();
+ AuxVal = state_fio->FgetInt32();
+ OverVal = state_fio->FgetInt32();
+ SignVal = state_fio->FgetInt32();
+ ZeroVal = state_fio->FgetInt32();
+ CarryVal = state_fio->FgetInt32();
+ DirVal = state_fio->FgetInt32();
+ ParityVal = state_fio->FgetUint8();
+ TF = state_fio->FgetUint8();
+ IF = state_fio->FgetUint8();
+ MF = state_fio->FgetUint8();
+ int_state = state_fio->FgetInt32();
+ test_state = state_fio->FgetBool();
+ busreq = state_fio->FgetBool();
+ halted = state_fio->FgetBool();
+ icount = state_fio->FgetInt32();
+ extra_icount = state_fio->FgetInt32();
+ seg_prefix = state_fio->FgetBool();
+ prefix_seg = state_fio->FgetUint8();
+ ea = state_fio->FgetUint32();
+ eo = state_fio->FgetUint16();
+ ea_seg = state_fio->FgetUint8();
+ return true;
+}
+
--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Origin : MAME 0.142
+ Author : Takeda.Toshiya
+ Date : 2011.04.23-
+
+ [ 80x86 ]
+*/
+
+#ifndef _I86_H_
+#define _I86_H_
+
+#include "vm.h"
+#include "../emu.h"
+#include "device.h"
+
+#define SIG_I86_TEST 0
+
+#ifdef USE_DEBUGGER
+class DEBUGGER;
+#endif
+
+class I86 : public DEVICE
+{
+private:
+ /* ---------------------------------------------------------------------------
+ contexts
+ --------------------------------------------------------------------------- */
+
+ DEVICE *d_mem, *d_io, *d_pic, *d_bios;
+#ifdef SINGLE_MODE_DMA
+ DEVICE *d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ DEBUGGER *d_debugger;
+ DEVICE *d_mem_stored, *d_io_stored;
+#endif
+
+ /* ---------------------------------------------------------------------------
+ registers
+ --------------------------------------------------------------------------- */
+
+ union REGTYPE {
+ uint16_t w[8]; /* viewed as 16 bits registers */
+ uint8_t b[16]; /* or as 8 bit registers */
+ } regs;
+ uint32_t pc;
+ uint32_t prevpc;
+ uint32_t base[4];
+ uint16_t sregs[4];
+ uint16_t flags;
+ int32_t AuxVal, OverVal, SignVal, ZeroVal, CarryVal, DirVal;
+ uint8_t ParityVal;
+ uint8_t TF, IF, MF;
+
+ int int_state;
+ bool test_state;
+ bool busreq, halted;
+
+ int icount;
+ int extra_icount;
+
+ bool seg_prefix; /* prefix segment indicator */
+ uint8_t prefix_seg; /* The prefixed segment */
+ unsigned ea;
+ uint16_t eo; /* effective offset of the address (before segment is added) */
+ uint8_t ea_seg; /* effective segment of the address */
+
+ /* ---------------------------------------------------------------------------
+ opecode
+ --------------------------------------------------------------------------- */
+
+ // sub
+ void interrupt(int num);
+ void trap();
+ unsigned GetEA(unsigned ModRM);
+ void rotate_shift_byte(unsigned ModRM, unsigned cnt);
+ void rotate_shift_word(unsigned ModRM, unsigned cnt);
+
+ // opecode
+ void run_one_opecode();
+#ifdef USE_DEBUGGER
+ void run_one_opecode_debugger();
+#endif
+ void instruction(uint8_t code);
+ inline void _add_br8();
+ inline void _add_wr16();
+ inline void _add_r8b();
+ inline void _add_r16w();
+ inline void _add_ald8();
+ inline void _add_axd16();
+ inline void _push_es();
+ inline void _pop_es();
+ inline void _or_br8();
+ inline void _or_wr16();
+ inline void _or_r8b();
+ inline void _or_r16w();
+ inline void _or_ald8();
+ inline void _or_axd16();
+ inline void _push_cs();
+#if defined(HAS_V30)
+ inline void _0fpre();
+#endif
+ inline void _adc_br8();
+ inline void _adc_wr16();
+ inline void _adc_r8b();
+ inline void _adc_r16w();
+ inline void _adc_ald8();
+ inline void _adc_axd16();
+ inline void _push_ss();
+ inline void _pop_ss();
+ inline void _sbb_br8();
+ inline void _sbb_wr16();
+ inline void _sbb_r8b();
+ inline void _sbb_r16w();
+ inline void _sbb_ald8();
+ inline void _sbb_axd16();
+ inline void _push_ds();
+ inline void _pop_ds();
+ inline void _and_br8();
+ inline void _and_wr16();
+ inline void _and_r8b();
+ inline void _and_r16w();
+ inline void _and_ald8();
+ inline void _and_axd16();
+ inline void _es();
+ inline void _daa();
+ inline void _sub_br8();
+ inline void _sub_wr16();
+ inline void _sub_r8b();
+ inline void _sub_r16w();
+ inline void _sub_ald8();
+ inline void _sub_axd16();
+ inline void _cs();
+ inline void _das();
+ inline void _xor_br8();
+ inline void _xor_wr16();
+ inline void _xor_r8b();
+ inline void _xor_r16w();
+ inline void _xor_ald8();
+ inline void _xor_axd16();
+ inline void _ss();
+ inline void _aaa();
+ inline void _cmp_br8();
+ inline void _cmp_wr16();
+ inline void _cmp_r8b();
+ inline void _cmp_r16w();
+ inline void _cmp_ald8();
+ inline void _cmp_axd16();
+ inline void _ds();
+ inline void _aas();
+ inline void _inc_ax();
+ inline void _inc_cx();
+ inline void _inc_dx();
+ inline void _inc_bx();
+ inline void _inc_sp();
+ inline void _inc_bp();
+ inline void _inc_si();
+ inline void _inc_di();
+ inline void _dec_ax();
+ inline void _dec_cx();
+ inline void _dec_dx();
+ inline void _dec_bx();
+ inline void _dec_sp();
+ inline void _dec_bp();
+ inline void _dec_si();
+ inline void _dec_di();
+ inline void _push_ax();
+ inline void _push_cx();
+ inline void _push_dx();
+ inline void _push_bx();
+ inline void _push_sp();
+ inline void _push_bp();
+ inline void _push_si();
+ inline void _push_di();
+ inline void _pop_ax();
+ inline void _pop_cx();
+ inline void _pop_dx();
+ inline void _pop_bx();
+ inline void _pop_sp();
+ inline void _pop_bp();
+ inline void _pop_si();
+ inline void _pop_di();
+ inline void _pusha();
+ inline void _popa();
+ inline void _bound();
+ inline void _repc(int flagval);
+ inline void _push_d16();
+ inline void _imul_d16();
+ inline void _push_d8();
+ inline void _imul_d8();
+ inline void _insb();
+ inline void _insw();
+ inline void _outsb();
+ inline void _outsw();
+ inline void _jo();
+ inline void _jno();
+ inline void _jb();
+ inline void _jnb();
+ inline void _jz();
+ inline void _jnz();
+ inline void _jbe();
+ inline void _jnbe();
+ inline void _js();
+ inline void _jns();
+ inline void _jp();
+ inline void _jnp();
+ inline void _jl();
+ inline void _jnl();
+ inline void _jle();
+ inline void _jnle();
+ inline void _80pre();
+ inline void _81pre();
+ inline void _82pre();
+ inline void _83pre();
+ inline void _test_br8();
+ inline void _test_wr16();
+ inline void _xchg_br8();
+ inline void _xchg_wr16();
+ inline void _mov_br8();
+ inline void _mov_wr16();
+ inline void _mov_r8b();
+ inline void _mov_r16w();
+ inline void _mov_wsreg();
+ inline void _lea();
+ inline void _mov_sregw();
+ inline void _popw();
+ inline void _nop();
+ inline void _xchg_axcx();
+ inline void _xchg_axdx();
+ inline void _xchg_axbx();
+ inline void _xchg_axsp();
+ inline void _xchg_axbp();
+ inline void _xchg_axsi();
+ inline void _xchg_axdi();
+ inline void _cbw();
+ inline void _cwd();
+ inline void _call_far();
+ inline void _wait();
+ inline void _pushf();
+ inline void _popf();
+ inline void _sahf();
+ inline void _lahf();
+ inline void _mov_aldisp();
+ inline void _mov_axdisp();
+ inline void _mov_dispal();
+ inline void _mov_dispax();
+ inline void _movsb();
+ inline void _movsw();
+ inline void _cmpsb();
+ inline void _cmpsw();
+ inline void _test_ald8();
+ inline void _test_axd16();
+ inline void _stosb();
+ inline void _stosw();
+ inline void _lodsb();
+ inline void _lodsw();
+ inline void _scasb();
+ inline void _scasw();
+ inline void _mov_ald8();
+ inline void _mov_cld8();
+ inline void _mov_dld8();
+ inline void _mov_bld8();
+ inline void _mov_ahd8();
+ inline void _mov_chd8();
+ inline void _mov_dhd8();
+ inline void _mov_bhd8();
+ inline void _mov_axd16();
+ inline void _mov_cxd16();
+ inline void _mov_dxd16();
+ inline void _mov_bxd16();
+ inline void _mov_spd16();
+ inline void _mov_bpd16();
+ inline void _mov_sid16();
+ inline void _mov_did16();
+ inline void _rotshft_bd8();
+ inline void _rotshft_wd8();
+ inline void _ret_d16();
+ inline void _ret();
+ inline void _les_dw();
+ inline void _lds_dw();
+ inline void _mov_bd8();
+ inline void _mov_wd16();
+ inline void _enter();
+ inline void _leav(); // _leave()
+ inline void _retf_d16();
+ inline void _retf();
+ inline void _int3();
+ inline void _int();
+ inline void _into();
+ inline void _iret();
+ inline void _rotshft_b();
+ inline void _rotshft_w();
+ inline void _rotshft_bcl();
+ inline void _rotshft_wcl();
+ inline void _aam();
+ inline void _aad();
+ inline void _setalc();
+ inline void _xlat();
+ inline void _escape();
+ inline void _loopne();
+ inline void _loope();
+ inline void _loop();
+ inline void _jcxz();
+ inline void _inal();
+ inline void _inax();
+ inline void _outal();
+ inline void _outax();
+ inline void _call_d16();
+ inline void _jmp_d16();
+ inline void _jmp_far();
+ inline void _jmp_d8();
+ inline void _inaldx();
+ inline void _inaxdx();
+ inline void _outdxal();
+ inline void _outdxax();
+ inline void _lock();
+ inline void _rep(int flagval);
+ inline void _repne();
+ inline void _repe();
+ inline void _hlt();
+ inline void _cmc();
+ inline void _f6pre();
+ inline void _f7pre();
+ inline void _clc();
+ inline void _stc();
+ inline void _cli();
+ inline void _sti();
+ inline void _cld();
+ inline void _std();
+ inline void _fepre();
+ inline void _ffpre();
+ inline void _invalid();
+
+public:
+ I86(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ d_bios = NULL;
+#ifdef SINGLE_MODE_DMA
+ d_dma = NULL;
+#endif
+ busreq = false;
+#if defined(HAS_I86)
+ set_device_name(_T("i8086 CPU"));
+#else
+ set_device_name(_T("i80186 CPU"));
+#endif
+ }
+ ~I86() {}
+
+ // common functions
+ void initialize();
+ void reset();
+ int run(int clock);
+ void write_signal(int id, uint32_t data, uint32_t mask);
+ void set_intr_line(bool line, bool pending, uint32_t bit);
+ void set_extra_clock(int clock)
+ {
+ extra_icount += clock;
+ }
+ int get_extra_clock()
+ {
+ return extra_icount;
+ }
+ uint32_t get_pc()
+ {
+ return prevpc;
+ }
+ uint32_t get_next_pc()
+ {
+ return pc;
+ }
+#ifdef USE_DEBUGGER
+ void *get_debugger()
+ {
+ return d_debugger;
+ }
+ uint32_t get_debug_prog_addr_mask()
+ {
+ return 0xfffff;
+ }
+ uint32_t get_debug_data_addr_mask()
+ {
+ return 0xfffff;
+ }
+ void write_debug_data8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data8(uint32_t addr);
+ void write_debug_data16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data16(uint32_t addr);
+ void write_debug_io8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io8(uint32_t addr);
+ void write_debug_io16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io16(uint32_t addr);
+ bool write_debug_reg(const _TCHAR *reg, uint32_t data);
+ void get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
+ int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len);
+#endif
+ void save_state(FILEIO* state_fio);
+ bool load_state(FILEIO* state_fio);
+
+ // unique function
+ void set_context_mem(DEVICE* device)
+ {
+ d_mem = device;
+ }
+ void set_context_io(DEVICE* device)
+ {
+ d_io = device;
+ }
+ void set_context_intr(DEVICE* device)
+ {
+ d_pic = device;
+ }
+ void set_context_bios(DEVICE* device)
+ {
+ d_bios = device;
+ }
+#ifdef SINGLE_MODE_DMA
+ void set_context_dma(DEVICE* device)
+ {
+ d_dma = device;
+ }
+#endif
+#ifdef USE_DEBUGGER
+ void set_context_debugger(DEBUGGER* device)
+ {
+ d_debugger = device;
+ }
+#endif
+};
+
+#endif
--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Origin : MAME 0.142
+ Author : Takeda.Toshiya
+ Date : 2011.04.23-
+
+ [ i86/v30 ]
+*/
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#pragma warning( disable : 4146 )
+#pragma warning( disable : 4996 )
+#endif
+
+#include "i86.h"
+#ifdef USE_DEBUGGER
+#include "debugger.h"
+#endif
+
+#define DIVIDE_FAULT 0
+#define NMI_INT_VECTOR 2
+#define OVERFLOW_TRAP 4
+#define BOUNDS_CHECK_FAULT 5
+#define ILLEGAL_INSTRUCTION 6
+#define GENERAL_PROTECTION_FAULT 13
+
+#define INT_REQ_BIT 1
+#define NMI_REQ_BIT 2
+
+typedef enum { ES, CS, SS, DS } SREGS;
+typedef enum { AX, CX, DX, BX, SP, BP, SI, DI } WREGS;
+
+typedef enum {
+#ifdef __BIG_ENDIAN__
+ AH, AL, CH, CL, DH, DL, BH, BL,
+ SPH, SPL, BPH, BPL, SIH, SIL, DIH, DIL,
+#else
+ AL, AH, CL, CH, DL, DH, BL, BH,
+ SPL, SPH, BPL, BPH, SIL, SIH, DIL, DIH,
+#endif
+} BREGS;
+
+static struct {
+ struct {
+ WREGS w[256];
+ BREGS b[256];
+ } reg;
+ struct {
+ WREGS w[256];
+ BREGS b[256];
+ } RM;
+} Mod_RM;
+
+static const uint8_t parity_table[256] = {
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+/************************************************************************/
+
+struct i80x86_timing {
+ uint8_t exception, iret; /* exception, IRET */
+ uint8_t int3, int_imm, into_nt, into_t; /* INTs */
+ uint8_t override; /* segment overrides */
+ uint8_t flag_ops, lahf, sahf; /* flag operations */
+ uint8_t aaa, aas, aam, aad; /* arithmetic adjusts */
+ uint8_t daa, das; /* decimal adjusts */
+ uint8_t cbw, cwd; /* sign extension */
+ uint8_t hlt, load_ptr, lea, nop, wait, xlat; /* misc */
+
+ uint8_t jmp_short, jmp_near, jmp_far; /* direct JMPs */
+ uint8_t jmp_r16, jmp_m16, jmp_m32; /* indirect JMPs */
+ uint8_t call_near, call_far; /* direct CALLs */
+ uint8_t call_r16, call_m16, call_m32; /* indirect CALLs */
+ uint8_t ret_near, ret_far, ret_near_imm, ret_far_imm; /* returns */
+ uint8_t jcc_nt, jcc_t, jcxz_nt, jcxz_t; /* conditional JMPs */
+ uint8_t loop_nt, loop_t, loope_nt, loope_t; /* loops */
+
+ uint8_t in_imm8, in_imm16, in_dx8, in_dx16; /* port reads */
+ uint8_t out_imm8, out_imm16, out_dx8, out_dx16; /* port writes */
+
+ uint8_t mov_rr8, mov_rm8, mov_mr8; /* move, 8-bit */
+ uint8_t mov_ri8, mov_mi8; /* move, 8-bit immediate */
+ uint8_t mov_rr16, mov_rm16, mov_mr16; /* move, 16-bit */
+ uint8_t mov_ri16, mov_mi16; /* move, 16-bit immediate */
+ uint8_t mov_am8, mov_am16, mov_ma8, mov_ma16; /* move, AL/AX memory */
+ uint8_t mov_sr, mov_sm, mov_rs, mov_ms; /* move, segment registers */
+ uint8_t xchg_rr8, xchg_rm8; /* exchange, 8-bit */
+ uint8_t xchg_rr16, xchg_rm16, xchg_ar16; /* exchange, 16-bit */
+
+ uint8_t push_r16, push_m16, push_seg, pushf; /* pushes */
+ uint8_t pop_r16, pop_m16, pop_seg, popf; /* pops */
+
+ uint8_t alu_rr8, alu_rm8, alu_mr8; /* ALU ops, 8-bit */
+ uint8_t alu_ri8, alu_mi8, alu_mi8_ro; /* ALU ops, 8-bit immediate */
+ uint8_t alu_rr16, alu_rm16, alu_mr16; /* ALU ops, 16-bit */
+ uint8_t alu_ri16, alu_mi16, alu_mi16_ro; /* ALU ops, 16-bit immediate */
+ uint8_t alu_r16i8, alu_m16i8, alu_m16i8_ro; /* ALU ops, 16-bit w/8-bit immediate */
+ uint8_t mul_r8, mul_r16, mul_m8, mul_m16; /* MUL */
+ uint8_t imul_r8, imul_r16, imul_m8, imul_m16; /* IMUL */
+ uint8_t div_r8, div_r16, div_m8, div_m16; /* DIV */
+ uint8_t idiv_r8, idiv_r16, idiv_m8, idiv_m16; /* IDIV */
+ uint8_t incdec_r8, incdec_r16, incdec_m8, incdec_m16; /* INC/DEC */
+ uint8_t negnot_r8, negnot_r16, negnot_m8, negnot_m16; /* NEG/NOT */
+
+ uint8_t rot_reg_1, rot_reg_base, rot_reg_bit; /* reg shift/rotate */
+ uint8_t rot_m8_1, rot_m8_base, rot_m8_bit; /* m8 shift/rotate */
+ uint8_t rot_m16_1, rot_m16_base, rot_m16_bit; /* m16 shift/rotate */
+
+ uint8_t cmps8, rep_cmps8_base, rep_cmps8_count; /* CMPS 8-bit */
+ uint8_t cmps16, rep_cmps16_base, rep_cmps16_count; /* CMPS 16-bit */
+ uint8_t scas8, rep_scas8_base, rep_scas8_count; /* SCAS 8-bit */
+ uint8_t scas16, rep_scas16_base, rep_scas16_count; /* SCAS 16-bit */
+ uint8_t lods8, rep_lods8_base, rep_lods8_count; /* LODS 8-bit */
+ uint8_t lods16, rep_lods16_base, rep_lods16_count; /* LODS 16-bit */
+ uint8_t stos8, rep_stos8_base, rep_stos8_count; /* STOS 8-bit */
+ uint8_t stos16, rep_stos16_base, rep_stos16_count; /* STOS 16-bit */
+ uint8_t movs8, rep_movs8_base, rep_movs8_count; /* MOVS 8-bit */
+ uint8_t movs16, rep_movs16_base, rep_movs16_count; /* MOVS 16-bit */
+
+ uint8_t ins8, rep_ins8_base, rep_ins8_count; /* (80186) INS 8-bit */
+ uint8_t ins16, rep_ins16_base, rep_ins16_count; /* (80186) INS 16-bit */
+ uint8_t outs8, rep_outs8_base, rep_outs8_count; /* (80186) OUTS 8-bit */
+ uint8_t outs16, rep_outs16_base, rep_outs16_count; /* (80186) OUTS 16-bit */
+ uint8_t push_imm, pusha, popa; /* (80186) PUSH immediate, PUSHA/POPA */
+ uint8_t imul_rri8, imul_rmi8; /* (80186) IMUL immediate 8-bit */
+ uint8_t imul_rri16, imul_rmi16; /* (80186) IMUL immediate 16-bit */
+ uint8_t enter0, enter1, enter_base, enter_count, leave; /* (80186) ENTER/LEAVE */
+ uint8_t bound; /* (80186) BOUND */
+};
+
+#if defined(HAS_I86)
+/* these come from the 8088 timings in OPCODE.LST, but with the
+ penalty for 16-bit memory accesses removed wherever possible */
+static const struct i80x86_timing timing = {
+ 51, 32, /* exception, IRET */
+ 2, 0, 4, 2, /* INTs */
+ 2, /* segment overrides */
+ 2, 4, 4, /* flag operations */
+ 4, 4, 83, 60, /* arithmetic adjusts */
+ 4, 4, /* decimal adjusts */
+ 2, 5, /* sign extension */
+ 2, 24, 2, 2, 3, 11, /* misc */
+
+ 15, 15, 15, /* direct JMPs */
+ 11, 18, 24, /* indirect JMPs */
+ 19, 28, /* direct CALLs */
+ 16, 21, 37, /* indirect CALLs */
+ 20, 32, 24, 31, /* returns */
+ 4, 16, 6, 18, /* conditional JMPs */
+ 5, 17, 6, 18, /* loops */
+
+ 10, 14, 8, 12, /* port reads */
+ 10, 14, 8, 12, /* port writes */
+
+ 2, 8, 9, /* move, 8-bit */
+ 4, 10, /* move, 8-bit immediate */
+ 2, 8, 9, /* move, 16-bit */
+ 4, 10, /* move, 16-bit immediate */
+ 10, 10, 10, 10, /* move, AL/AX memory */
+ 2, 8, 2, 9, /* move, segment registers */
+ 4, 17, /* exchange, 8-bit */
+ 4, 17, 3, /* exchange, 16-bit */
+
+ 15, 24, 14, 14, /* pushes */
+ 12, 25, 12, 12, /* pops */
+
+ 3, 9, 16, /* ALU ops, 8-bit */
+ 4, 17, 10, /* ALU ops, 8-bit immediate */
+ 3, 9, 16, /* ALU ops, 16-bit */
+ 4, 17, 10, /* ALU ops, 16-bit immediate */
+ 4, 17, 10, /* ALU ops, 16-bit w/8-bit immediate */
+ 70, 118, 76, 128, /* MUL */
+ 80, 128, 86, 138, /* IMUL */
+ 80, 144, 86, 154, /* DIV */
+ 101, 165, 107, 175, /* IDIV */
+ 3, 2, 15, 15, /* INC/DEC */
+ 3, 3, 16, 16, /* NEG/NOT */
+
+ 2, 8, 4, /* reg shift/rotate */
+ 15, 20, 4, /* m8 shift/rotate */
+ 15, 20, 4, /* m16 shift/rotate */
+
+ 22, 9, 21, /* CMPS 8-bit */
+ 22, 9, 21, /* CMPS 16-bit */
+ 15, 9, 14, /* SCAS 8-bit */
+ 15, 9, 14, /* SCAS 16-bit */
+ 12, 9, 11, /* LODS 8-bit */
+ 12, 9, 11, /* LODS 16-bit */
+ 11, 9, 10, /* STOS 8-bit */
+ 11, 9, 10, /* STOS 16-bit */
+ 18, 9, 17, /* MOVS 8-bit */
+ 18, 9, 17, /* MOVS 16-bit */
+};
+#else
+/* these come from the Intel 80186 datasheet */
+static const struct i80x86_timing timing = {
+ 45, 28, /* exception, IRET */
+ 0, 2, 4, 3, /* INTs */
+ 2, /* segment overrides */
+ 2, 2, 3, /* flag operations */
+ 8, 7, 19, 15, /* arithmetic adjusts */
+ 4, 4, /* decimal adjusts */
+ 2, 4, /* sign extension */
+ 2, 18, 6, 2, 6, 11, /* misc */
+
+ 14, 14, 14, /* direct JMPs */
+ 11, 17, 26, /* indirect JMPs */
+ 15, 23, /* direct CALLs */
+ 13, 19, 38, /* indirect CALLs */
+ 16, 22, 18, 25, /* returns */
+ 4, 13, 5, 15, /* conditional JMPs */
+ 6, 16, 6, 16, /* loops */
+
+ 10, 10, 8, 8, /* port reads */
+ 9, 9, 7, 7, /* port writes */
+
+ 2, 9, 12, /* move, 8-bit */
+ 3, 12, /* move, 8-bit immediate */
+ 2, 9, 12, /* move, 16-bit */
+ 4, 13, /* move, 16-bit immediate */
+ 8, 8, 9, 9, /* move, AL/AX memory */
+ 2, 11, 2, 11, /* move, segment registers */
+ 4, 17, /* exchange, 8-bit */
+ 4, 17, 3, /* exchange, 16-bit */
+
+ 10, 16, 9, 9, /* pushes */
+ 10, 20, 8, 8, /* pops */
+
+ 3, 10, 10, /* ALU ops, 8-bit */
+ 4, 16, 10, /* ALU ops, 8-bit immediate */
+ 3, 10, 10, /* ALU ops, 16-bit */
+ 4, 16, 10, /* ALU ops, 16-bit immediate */
+ 4, 16, 10, /* ALU ops, 16-bit w/8-bit immediate */
+ 26, 35, 32, 41, /* MUL */
+ 25, 34, 31, 40, /* IMUL */
+ 29, 38, 35, 44, /* DIV */
+ 44, 53, 50, 59, /* IDIV */
+ 3, 3, 15, 15, /* INC/DEC */
+ 3, 3, 10, 10, /* NEG/NOT */
+
+ 2, 5, 1, /* reg shift/rotate */
+ 15, 17, 1, /* m8 shift/rotate */
+ 15, 17, 1, /* m16 shift/rotate */
+
+ 22, 5, 22, /* CMPS 8-bit */
+ 22, 5, 22, /* CMPS 16-bit */
+ 15, 5, 15, /* SCAS 8-bit */
+ 15, 5, 15, /* SCAS 16-bit */
+ 12, 6, 11, /* LODS 8-bit */
+ 12, 6, 11, /* LODS 16-bit */
+ 10, 6, 9, /* STOS 8-bit */
+ 10, 6, 9, /* STOS 16-bit */
+ 14, 8, 8, /* MOVS 8-bit */
+ 14, 8, 8, /* MOVS 16-bit */
+
+ 14, 8, 8, /* (80186) INS 8-bit */
+ 14, 8, 8, /* (80186) INS 16-bit */
+ 14, 8, 8, /* (80186) OUTS 8-bit */
+ 14, 8, 8, /* (80186) OUTS 16-bit */
+ 14, 68, 83, /* (80186) PUSH immediate, PUSHA/POPA */
+ 22, 29, /* (80186) IMUL immediate 8-bit */
+ 25, 32, /* (80186) IMUL immediate 16-bit */
+ 15, 25, 4, 16, 8, /* (80186) ENTER/LEAVE */
+ 33, /* (80186) BOUND */
+};
+#endif
+
+/************************************************************************/
+
+#define SetTF(x) (TF = (x))
+#define SetIF(x) (IF = (x))
+#define SetDF(x) (DirVal = (x) ? -1 : 1)
+#define SetMD(x) (MF = (x))
+
+#define SetOFW_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x8000)
+#define SetOFB_Add(x, y, z) (OverVal = ((x) ^ (y)) & ((x) ^ (z)) & 0x80)
+#define SetOFW_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x8000)
+#define SetOFB_Sub(x, y, z) (OverVal = ((z) ^ (y)) & ((z) ^ (x)) & 0x80)
+
+#define SetCFB(x) (CarryVal = (x) & 0x100)
+#define SetCFW(x) (CarryVal = (x) & 0x10000)
+#define SetAF(x, y, z) (AuxVal = ((x) ^ ((y) ^ (z))) & 0x10)
+#define SetSF(x) (SignVal = (x))
+#define SetZF(x) (ZeroVal = (x))
+#define SetPF(x) (ParityVal = (x))
+
+#define SetSZPF_Byte(x) (ParityVal = SignVal = ZeroVal = (int8_t)(x))
+#define SetSZPF_Word(x) (ParityVal = SignVal = ZeroVal = (int16_t)(x))
+
+#define ADDB(dst, src) { unsigned res = (dst) + (src); SetCFB(res); SetOFB_Add(res, src, dst); SetAF(res, src, dst); SetSZPF_Byte(res); dst = (uint8_t)res; }
+#define ADDW(dst, src) { unsigned res = (dst) + (src); SetCFW(res); SetOFW_Add(res, src, dst); SetAF(res, src, dst); SetSZPF_Word(res); dst = (uint16_t)res; }
+
+#define SUBB(dst, src) { unsigned res = (dst) - (src); SetCFB(res); SetOFB_Sub(res, src, dst); SetAF(res, src, dst); SetSZPF_Byte(res); dst = (uint8_t)res; }
+#define SUBW(dst, src) { unsigned res = (dst) - (src); SetCFW(res); SetOFW_Sub(res, src, dst); SetAF(res, src, dst); SetSZPF_Word(res); dst = (uint16_t)res; }
+
+#define ORB(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
+#define ORW(dst, src) dst |= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
+
+#define ANDB(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
+#define ANDW(dst, src) dst &= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
+
+#define XORB(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Byte(dst)
+#define XORW(dst, src) dst ^= (src); CarryVal = OverVal = AuxVal = 0; SetSZPF_Word(dst)
+
+#define CF (CarryVal != 0)
+#define SF (SignVal < 0)
+#define ZF (ZeroVal == 0)
+#define PF parity_table[ParityVal]
+#define AF (AuxVal != 0)
+#define OF (OverVal != 0)
+#define DF (DirVal < 0)
+#define MD (MF != 0)
+
+/************************************************************************/
+
+#define AMASK 0xfffff
+
+#define read_mem_byte(a) d_mem->read_data8((a) & AMASK)
+#define read_mem_word(a) d_mem->read_data16((a) & AMASK)
+#define write_mem_byte(a, d) d_mem->write_data8((a) & AMASK, (d))
+#define write_mem_word(a, d) d_mem->write_data16((a) & AMASK, (d))
+
+#define read_port_byte(a) d_io->read_io8(a)
+#define read_port_word(a) d_io->read_io16(a)
+#define write_port_byte(a, d) d_io->write_io8((a), (d))
+#define write_port_word(a, d) d_io->write_io16((a), (d))
+
+/************************************************************************/
+
+#define SegBase(Seg) (sregs[Seg] << 4)
+
+#define DefaultSeg(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? prefix_seg : Seg)
+#define DefaultBase(Seg) ((seg_prefix && (Seg == DS || Seg == SS)) ? base[prefix_seg] : base[Seg])
+
+#define GetMemB(Seg, Off) (read_mem_byte((DefaultBase(Seg) + (Off)) & AMASK))
+#define GetMemW(Seg, Off) (read_mem_word((DefaultBase(Seg) + (Off)) & AMASK))
+#define PutMemB(Seg, Off, x) write_mem_byte((DefaultBase(Seg) + (Off)) & AMASK, (x))
+#define PutMemW(Seg, Off, x) write_mem_word((DefaultBase(Seg) + (Off)) & AMASK, (x))
+
+#define ReadByte(ea) (read_mem_byte((ea) & AMASK))
+#define ReadWord(ea) (read_mem_word((ea) & AMASK))
+#define WriteByte(ea, val) write_mem_byte((ea) & AMASK, val);
+#define WriteWord(ea, val) write_mem_word((ea) & AMASK, val);
+
+#define FETCH read_mem_byte(pc++)
+#define FETCHOP read_mem_byte(pc++)
+#define FETCHWORD(var) { var = read_mem_word(pc); pc += 2; }
+#define PUSH(val) { regs.w[SP] -= 2; WriteWord(((base[SS] + regs.w[SP]) & AMASK), val); }
+#define POP(var) { regs.w[SP] += 2; var = ReadWord(((base[SS] + ((regs.w[SP]-2) & 0xffff)) & AMASK)); }
+
+/************************************************************************/
+
+#define CompressFlags() (uint16_t)(CF | (PF << 2) | (AF << 4) | (ZF << 6) | (SF << 7) | (TF << 8) | (IF << 9) | (DF << 10) | (OF << 11) | (MD << 15))
+
+#define ExpandFlags(f) { \
+ CarryVal = (f) & 1; \
+ ParityVal = !((f) & 4); \
+ AuxVal = (f) & 0x10; \
+ ZeroVal = !((f) & 0x40); \
+ SignVal = ((f) & 0x80) ? -1 : 0; \
+ TF = ((f) & 0x100) >> 8; \
+ IF = ((f) & 0x200) >> 9; \
+ MF = ((f) & 0x8000) >> 15; \
+ DirVal = ((f) & 0x400) ? -1 : 1; \
+ OverVal = (f) & 0x800; \
+}
+
+/************************************************************************/
+
+#define RegWord(ModRM) regs.w[Mod_RM.reg.w[ModRM]]
+#define RegByte(ModRM) regs.b[Mod_RM.reg.b[ModRM]]
+
+#define GetRMWord(ModRM) \
+ ((ModRM) >= 0xc0 ? regs.w[Mod_RM.RM.w[ModRM]] : (GetEA(ModRM), ReadWord(ea)))
+
+#define PutbackRMWord(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.w[Mod_RM.RM.w[ModRM]] = val; \
+ } else { \
+ WriteWord(ea, val); \
+ } \
+}
+
+#define GetNextRMWord ( \
+ ReadWord(ea + 2) \
+)
+
+#define GetRMWordOffset(offs) ( \
+ ReadWord(ea - eo + (uint16_t)(eo + offs)) \
+)
+
+#define GetRMByteOffset(offs) ( \
+ ReadByte(ea - eo + (uint16_t)(eo + offs)) \
+)
+
+#define PutRMWord(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.w[Mod_RM.RM.w[ModRM]] = val; \
+ } else { \
+ GetEA(ModRM); \
+ WriteWord(ea, val); \
+ } \
+}
+
+#define PutRMWordOffset(offs, val) \
+ WriteWord(ea - eo + (uint16_t)(eo + offs), val)
+
+#define PutRMByteOffset(offs, val) \
+ WriteByte(ea - eo + (uint16_t)(eo + offs), val)
+
+#define PutImmRMWord(ModRM) { \
+ uint16_t val; \
+ if (ModRM >= 0xc0) { \
+ FETCHWORD(regs.w[Mod_RM.RM.w[ModRM]]) \
+ } else { \
+ GetEA(ModRM); \
+ FETCHWORD(val) \
+ WriteWord(ea, val); \
+ } \
+}
+
+#define GetRMByte(ModRM) \
+ ((ModRM) >= 0xc0 ? regs.b[Mod_RM.RM.b[ModRM]] : (GetEA(ModRM), ReadByte(ea)))
+
+#define PutRMByte(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.b[Mod_RM.RM.b[ModRM]] = val; \
+ } else { \
+ GetEA(ModRM); \
+ WriteByte(ea, val); \
+ } \
+}
+
+#define PutImmRMByte(ModRM) { \
+ if (ModRM >= 0xc0) { \
+ regs.b[Mod_RM.RM.b[ModRM]] = FETCH; \
+ } else { \
+ GetEA(ModRM); \
+ WriteByte(ea, FETCH); \
+ } \
+}
+
+#define PutbackRMByte(ModRM, val) { \
+ if (ModRM >= 0xc0) { \
+ regs.b[Mod_RM.RM.b[ModRM]] = val; \
+ } else { \
+ WriteByte(ea, val); \
+ } \
+}
+
+#define DEF_br8(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegByte(ModRM); \
+ unsigned dst = GetRMByte(ModRM)
+
+#define DEF_wr16(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned src = RegWord(ModRM); \
+ unsigned dst = GetRMWord(ModRM)
+
+#define DEF_r8b(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegByte(ModRM); \
+ unsigned src = GetRMByte(ModRM)
+
+#define DEF_r16w(dst, src) \
+ unsigned ModRM = FETCHOP; \
+ unsigned dst = RegWord(ModRM); \
+ unsigned src = GetRMWord(ModRM)
+
+#define DEF_ald8(dst, src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = regs.b[AL]
+
+#define DEF_axd16(dst, src) \
+ unsigned src = FETCHOP; \
+ unsigned dst = regs.w[AX]; \
+ src += (FETCH << 8)
+
+/************************************************************************/
+
+#ifndef INLINE
+#define INLINE inline
+#endif
+
+#define offs_t UINT32
+
+// Disassembler constants
+const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
+const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
+const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
+const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
+const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
+const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
+
+/* Highly useful macro for compile-time knowledge of an array size */
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
+
+int necv_dasm_one(_TCHAR *buffer, UINT32 eip, const UINT8 *oprom);
+
+void I86::initialize()
+{
+ static const BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH};
+
+ for(int i = 0; i < 256; i++) {
+ Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
+ Mod_RM.reg.w[i] = (WREGS)((i & 0x38) >> 3);
+ }
+ for(int i = 0xc0; i < 0x100; i++) {
+ Mod_RM.RM.w[i] = (WREGS)(i & 7);
+ Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
+ }
+#ifdef USE_DEBUGGER
+ d_mem_stored = d_mem;
+ d_io_stored = d_io;
+ d_debugger->set_context_mem(d_mem);
+ d_debugger->set_context_io(d_io);
+#endif
+}
+
+void I86::reset()
+{
+ for(int i = 0; i < 8; i++) {
+ regs.w[i] = 0;
+ }
+ sregs[CS] = 0xf000;
+ sregs[SS] = sregs[DS] = sregs[ES] = 0;
+
+ base[CS] = SegBase(CS);
+ base[SS] = base[DS] = base[ES] = 0;
+
+ ea = 0;
+ eo = 0;
+ AuxVal = OverVal = SignVal = ZeroVal = CarryVal = 0;
+ DirVal = 1;
+ ParityVal = TF = IF = MF = 0;
+
+ icount = extra_icount = 0;
+ int_state = 0;
+ test_state = false;
+ halted = false;
+
+ pc = 0xffff0 & AMASK;
+ flags = 0;
+ ExpandFlags(flags);
+#ifdef HAS_V30
+ SetMD(1);
+#endif
+ seg_prefix = false;
+}
+
+int I86::run(int clock)
+{
+ /* return now if BUSREQ */
+ if(busreq) {
+#ifdef SINGLE_MODE_DMA
+ if(d_dma) {
+ d_dma->do_dma();
+ }
+#endif
+ if(clock == -1) {
+ int passed_icount = max(1, extra_icount);
+ // this is main cpu, icount is not used
+ /*icount = */extra_icount = 0;
+ return passed_icount;
+ } else {
+ icount += clock;
+ int first_icount = icount;
+
+ /* adjust for any interrupts that came in */
+ icount -= extra_icount;
+ extra_icount = 0;
+
+ /* if busreq is raised, spin cpu while remained clock */
+ if(icount > 0) {
+ icount = 0;
+ }
+ return first_icount - icount;
+ }
+ }
+
+ if(clock == -1) {
+ /* run only one opcode */
+ icount = -extra_icount;
+ extra_icount = 0;
+#ifdef USE_DEBUGGER
+ run_one_opecode_debugger();
+#else
+ run_one_opecode();
+#endif
+ return -icount;
+ } else {
+ icount += clock;
+ int first_icount = icount;
+
+ /* adjust for any interrupts that came in */
+ icount -= extra_icount;
+ extra_icount = 0;
+
+ /* run cpu while given clocks */
+ while(icount > 0 && !busreq) {
+#ifdef USE_DEBUGGER
+ run_one_opecode_debugger();
+#else
+ run_one_opecode();
+#endif
+ }
+ /* if busreq is raised, spin cpu while remained clock */
+ if(icount > 0 && busreq) {
+ icount = 0;
+ }
+ return first_icount - icount;
+ }
+}
+
+#ifdef USE_DEBUGGER
+void I86::run_one_opecode_debugger()
+{
+ bool now_debugging = d_debugger->now_debugging;
+ if(now_debugging) {
+ d_debugger->check_break_points(pc);
+ if(d_debugger->now_suspended) {
+ emu->mute_sound();
+ while(d_debugger->now_debugging && d_debugger->now_suspended) {
+ emu->sleep(10);
+ }
+ }
+ if(d_debugger->now_debugging) {
+ d_mem = d_io = d_debugger;
+ } else {
+ now_debugging = false;
+ }
+
+ run_one_opecode();
+ if(now_debugging) {
+ if(!d_debugger->now_going) {
+ d_debugger->now_suspended = true;
+ }
+ d_mem = d_mem_stored;
+ d_io = d_io_stored;
+ }
+ } else {
+ run_one_opecode();
+ }
+}
+#endif
+
+void I86::run_one_opecode()
+{
+ seg_prefix = false;
+#ifdef _JX
+ // ugly patch for PC/JX hardware diagnostics :-(
+#ifdef TIMER_HACK
+ if(pc == 0xff040) pc = 0xff04a;
+ if(pc == 0xff17d) pc = 0xff18f;
+#endif
+#ifdef KEYBOARD_HACK
+ if(pc == 0xfa909) { regs.b[BH] = read_port_byte(0xa1); pc = 0xfa97c; }
+ if(pc == 0xff6e1) { regs.b[AL] = 0x0d; pc += 2; }
+#endif
+#endif
+ instruction(FETCHOP);
+ if(int_state & NMI_REQ_BIT) {
+ if(halted) {
+ pc++;
+ halted = false;
+ }
+ int_state &= ~NMI_REQ_BIT;
+ interrupt(NMI_INT_VECTOR);
+ } else if((int_state & INT_REQ_BIT) && IF) {
+ if(halted) {
+ pc++;
+ halted = false;
+ }
+ interrupt(-1);
+ }
+#ifdef SINGLE_MODE_DMA
+ if(d_dma) {
+ d_dma->do_dma();
+ }
+#endif
+ icount -= extra_icount;
+ extra_icount = 0;
+}
+
+void I86::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ if(id == SIG_CPU_NMI) {
+ if(data & mask) {
+ int_state |= NMI_REQ_BIT;
+ } else {
+ int_state &= ~NMI_REQ_BIT;
+ }
+ } else if(id == SIG_CPU_BUSREQ) {
+ busreq = ((data & mask) != 0);
+ } else if(id == SIG_I86_TEST) {
+ test_state = ((data & mask) != 0);
+ }
+}
+
+void I86::set_intr_line(bool line, bool pending, uint32_t bit)
+{
+ if(line) {
+ int_state |= INT_REQ_BIT;
+ } else {
+ int_state &= ~INT_REQ_BIT;
+ }
+}
+
+#ifdef USE_DEBUGGER
+void I86::write_debug_data8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem_stored->write_data8w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_data8(uint32_t addr)
+{
+ int wait;
+ return d_mem_stored->read_data8w(addr, &wait);
+}
+
+void I86::write_debug_data16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_mem_stored->write_data16w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_data16(uint32_t addr)
+{
+ int wait;
+ return d_mem_stored->read_data16w(addr, &wait);
+}
+
+void I86::write_debug_io8(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io_stored->write_io8w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_io8(uint32_t addr) {
+ int wait;
+ return d_io_stored->read_io8w(addr, &wait);
+}
+
+void I86::write_debug_io16(uint32_t addr, uint32_t data)
+{
+ int wait;
+ d_io_stored->write_io16w(addr, data, &wait);
+}
+
+uint32_t I86::read_debug_io16(uint32_t addr) {
+ int wait;
+ return d_io_stored->read_io16w(addr, &wait);
+}
+
+bool I86::write_debug_reg(const _TCHAR *reg, uint32_t data)
+{
+ if(_tcsicmp(reg, _T("IP")) == 0) {
+ pc = ((data & 0xffff) + base[CS]) & AMASK;
+ } else if(_tcsicmp(reg, _T("AX")) == 0) {
+ regs.w[AX] = data;
+ } else if(_tcsicmp(reg, _T("BX")) == 0) {
+ regs.w[BX] = data;
+ } else if(_tcsicmp(reg, _T("CX")) == 0) {
+ regs.w[CX] = data;
+ } else if(_tcsicmp(reg, _T("DX")) == 0) {
+ regs.w[DX] = data;
+ } else if(_tcsicmp(reg, _T("SP")) == 0) {
+ regs.w[SP] = data;
+ } else if(_tcsicmp(reg, _T("BP")) == 0) {
+ regs.w[BP] = data;
+ } else if(_tcsicmp(reg, _T("SI")) == 0) {
+ regs.w[SI] = data;
+ } else if(_tcsicmp(reg, _T("DI")) == 0) {
+ regs.w[DI] = data;
+ } else if(_tcsicmp(reg, _T("AL")) == 0) {
+ regs.b[AL] = data;
+ } else if(_tcsicmp(reg, _T("AH")) == 0) {
+ regs.b[AH] = data;
+ } else if(_tcsicmp(reg, _T("BL")) == 0) {
+ regs.b[BL] = data;
+ } else if(_tcsicmp(reg, _T("BH")) == 0) {
+ regs.b[BH] = data;
+ } else if(_tcsicmp(reg, _T("CL")) == 0) {
+ regs.b[CL] = data;
+ } else if(_tcsicmp(reg, _T("CH")) == 0) {
+ regs.b[CH] = data;
+ } else if(_tcsicmp(reg, _T("DL")) == 0) {
+ regs.b[DL] = data;
+ } else if(_tcsicmp(reg, _T("DH")) == 0) {
+ regs.b[DH] = data;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void I86::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
+{
+ my_stprintf_s(buffer, buffer_len,
+ _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\nDS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]"),
+ regs.w[AX], regs.w[BX], regs.w[CX], regs.w[DX], regs.w[SP], regs.w[BP], regs.w[SI], regs.w[DI], sregs[DS], sregs[ES], sregs[SS], sregs[CS], (uint16_t)(pc - base[CS]),
+ OF ? _T('O') : _T('-'), DF ? _T('D') : _T('-'), IF ? _T('I') : _T('-'), TF ? _T('T') : _T('-'),
+ SF ? _T('S') : _T('-'), ZF ? _T('Z') : _T('-'), AF ? _T('A') : _T('-'), PF ? _T('P') : _T('-'), CF ? _T('C') : _T('-'));
+}
+
+int I86::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
+{
+ UINT32 eip = (UINT32)(uint16_t)(pc - base[CS]);
+ UINT8 ops[16];
+ for(int i = 0; i < 16; i++) {
+ int wait;
+ ops[i] = d_mem->read_data8w(pc + i, &wait);
+ }
+ return necv_dasm_one(buffer, eip, ops) & DASMFLAG_LENGTHMASK;
+}
+#endif
+
+void I86::interrupt(int int_num)
+{
+ unsigned dest_seg, dest_off;
+ uint16_t ip = pc - base[CS];
+
+ if(int_num == -1) {
+ int_num = d_pic->get_intr_ack() & 0xff;
+ int_state &= ~INT_REQ_BIT;
+ }
+ dest_off = ReadWord(int_num * 4);
+ dest_seg = ReadWord(int_num * 4 + 2);
+
+ _pushf();
+ TF = IF = 0;
+ PUSH(sregs[CS]);
+ PUSH(ip);
+ sregs[CS] = (uint16_t)dest_seg;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + dest_off) & AMASK;
+ icount -= timing.exception;
+}
+
+void I86::trap()
+{
+ instruction(FETCHOP);
+ interrupt(1);
+}
+
+unsigned I86::GetEA(unsigned ModRM)
+{
+ switch(ModRM) {
+ case 0x00: case 0x08: case 0x10: case 0x18: case 0x20: case 0x28: case 0x30: case 0x38:
+ icount -= 7; eo = (uint16_t)(regs.w[BX] + regs.w[SI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x01: case 0x09: case 0x11: case 0x19: case 0x21: case 0x29: case 0x31: case 0x39:
+ icount -= 8; eo = (uint16_t)(regs.w[BX] + regs.w[DI]); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x02: case 0x0a: case 0x12: case 0x1a: case 0x22: case 0x2a: case 0x32: case 0x3a:
+ icount -= 8; eo = (uint16_t)(regs.w[BP] + regs.w[SI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x03: case 0x0b: case 0x13: case 0x1b: case 0x23: case 0x2b: case 0x33: case 0x3b:
+ icount -= 7; eo = (uint16_t)(regs.w[BP] + regs.w[DI]); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x04: case 0x0c: case 0x14: case 0x1c: case 0x24: case 0x2c: case 0x34: case 0x3c:
+ icount -= 5; eo = regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x05: case 0x0d: case 0x15: case 0x1d: case 0x25: case 0x2d: case 0x35: case 0x3d:
+ icount -= 5; eo = regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x06: case 0x0e: case 0x16: case 0x1e: case 0x26: case 0x2e: case 0x36: case 0x3e:
+ icount -= 6; eo = FETCHOP; eo += FETCHOP << 8; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x07: case 0x0f: case 0x17: case 0x1f: case 0x27: case 0x2f: case 0x37: case 0x3f:
+ icount -= 5; eo = regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+
+ case 0x40: case 0x48: case 0x50: case 0x58: case 0x60: case 0x68: case 0x70: case 0x78:
+ icount -= 11; eo = (uint16_t)(regs.w[BX] + regs.w[SI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x41: case 0x49: case 0x51: case 0x59: case 0x61: case 0x69: case 0x71: case 0x79:
+ icount -= 12; eo = (uint16_t)(regs.w[BX] + regs.w[DI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x42: case 0x4a: case 0x52: case 0x5a: case 0x62: case 0x6a: case 0x72: case 0x7a:
+ icount -= 12; eo = (uint16_t)(regs.w[BP] + regs.w[SI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x43: case 0x4b: case 0x53: case 0x5b: case 0x63: case 0x6b: case 0x73: case 0x7b:
+ icount -= 11; eo = (uint16_t)(regs.w[BP] + regs.w[DI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x44: case 0x4c: case 0x54: case 0x5c: case 0x64: case 0x6c: case 0x74: case 0x7c:
+ icount -= 9; eo = (uint16_t)(regs.w[SI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x45: case 0x4d: case 0x55: case 0x5d: case 0x65: case 0x6d: case 0x75: case 0x7d:
+ icount -= 9; eo = (uint16_t)(regs.w[DI] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+ case 0x46: case 0x4e: case 0x56: case 0x5e: case 0x66: case 0x6e: case 0x76: case 0x7e:
+ icount -= 9; eo = (uint16_t)(regs.w[BP] + (int8_t)FETCHOP); ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + eo; return ea;
+ case 0x47: case 0x4f: case 0x57: case 0x5f: case 0x67: case 0x6f: case 0x77: case 0x7f:
+ icount -= 9; eo = (uint16_t)(regs.w[BX] + (int8_t)FETCHOP); ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + eo; return ea;
+
+ case 0x80: case 0x88: case 0x90: case 0x98: case 0xa0: case 0xa8: case 0xb0: case 0xb8:
+ icount -= 11; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX] + regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x81: case 0x89: case 0x91: case 0x99: case 0xa1: case 0xa9: case 0xb1: case 0xb9:
+ icount -= 12; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX] + regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x82: case 0x8a: case 0x92: case 0x9a: case 0xa2: case 0xaa: case 0xb2: case 0xba:
+ icount -= 12; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP] + regs.w[SI]; ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + (uint16_t)eo; return ea;
+ case 0x83: case 0x8b: case 0x93: case 0x9b: case 0xa3: case 0xab: case 0xb3: case 0xbb:
+ icount -= 11; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP] + regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(SS) + (uint16_t)eo; return ea;
+ case 0x84: case 0x8c: case 0x94: case 0x9c: case 0xa4: case 0xac: case 0xb4: case 0xbc:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[SI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x85: case 0x8d: case 0x95: case 0x9d: case 0xa5: case 0xad: case 0xb5: case 0xbd:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[DI]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ case 0x86: case 0x8e: case 0x96: case 0x9e: case 0xa6: case 0xae: case 0xb6: case 0xbe:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BP]; ea_seg = DefaultSeg(SS); ea = DefaultBase(SS) + (uint16_t)eo; return ea;
+ case 0x87: case 0x8f: case 0x97: case 0x9f: case 0xa7: case 0xaf: case 0xb7: case 0xbf:
+ icount -= 9; eo = FETCHOP; eo += FETCHOP << 8; eo += regs.w[BX]; ea_seg = DefaultSeg(DS); ea = DefaultBase(DS) + (uint16_t)eo; return ea;
+ }
+ return 0;
+}
+
+void I86::rotate_shift_byte(unsigned ModRM, unsigned count)
+{
+ unsigned src = (unsigned)GetRMByte(ModRM);
+ unsigned dst = src;
+
+ if(count == 0) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;
+ } else if(count == 1) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL eb, 1 */
+ CarryVal = src & 0x80;
+ dst = (src << 1) + CF;
+ PutbackRMByte(ModRM, dst);
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 1: /* ROR eb, 1 */
+ CarryVal = src & 0x01;
+ dst = ((CF << 8) + src) >> 1;
+ PutbackRMByte(ModRM, dst);
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 2: /* RCL eb, 1 */
+ dst = (src << 1) + CF;
+ PutbackRMByte(ModRM, dst);
+ SetCFB(dst);
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 3: /* RCR eb, 1 */
+ dst = ((CF << 8) + src) >> 1;
+ PutbackRMByte(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = (src ^ dst) & 0x80;
+ break;
+ case 4: /* SHL eb, 1 */
+ case 6:
+ dst = src << 1;
+ PutbackRMByte(ModRM, dst);
+ SetCFB(dst);
+ OverVal = (src ^ dst) & 0x80;
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 5: /* SHR eb, 1 */
+ dst = src >> 1;
+ PutbackRMByte(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = src & 0x80;
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+ case 7: /* SAR eb, 1 */
+ dst = ((int8_t)src) >> 1;
+ PutbackRMByte(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = 0;
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ } else {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m8_bit;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL eb, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x80;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 1: /* ROR eb, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 7);
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 2: /* RCL eb, count */
+ for(; count > 0; count--) {
+ dst = (dst << 1) + CF;
+ SetCFB(dst);
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 3: /* RCR eb, count */
+ for(; count > 0; count--) {
+ dst = (CF << 8) + dst;
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 4: /* SHL eb, count */
+ case 6:
+ dst <<= count;
+ SetCFB(dst);
+ AuxVal = 1;
+ SetSZPF_Byte(dst);
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 5: /* SHR eb, count */
+ dst >>= count - 1;
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ SetSZPF_Byte(dst);
+ AuxVal = 1;
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+ case 7: /* SAR eb, count */
+ dst = ((int8_t)dst) >> (count - 1);
+ CarryVal = dst & 0x01;
+ dst = ((int8_t)((uint8_t)dst)) >> 1;
+ SetSZPF_Byte(dst);
+ AuxVal = 1;
+ PutbackRMByte(ModRM, (uint8_t)dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ }
+}
+
+void I86::rotate_shift_word(unsigned ModRM, unsigned count)
+{
+ unsigned src = GetRMWord(ModRM);
+ unsigned dst = src;
+
+ if(count == 0) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;
+ } else if(count == 1) {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL ew, 1 */
+ CarryVal = src & 0x8000;
+ dst = (src << 1) + CF;
+ PutbackRMWord(ModRM, dst);
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 1: /* ROR ew, 1 */
+ CarryVal = src & 0x01;
+ dst = ((CF << 16) + src) >> 1;
+ PutbackRMWord(ModRM, dst);
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 2: /* RCL ew, 1 */
+ dst = (src << 1) + CF;
+ PutbackRMWord(ModRM, dst);
+ SetCFW(dst);
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 3: /* RCR ew, 1 */
+ dst = ((CF << 16) + src) >> 1;
+ PutbackRMWord(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = (src ^ dst) & 0x8000;
+ break;
+ case 4: /* SHL ew, 1 */
+ case 6:
+ dst = src << 1;
+ PutbackRMWord(ModRM, dst);
+ SetCFW(dst);
+ OverVal = (src ^ dst) & 0x8000;
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 5: /* SHR ew, 1 */
+ dst = src >> 1;
+ PutbackRMWord(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = src & 0x8000;
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+ case 7: /* SAR ew, 1 */
+ dst = ((int16_t)src) >> 1;
+ PutbackRMWord(ModRM, dst);
+ CarryVal = src & 0x01;
+ OverVal = 0;
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ } else {
+ icount -= (ModRM >= 0xc0) ? timing.rot_reg_base + timing.rot_reg_bit : timing.rot_m8_base + timing.rot_m16_bit;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ROL ew, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x8000;
+ dst = (dst << 1) + CF;
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 1: /* ROR ew, count */
+ for(; count > 0; count--) {
+ CarryVal = dst & 0x01;
+ dst = (dst >> 1) + (CF << 15);
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 2: /* RCL ew, count */
+ for(; count > 0; count--) {
+ dst = (dst << 1) + CF;
+ SetCFW(dst);
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 3: /* RCR ew, count */
+ for(; count > 0; count--) {
+ dst = dst + (CF << 16);
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ }
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 4: /* SHL ew, count */
+ case 6:
+ dst <<= count;
+ SetCFW(dst);
+ AuxVal = 1;
+ SetSZPF_Word(dst);
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 5: /* SHR ew, count */
+ dst >>= count - 1;
+ CarryVal = dst & 0x01;
+ dst >>= 1;
+ SetSZPF_Word(dst);
+ AuxVal = 1;
+ PutbackRMWord(ModRM, dst);
+ break;
+ case 7: /* SAR ew, count */
+ dst = ((int16_t)dst) >> (count - 1);
+ CarryVal = dst & 0x01;
+ dst = ((int16_t)((uint16_t)dst)) >> 1;
+ SetSZPF_Word(dst);
+ AuxVal = 1;
+ PutbackRMWord(ModRM, dst);
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+ }
+}
+
+void I86::instruction(uint8_t code)
+{
+ prevpc = pc - 1;
+
+ switch(code) {
+ case 0x00: _add_br8(); break;
+ case 0x01: _add_wr16(); break;
+ case 0x02: _add_r8b(); break;
+ case 0x03: _add_r16w(); break;
+ case 0x04: _add_ald8(); break;
+ case 0x05: _add_axd16(); break;
+ case 0x06: _push_es(); break;
+ case 0x07: _pop_es(); break;
+ case 0x08: _or_br8(); break;
+ case 0x09: _or_wr16(); break;
+ case 0x0a: _or_r8b(); break;
+ case 0x0b: _or_r16w(); break;
+ case 0x0c: _or_ald8(); break;
+ case 0x0d: _or_axd16(); break;
+ case 0x0e: _push_cs(); break;
+#if defined(HAS_V30)
+ case 0x0f: _0fpre(); break;
+#else
+ case 0x0f: _invalid(); break;
+#endif
+ case 0x10: _adc_br8(); break;
+ case 0x11: _adc_wr16(); break;
+ case 0x12: _adc_r8b(); break;
+ case 0x13: _adc_r16w(); break;
+ case 0x14: _adc_ald8(); break;
+ case 0x15: _adc_axd16(); break;
+ case 0x16: _push_ss(); break;
+ case 0x17: _pop_ss(); break;
+ case 0x18: _sbb_br8(); break;
+ case 0x19: _sbb_wr16(); break;
+ case 0x1a: _sbb_r8b(); break;
+ case 0x1b: _sbb_r16w(); break;
+ case 0x1c: _sbb_ald8(); break;
+ case 0x1d: _sbb_axd16(); break;
+ case 0x1e: _push_ds(); break;
+ case 0x1f: _pop_ds(); break;
+ case 0x20: _and_br8(); break;
+ case 0x21: _and_wr16(); break;
+ case 0x22: _and_r8b(); break;
+ case 0x23: _and_r16w(); break;
+ case 0x24: _and_ald8(); break;
+ case 0x25: _and_axd16(); break;
+ case 0x26: _es(); break;
+ case 0x27: _daa(); break;
+ case 0x28: _sub_br8(); break;
+ case 0x29: _sub_wr16(); break;
+ case 0x2a: _sub_r8b(); break;
+ case 0x2b: _sub_r16w(); break;
+ case 0x2c: _sub_ald8(); break;
+ case 0x2d: _sub_axd16(); break;
+ case 0x2e: _cs(); break;
+ case 0x2f: _das(); break;
+ case 0x30: _xor_br8(); break;
+ case 0x31: _xor_wr16(); break;
+ case 0x32: _xor_r8b(); break;
+ case 0x33: _xor_r16w(); break;
+ case 0x34: _xor_ald8(); break;
+ case 0x35: _xor_axd16(); break;
+ case 0x36: _ss(); break;
+ case 0x37: _aaa(); break;
+ case 0x38: _cmp_br8(); break;
+ case 0x39: _cmp_wr16(); break;
+ case 0x3a: _cmp_r8b(); break;
+ case 0x3b: _cmp_r16w(); break;
+ case 0x3c: _cmp_ald8(); break;
+ case 0x3d: _cmp_axd16(); break;
+ case 0x3e: _ds(); break;
+ case 0x3f: _aas(); break;
+ case 0x40: _inc_ax(); break;
+ case 0x41: _inc_cx(); break;
+ case 0x42: _inc_dx(); break;
+ case 0x43: _inc_bx(); break;
+ case 0x44: _inc_sp(); break;
+ case 0x45: _inc_bp(); break;
+ case 0x46: _inc_si(); break;
+ case 0x47: _inc_di(); break;
+ case 0x48: _dec_ax(); break;
+ case 0x49: _dec_cx(); break;
+ case 0x4a: _dec_dx(); break;
+ case 0x4b: _dec_bx(); break;
+ case 0x4c: _dec_sp(); break;
+ case 0x4d: _dec_bp(); break;
+ case 0x4e: _dec_si(); break;
+ case 0x4f: _dec_di(); break;
+ case 0x50: _push_ax(); break;
+ case 0x51: _push_cx(); break;
+ case 0x52: _push_dx(); break;
+ case 0x53: _push_bx(); break;
+ case 0x54: _push_sp(); break;
+ case 0x55: _push_bp(); break;
+ case 0x56: _push_si(); break;
+ case 0x57: _push_di(); break;
+ case 0x58: _pop_ax(); break;
+ case 0x59: _pop_cx(); break;
+ case 0x5a: _pop_dx(); break;
+ case 0x5b: _pop_bx(); break;
+ case 0x5c: _pop_sp(); break;
+ case 0x5d: _pop_bp(); break;
+ case 0x5e: _pop_si(); break;
+ case 0x5f: _pop_di(); break;
+#if defined(HAS_V30)
+ case 0x60: _pusha(); break;
+ case 0x61: _popa(); break;
+ case 0x62: _bound(); break;
+#else
+ case 0x60: _invalid(); break;
+ case 0x61: _invalid(); break;
+ case 0x62: _invalid(); break;
+#endif
+ case 0x63: _invalid(); break;
+#if defined(HAS_V30)
+ case 0x64: _repc(0); break;
+ case 0x65: _repc(1); break;
+#else
+ case 0x64: _invalid(); break;
+ case 0x65: _invalid(); break;
+#endif
+ case 0x66: _invalid(); break;
+ case 0x67: _invalid(); break;
+#if defined(HAS_V30)
+ case 0x68: _push_d16(); break;
+ case 0x69: _imul_d16(); break;
+ case 0x6a: _push_d8(); break;
+ case 0x6b: _imul_d8(); break;
+ case 0x6c: _insb(); break;
+ case 0x6d: _insw(); break;
+ case 0x6e: _outsb(); break;
+ case 0x6f: _outsw(); break;
+#else
+ case 0x68: _invalid(); break;
+ case 0x69: _invalid(); break;
+ case 0x6a: _invalid(); break;
+ case 0x6b: _invalid(); break;
+ case 0x6c: _invalid(); break;
+ case 0x6d: _invalid(); break;
+ case 0x6e: _invalid(); break;
+ case 0x6f: _invalid(); break;
+#endif
+ case 0x70: _jo(); break;
+ case 0x71: _jno(); break;
+ case 0x72: _jb(); break;
+ case 0x73: _jnb(); break;
+ case 0x74: _jz(); break;
+ case 0x75: _jnz(); break;
+ case 0x76: _jbe(); break;
+ case 0x77: _jnbe(); break;
+ case 0x78: _js(); break;
+ case 0x79: _jns(); break;
+ case 0x7a: _jp(); break;
+ case 0x7b: _jnp(); break;
+ case 0x7c: _jl(); break;
+ case 0x7d: _jnl(); break;
+ case 0x7e: _jle(); break;
+ case 0x7f: _jnle(); break;
+ case 0x80: _80pre(); break;
+ case 0x81: _81pre(); break;
+ case 0x82: _82pre(); break;
+ case 0x83: _83pre(); break;
+ case 0x84: _test_br8(); break;
+ case 0x85: _test_wr16(); break;
+ case 0x86: _xchg_br8(); break;
+ case 0x87: _xchg_wr16(); break;
+ case 0x88: _mov_br8(); break;
+ case 0x89: _mov_wr16(); break;
+ case 0x8a: _mov_r8b(); break;
+ case 0x8b: _mov_r16w(); break;
+ case 0x8c: _mov_wsreg(); break;
+ case 0x8d: _lea(); break;
+ case 0x8e: _mov_sregw(); break;
+ case 0x8f: _popw(); break;
+ case 0x90: _nop(); break;
+ case 0x91: _xchg_axcx(); break;
+ case 0x92: _xchg_axdx(); break;
+ case 0x93: _xchg_axbx(); break;
+ case 0x94: _xchg_axsp(); break;
+ case 0x95: _xchg_axbp(); break;
+ case 0x96: _xchg_axsi(); break;
+ case 0x97: _xchg_axdi(); break;
+ case 0x98: _cbw(); break;
+ case 0x99: _cwd(); break;
+ case 0x9a: _call_far(); break;
+ case 0x9b: _wait(); break;
+ case 0x9c: _pushf(); break;
+ case 0x9d: _popf(); break;
+ case 0x9e: _sahf(); break;
+ case 0x9f: _lahf(); break;
+ case 0xa0: _mov_aldisp(); break;
+ case 0xa1: _mov_axdisp(); break;
+ case 0xa2: _mov_dispal(); break;
+ case 0xa3: _mov_dispax(); break;
+ case 0xa4: _movsb(); break;
+ case 0xa5: _movsw(); break;
+ case 0xa6: _cmpsb(); break;
+ case 0xa7: _cmpsw(); break;
+ case 0xa8: _test_ald8(); break;
+ case 0xa9: _test_axd16(); break;
+ case 0xaa: _stosb(); break;
+ case 0xab: _stosw(); break;
+ case 0xac: _lodsb(); break;
+ case 0xad: _lodsw(); break;
+ case 0xae: _scasb(); break;
+ case 0xaf: _scasw(); break;
+ case 0xb0: _mov_ald8(); break;
+ case 0xb1: _mov_cld8(); break;
+ case 0xb2: _mov_dld8(); break;
+ case 0xb3: _mov_bld8(); break;
+ case 0xb4: _mov_ahd8(); break;
+ case 0xb5: _mov_chd8(); break;
+ case 0xb6: _mov_dhd8(); break;
+ case 0xb7: _mov_bhd8(); break;
+ case 0xb8: _mov_axd16(); break;
+ case 0xb9: _mov_cxd16(); break;
+ case 0xba: _mov_dxd16(); break;
+ case 0xbb: _mov_bxd16(); break;
+ case 0xbc: _mov_spd16(); break;
+ case 0xbd: _mov_bpd16(); break;
+ case 0xbe: _mov_sid16(); break;
+ case 0xbf: _mov_did16(); break;
+#if defined(HAS_V30)
+ case 0xc0: _rotshft_bd8(); break;
+ case 0xc1: _rotshft_wd8(); break;
+#else
+ case 0xc0: _invalid(); break;
+ case 0xc1: _invalid(); break;
+#endif
+ case 0xc2: _ret_d16(); break;
+ case 0xc3: _ret(); break;
+ case 0xc4: _les_dw(); break;
+ case 0xc5: _lds_dw(); break;
+ case 0xc6: _mov_bd8(); break;
+ case 0xc7: _mov_wd16(); break;
+#if defined(HAS_V30)
+ case 0xc8: _enter(); break;
+ case 0xc9: _leav(); break; /* _leave() */
+#else
+ case 0xc8: _invalid(); break;
+ case 0xc9: _invalid(); break;
+#endif
+ case 0xca: _retf_d16(); break;
+ case 0xcb: _retf(); break;
+ case 0xcc: _int3(); break;
+ case 0xcd: _int(); break;
+ case 0xce: _into(); break;
+ case 0xcf: _iret(); break;
+ case 0xd0: _rotshft_b(); break;
+ case 0xd1: _rotshft_w(); break;
+ case 0xd2: _rotshft_bcl(); break;
+ case 0xd3: _rotshft_wcl(); break;
+ case 0xd4: _aam(); break;
+ case 0xd5: _aad(); break;
+#if defined(HAS_V30)
+ case 0xd6: _setalc(); break;
+#else
+ case 0xd6: _invalid(); break;
+#endif
+ case 0xd7: _xlat(); break;
+ case 0xd8: _escape(); break;
+ case 0xd9: _escape(); break;
+ case 0xda: _escape(); break;
+ case 0xdb: _escape(); break;
+ case 0xdc: _escape(); break;
+ case 0xdd: _escape(); break;
+ case 0xde: _escape(); break;
+ case 0xdf: _escape(); break;
+ case 0xe0: _loopne(); break;
+ case 0xe1: _loope(); break;
+ case 0xe2: _loop(); break;
+ case 0xe3: _jcxz(); break;
+ case 0xe4: _inal(); break;
+ case 0xe5: _inax(); break;
+ case 0xe6: _outal(); break;
+ case 0xe7: _outax(); break;
+ case 0xe8: _call_d16(); break;
+ case 0xe9: _jmp_d16(); break;
+ case 0xea: _jmp_far(); break;
+ case 0xeb: _jmp_d8(); break;
+ case 0xec: _inaldx(); break;
+ case 0xed: _inaxdx(); break;
+ case 0xee: _outdxal(); break;
+ case 0xef: _outdxax(); break;
+ case 0xf0: _lock(); break;
+ case 0xf1: _invalid(); break;
+ case 0xf2: _repne(); break;
+ case 0xf3: _repe(); break;
+ case 0xf4: _hlt(); break;
+ case 0xf5: _cmc(); break;
+ case 0xf6: _f6pre(); break;
+ case 0xf7: _f7pre(); break;
+ case 0xf8: _clc(); break;
+ case 0xf9: _stc(); break;
+ case 0xfa: _cli(); break;
+ case 0xfb: _sti(); break;
+ case 0xfc: _cld(); break;
+ case 0xfd: _std(); break;
+ case 0xfe: _fepre(); break;
+ case 0xff: _ffpre(); break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default: __assume(0);
+#endif
+ }
+}
+
+inline void I86::_add_br8() /* Opcode 0x00 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_add_wr16() /* Opcode 0x01 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_add_r8b() /* Opcode 0x02 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ADDB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_add_r16w() /* Opcode 0x03 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ADDW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_add_ald8() /* Opcode 0x04 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ADDB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_add_axd16() /* Opcode 0x05 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ADDW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_es() /* Opcode 0x06 */
+{
+ icount -= timing.push_seg;
+ PUSH(sregs[ES]);
+}
+
+inline void I86::_pop_es() /* Opcode 0x07 */
+{
+ POP(sregs[ES]);
+ base[ES] = SegBase(ES);
+ icount -= timing.pop_seg;
+}
+
+inline void I86::_or_br8() /* Opcode 0x08 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_or_wr16() /* Opcode 0x09 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_or_r8b() /* Opcode 0x0a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ORB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_or_r16w() /* Opcode 0x0b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ORW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_or_ald8() /* Opcode 0x0c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ORB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_or_axd16() /* Opcode 0x0d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ORW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_cs() /* Opcode 0x0e */
+{
+ icount -= timing.push_seg;
+ PUSH(sregs[CS]);
+}
+
+#if defined(HAS_V30)
+inline void I86::_0fpre() /* Opcode 0x0f */
+{
+ static const uint16_t bytes[] = {
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
+ };
+ unsigned code = FETCH;
+ unsigned ModRM;
+ unsigned tmp;
+ unsigned tmp2;
+
+ switch(code) {
+ case 0x10: /* 0F 10 47 30 - TEST1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 3;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 12;
+ }
+ tmp2 = regs.b[CL] & 7;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x11: /* 0F 11 47 30 - TEST1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 3;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 12;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x12: /* 0F 12 [mod:000:r/m] - CLR1 reg/m8, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 14;
+ }
+ tmp2 = regs.b[CL] & 7;
+ tmp &= ~bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x13: /* 0F 13 [mod:000:r/m] - CLR1 reg/m16, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 14;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ tmp &= ~bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x14: /* 0F 14 47 30 - SET1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 13;
+ }
+ tmp2 = regs.b[CL] & 7;
+ tmp |= bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x15: /* 0F 15 C6 - SET1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 13;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ tmp |= bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x16: /* 0F 16 C6 - NOT1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 18;
+ }
+ tmp2 = regs.b[CL] & 7;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x17: /* 0F 17 C6 - NOT1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 18;
+ }
+ tmp2 = regs.b[CL] & 0xf;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x18: /* 0F 18 XX - TEST1 [bx+30h], 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 13;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x19: /* 0F 19 XX - TEST1 [bx+30h], 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 4;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 13;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ SetZF(tmp & bytes[tmp2]);
+ break;
+ case 0x1a: /* 0F 1A 06 - CLR1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 6;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 15;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 7;
+ tmp &= ~bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x1B: /* 0F 1B 06 - CLR1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 6;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 15;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ tmp &= ~bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x1C: /* 0F 1C 47 30 - SET1 [bx+30h], cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 14;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 7;
+ tmp |= bytes[tmp2];
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x1D: /* 0F 1D C6 - SET1 si, cl */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 14;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ tmp |= bytes[tmp2];
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x1e: /* 0F 1e C6 - NOT1 si, 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 19;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 7;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x1f: /* 0F 1f C6 - NOT1 si, 07 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.w[Mod_RM.RM.w[ModRM]];
+ icount -= 5;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadWord(ea);
+ icount = old - 19;
+ }
+ tmp2 = FETCH;
+ tmp2 &= 0xf;
+ if(tmp & bytes[tmp2]) {
+ tmp &= ~bytes[tmp2];
+ } else {
+ tmp |= bytes[tmp2];
+ }
+ PutbackRMWord(ModRM, tmp);
+ break;
+ case 0x20: /* 0F 20 59 - add4s */
+ {
+ /* length in words ! */
+ int count = (regs.b[CL] + 1) / 2;
+ unsigned di = regs.w[DI];
+ unsigned si = regs.w[SI];
+
+ ZeroVal = 1;
+ CarryVal = 0; /* NOT ADC */
+ for(int i = 0; i < count; i++) {
+ 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 + CarryVal;
+ CarryVal = result > 99 ? 1 : 0;
+ result = result % 100;
+ v1 = ((result / 10) << 4) | (result % 10);
+ PutMemB(ES, di, v1);
+ if(v1) {
+ ZeroVal = 0;
+ }
+ si++;
+ di++;
+ }
+ OverVal = CarryVal;
+ icount -= 7 + 19 * count;
+ }
+ break;
+ case 0x22: /* 0F 22 59 - sub4s */
+ {
+ int count = (regs.b[CL] + 1) / 2;
+ unsigned di = regs.w[DI];
+ unsigned si = regs.w[SI];
+
+ ZeroVal = 1;
+ CarryVal = 0; /* NOT ADC */
+ for(int i = 0; i < count; i++) {
+ tmp = GetMemB(ES, di);
+ tmp2 = GetMemB(DS, si);
+ int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
+ int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
+ if(v1 < (v2 + CarryVal)) {
+ v1 += 100;
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 1;
+ } else {
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 0;
+ }
+ v1 = ((result / 10) << 4) | (result % 10);
+ PutMemB(ES, di, v1);
+ if(v1) {
+ ZeroVal = 0;
+ }
+ si++;
+ di++;
+ }
+ OverVal = CarryVal;
+ icount -= 7 + 19 * count;
+ }
+ break;
+ case 0x25:
+ icount -= 16;
+ break;
+ case 0x26: /* 0F 22 59 - cmp4s */
+ {
+ int count = (regs.b[CL] + 1) / 2;
+ unsigned di = regs.w[DI];
+ unsigned si = regs.w[SI];
+
+ ZeroVal = 1;
+ CarryVal = 0; /* NOT ADC */
+ for(int i = 0; i < count; i++) {
+ tmp = GetMemB(ES, di);
+ tmp2 = GetMemB(DS, si);
+ int v1 = (tmp >> 4) * 10 + (tmp & 0xf);
+ int v2 = (tmp2 >> 4) * 10 + (tmp2 & 0xf), result;
+ if(v1 < (v2 + CarryVal)) {
+ v1 += 100;
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 1;
+ } else {
+ result = v1 - (v2 + CarryVal);
+ CarryVal = 0;
+ }
+ v1 = ((result / 10) << 4) | (result % 10);
+ /* PutMemB(ES, di, v1); /* no store, only compare */
+ if(v1) {
+ ZeroVal = 0;
+ }
+ si++;
+ di++;
+ }
+ OverVal = CarryVal;
+ icount -= 7 + 19 * (regs.b[CL] + 1);
+ }
+ break;
+ case 0x28: /* 0F 28 C7 - ROL4 bh */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 25;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 28;
+ }
+ tmp <<= 4;
+ tmp |= regs.b[AL] & 0xf;
+ regs.b[AL] = (regs.b[AL] & 0xf0) | ((tmp >> 8) & 0xf);
+ tmp &= 0xff;
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x29: /* 0F 29 C7 - ROL4 bx */
+ ModRM = FETCH;
+ break;
+ case 0x2A: /* 0F 2a c2 - ROR4 bh */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 29;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 33;
+ }
+ tmp2 = (regs.b[AL] & 0xf) << 4;
+ regs.b[AL] = (regs.b[AL] & 0xf0) | (tmp & 0xf);
+ tmp = tmp2 | (tmp >> 4);
+ PutbackRMByte(ModRM, tmp);
+ break;
+ case 0x2B: /* 0F 2b c2 - ROR4 bx */
+ ModRM = FETCH;
+ break;
+ case 0x2D: /* 0Fh 2Dh < 1111 1RRR> */
+ ModRM = FETCH;
+ icount -= 15;
+ break;
+ case 0x31: /* 0F 31 [mod:reg:r/m] - INS reg8, reg8 or INS reg8, imm4 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 29;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 33;
+ }
+ break;
+ case 0x33: /* 0F 33 [mod:reg:r/m] - EXT reg8, reg8 or EXT reg8, imm4 */
+ ModRM = FETCH;
+ if(ModRM >= 0xc0) {
+ tmp = regs.b[Mod_RM.RM.b[ModRM]];
+ icount -= 29;
+ } else {
+ int old = icount;
+ GetEA(ModRM);
+ tmp = ReadByte(ea);
+ icount = old - 33;
+ }
+ break;
+ case 0x91:
+ icount -= 12;
+ break;
+ case 0x94:
+ ModRM = FETCH;
+ icount -= 11;
+ break;
+ case 0x95:
+ ModRM = FETCH;
+ icount -= 11;
+ break;
+ case 0xbe:
+ icount -= 2;
+ break;
+ case 0xe0:
+ ModRM = FETCH;
+ icount -= 12;
+ break;
+ case 0xf0:
+ ModRM = FETCH;
+ icount -= 12;
+ break;
+ case 0xff: /* 0F ff imm8 - BRKEM */
+ ModRM = FETCH;
+ icount -= 38;
+ interrupt(ModRM);
+ break;
+ }
+}
+#endif
+
+inline void I86::_adc_br8() /* Opcode 0x10 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src += CF;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_adc_wr16() /* Opcode 0x11 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src += CF;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_adc_r8b() /* Opcode 0x12 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src += CF;
+ ADDB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_adc_r16w() /* Opcode 0x13 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src += CF;
+ ADDW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_adc_ald8() /* Opcode 0x14 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ src += CF;
+ ADDB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_adc_axd16() /* Opcode 0x15 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ src += CF;
+ ADDW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_ss() /* Opcode 0x16 */
+{
+ PUSH(sregs[SS]);
+ icount -= timing.push_seg;
+}
+
+inline void I86::_pop_ss() /* Opcode 0x17 */
+{
+ POP(sregs[SS]);
+ base[SS] = SegBase(SS);
+ icount -= timing.pop_seg;
+ instruction(FETCHOP); /* no interrupt before next instruction */
+}
+
+inline void I86::_sbb_br8() /* Opcode 0x18 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ src += CF;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_sbb_wr16() /* Opcode 0x19 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ src += CF;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_sbb_r8b() /* Opcode 0x1a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ src += CF;
+ SUBB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_sbb_r16w() /* Opcode 0x1b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ src += CF;
+ SUBW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_sbb_ald8() /* Opcode 0x1c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ src += CF;
+ SUBB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_sbb_axd16() /* Opcode 0x1d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ src += CF;
+ SUBW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_push_ds() /* Opcode 0x1e */
+{
+ PUSH(sregs[DS]);
+ icount -= timing.push_seg;
+}
+
+inline void I86::_pop_ds() /* Opcode 0x1f */
+{
+ POP(sregs[DS]);
+ base[DS] = SegBase(DS);
+ icount -= timing.push_seg;
+}
+
+inline void I86::_and_br8() /* Opcode 0x20 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ ANDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_and_wr16() /* Opcode 0x21 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ ANDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_and_r8b() /* Opcode 0x22 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_and_r16w() /* Opcode 0x23 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_and_ald8() /* Opcode 0x24 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ANDB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_and_axd16() /* Opcode 0x25 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ANDW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_es() /* Opcode 0x26 */
+{
+ seg_prefix = true;
+ prefix_seg = ES;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_daa() /* Opcode 0x27 */
+{
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ int tmp;
+ regs.b[AL] = tmp = regs.b[AL] + 6;
+ AuxVal = 1;
+ CarryVal |= tmp & 0x100;
+ }
+
+ if(CF || (regs.b[AL] > 0x9f)) {
+ regs.b[AL] += 0x60;
+ CarryVal = 1;
+ }
+
+ SetSZPF_Byte(regs.b[AL]);
+ icount -= timing.daa;
+}
+
+inline void I86::_sub_br8() /* Opcode 0x28 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_sub_wr16() /* Opcode 0x29 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_sub_r8b() /* Opcode 0x2a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_sub_r16w() /* Opcode 0x2b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_sub_ald8() /* Opcode 0x2c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ SUBB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_sub_axd16() /* Opcode 0x2d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ SUBW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_cs() /* Opcode 0x2e */
+{
+ seg_prefix = true;
+ prefix_seg = CS;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_das() /* Opcode 0x2f */
+{
+ uint8_t tmpAL = regs.b[AL];
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ int tmp;
+ regs.b[AL] = tmp = regs.b[AL] - 6;
+ AuxVal = 1;
+ CarryVal |= tmp & 0x100;
+ }
+
+ if(CF || (tmpAL > 0x9f)) {
+ regs.b[AL] -= 0x60;
+ CarryVal = 1;
+ }
+
+ SetSZPF_Byte(regs.b[AL]);
+ icount -= timing.das;
+}
+
+inline void I86::_xor_br8() /* Opcode 0x30 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;
+ XORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+}
+
+inline void I86::_xor_wr16() /* Opcode 0x31 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;
+ XORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+}
+
+inline void I86::_xor_r8b() /* Opcode 0x32 */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ XORB(dst, src);
+ RegByte(ModRM) = dst;
+}
+
+inline void I86::_xor_r16w() /* Opcode 0x33 */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ XORW(dst, src);
+ RegWord(ModRM) = dst;
+}
+
+inline void I86::_xor_ald8() /* Opcode 0x34 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ XORB(dst, src);
+ regs.b[AL] = dst;
+}
+
+inline void I86::_xor_axd16() /* Opcode 0x35 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ XORW(dst, src);
+ regs.w[AX] = dst;
+}
+
+inline void I86::_ss() /* Opcode 0x36 */
+{
+ seg_prefix = true;
+ prefix_seg = SS;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_aaa() /* Opcode 0x37 */
+{
+ uint8_t ALcarry = 1;
+ if(regs.b[AL]>0xf9) {
+ ALcarry = 2;
+ }
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ regs.b[AL] += 6;
+ regs.b[AH] += ALcarry;
+ AuxVal = 1;
+ CarryVal = 1;
+ } else {
+ AuxVal = 0;
+ CarryVal = 0;
+ }
+ regs.b[AL] &= 0x0F;
+ icount -= timing.aaa;
+}
+
+inline void I86::_cmp_br8() /* Opcode 0x38 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst, src);
+}
+
+inline void I86::_cmp_wr16() /* Opcode 0x39 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst, src);
+}
+
+inline void I86::_cmp_r8b() /* Opcode 0x3a */
+{
+ DEF_r8b(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ SUBB(dst, src);
+}
+
+inline void I86::_cmp_r16w() /* Opcode 0x3b */
+{
+ DEF_r16w(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ SUBW(dst, src);
+}
+
+inline void I86::_cmp_ald8() /* Opcode 0x3c */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ SUBB(dst, src);
+}
+
+inline void I86::_cmp_axd16() /* Opcode 0x3d */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ SUBW(dst, src);
+}
+
+inline void I86::_ds() /* Opcode 0x3e */
+{
+ seg_prefix = true;
+ prefix_seg = DS;
+ icount -= timing.override;
+ instruction(FETCHOP);
+}
+
+inline void I86::_aas() /* Opcode 0x3f */
+{
+ uint8_t ALcarry = 1;
+ if(regs.b[AL] > 0xf9) {
+ ALcarry = 2;
+ }
+ if(AF || ((regs.b[AL] & 0xf) > 9)) {
+ regs.b[AL] -= 6;
+ regs.b[AH] -= 1;
+ AuxVal = 1;
+ CarryVal = 1;
+ } else {
+ AuxVal = 0;
+ CarryVal = 0;
+ }
+ regs.b[AL] &= 0x0F;
+ icount -= timing.aas;
+}
+
+#define IncWordReg(Reg) { \
+ unsigned tmp = (unsigned)regs.w[Reg]; \
+ unsigned tmp1 = tmp + 1; \
+ SetOFW_Add(tmp1, tmp, 1); \
+ SetAF(tmp1, tmp, 1); \
+ SetSZPF_Word(tmp1); \
+ regs.w[Reg] = tmp1; \
+ icount -= timing.incdec_r16; \
+}
+
+inline void I86::_inc_ax() /* Opcode 0x40 */
+{
+ IncWordReg(AX);
+}
+
+inline void I86::_inc_cx() /* Opcode 0x41 */
+{
+ IncWordReg(CX);
+}
+
+inline void I86::_inc_dx() /* Opcode 0x42 */
+{
+ IncWordReg(DX);
+}
+
+inline void I86::_inc_bx() /* Opcode 0x43 */
+{
+ IncWordReg(BX);
+}
+
+inline void I86::_inc_sp() /* Opcode 0x44 */
+{
+ IncWordReg(SP);
+}
+
+inline void I86::_inc_bp() /* Opcode 0x45 */
+{
+ IncWordReg(BP);
+}
+
+inline void I86::_inc_si() /* Opcode 0x46 */
+{
+ IncWordReg(SI);
+}
+
+inline void I86::_inc_di() /* Opcode 0x47 */
+{
+ IncWordReg(DI);
+}
+
+#define DecWordReg(Reg) { \
+ unsigned tmp = (unsigned)regs.w[Reg]; \
+ unsigned tmp1 = tmp - 1; \
+ SetOFW_Sub(tmp1, 1, tmp); \
+ SetAF(tmp1, tmp, 1); \
+ SetSZPF_Word(tmp1); \
+ regs.w[Reg] = tmp1; \
+ icount -= timing.incdec_r16; \
+}
+
+inline void I86::_dec_ax() /* Opcode 0x48 */
+{
+ DecWordReg(AX);
+}
+
+inline void I86::_dec_cx() /* Opcode 0x49 */
+{
+ DecWordReg(CX);
+}
+
+inline void I86::_dec_dx() /* Opcode 0x4a */
+{
+ DecWordReg(DX);
+}
+
+inline void I86::_dec_bx() /* Opcode 0x4b */
+{
+ DecWordReg(BX);
+}
+
+inline void I86::_dec_sp() /* Opcode 0x4c */
+{
+ DecWordReg(SP);
+}
+
+inline void I86::_dec_bp() /* Opcode 0x4d */
+{
+ DecWordReg(BP);
+}
+
+inline void I86::_dec_si() /* Opcode 0x4e */
+{
+ DecWordReg(SI);
+}
+
+inline void I86::_dec_di() /* Opcode 0x4f */
+{
+ DecWordReg(DI);
+}
+
+inline void I86::_push_ax() /* Opcode 0x50 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[AX]);
+}
+
+inline void I86::_push_cx() /* Opcode 0x51 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[CX]);
+}
+
+inline void I86::_push_dx() /* Opcode 0x52 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[DX]);
+}
+
+inline void I86::_push_bx() /* Opcode 0x53 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[BX]);
+}
+
+inline void I86::_push_sp() /* Opcode 0x54 */
+{
+ unsigned tmp = regs.w[SP];
+
+ icount -= timing.push_r16;
+ PUSH(tmp - 2);
+}
+
+inline void I86::_push_bp() /* Opcode 0x55 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[BP]);
+}
+
+inline void I86::_push_si() /* Opcode 0x56 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[SI]);
+}
+
+inline void I86::_push_di() /* Opcode 0x57 */
+{
+ icount -= timing.push_r16;
+ PUSH(regs.w[DI]);
+}
+
+inline void I86::_pop_ax() /* Opcode 0x58 */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[AX]);
+}
+
+inline void I86::_pop_cx() /* Opcode 0x59 */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[CX]);
+}
+
+inline void I86::_pop_dx() /* Opcode 0x5a */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[DX]);
+}
+
+inline void I86::_pop_bx() /* Opcode 0x5b */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[BX]);
+}
+
+inline void I86::_pop_sp() /* Opcode 0x5c */
+{
+ unsigned tmp;
+
+ icount -= timing.pop_r16;
+ POP(tmp);
+ regs.w[SP] = tmp;
+}
+
+inline void I86::_pop_bp() /* Opcode 0x5d */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[BP]);
+}
+
+inline void I86::_pop_si() /* Opcode 0x5e */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[SI]);
+}
+
+inline void I86::_pop_di() /* Opcode 0x5f */
+{
+ icount -= timing.pop_r16;
+ POP(regs.w[DI]);
+}
+
+inline void I86::_pusha() /* Opcode 0x60 */
+{
+ unsigned tmp = regs.w[SP];
+
+ icount -= timing.pusha;
+ PUSH(regs.w[AX]);
+ PUSH(regs.w[CX]);
+ PUSH(regs.w[DX]);
+ PUSH(regs.w[BX]);
+ PUSH(tmp);
+ PUSH(regs.w[BP]);
+ PUSH(regs.w[SI]);
+ PUSH(regs.w[DI]);
+}
+
+inline void I86::_popa() /* Opcode 0x61 */
+{
+ unsigned tmp;
+
+ icount -= timing.popa;
+ POP(regs.w[DI]);
+ POP(regs.w[SI]);
+ POP(regs.w[BP]);
+ POP(tmp);
+ POP(regs.w[BX]);
+ POP(regs.w[DX]);
+ POP(regs.w[CX]);
+ POP(regs.w[AX]);
+}
+
+inline void I86::_bound() /* Opcode 0x62 */
+{
+ unsigned ModRM = FETCHOP;
+ int low = (int16_t)GetRMWord(ModRM);
+ int high = (int16_t)GetNextRMWord;
+ int tmp = (int16_t)RegWord(ModRM);
+ if(tmp < low || tmp>high) {
+ pc -= (seg_prefix ? 3 : 2);
+ interrupt(BOUNDS_CHECK_FAULT);
+ }
+ icount -= timing.bound;
+}
+
+inline void I86::_repc(int flagval)
+{
+#ifdef HAS_V30
+ unsigned next = FETCHOP;
+ unsigned count = regs.w[CX];
+
+ switch(next) {
+ case 0x26: /* ES: */
+ seg_prefix = true;
+ prefix_seg = ES;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x2e: /* CS: */
+ seg_prefix = true;
+ prefix_seg = CS;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x36: /* SS: */
+ seg_prefix = true;
+ prefix_seg = SS;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x3e: /* DS: */
+ seg_prefix = true;
+ prefix_seg = DS;
+ icount -= 2;
+ _repc(flagval);
+ break;
+ case 0x6c: /* REP INSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _insb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6d: /* REP INSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _insw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6e: /* REP OUTSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _outsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6f: /* REP OUTSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _outsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa4: /* REP MOVSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _movsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa5: /* REP MOVSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _movsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa6: /* REP(N)E CMPSB */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _cmpsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa7: /* REP(N)E CMPSW */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _cmpsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaa: /* REP STOSB */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _stosb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xab: /* REP STOSW */
+ icount -= 9 - count;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _stosw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xac: /* REP LODSB */
+ icount -= 9;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _lodsb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xad: /* REP LODSW */
+ icount -= 9;
+ for(; (CF == flagval) && (count > 0); count--) {
+ _lodsw();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xae: /* REP(N)E SCASB */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _scasb();
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaf: /* REP(N)E SCASW */
+ icount -= 9;
+ for(ZeroVal = !flagval; (ZF == flagval) && (CF == flagval) && (count > 0); count--) {
+ _scasw();
+ }
+ regs.w[CX] = count;
+ break;
+ default:
+ instruction(next);
+ }
+#endif
+}
+
+inline void I86::_push_d16() /* Opcode 0x68 */
+{
+ unsigned tmp = FETCH;
+ icount -= timing.push_imm;
+ tmp += FETCH << 8;
+ PUSH(tmp);
+}
+
+inline void I86::_imul_d16() /* Opcode 0x69 */
+{
+ DEF_r16w(dst, src);
+ unsigned src2 = FETCH;
+ src += (FETCH << 8);
+ icount -= (ModRM >= 0xc0) ? timing.imul_rri16 : timing.imul_rmi16;
+ dst = (int32_t)((int16_t)src) * (int32_t)((int16_t)src2);
+ CarryVal = OverVal = (((int32_t)dst) >> 15 != 0) && (((int32_t)dst) >> 15 != -1);
+ RegWord(ModRM) = (uint16_t)dst;
+}
+
+inline void I86::_push_d8() /* Opcode 0x6a */
+{
+ unsigned tmp = (uint16_t)((int16_t)((int8_t)FETCH));
+ icount -= timing.push_imm;
+ PUSH(tmp);
+}
+
+inline void I86::_imul_d8() /* Opcode 0x6b */
+{
+ DEF_r16w(dst, src);
+ unsigned src2 = (uint16_t)((int16_t)((int8_t)FETCH));
+ icount -= (ModRM >= 0xc0) ? timing.imul_rri8 : timing.imul_rmi8;
+ dst = (int32_t)((int16_t)src) * (int32_t)((int16_t)src2);
+ CarryVal = OverVal = (((int32_t)dst) >> 15 != 0) && (((int32_t)dst) >> 15 != -1);
+ RegWord(ModRM) = (uint16_t)dst;
+}
+
+inline void I86::_insb() /* Opcode 0x6c */
+{
+ icount -= timing.ins8;
+ PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
+ regs.w[DI] += DirVal;
+}
+
+inline void I86::_insw() /* Opcode 0x6d */
+{
+ icount -= timing.ins16;
+ PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
+ regs.w[DI] += 2 * DirVal;
+}
+
+inline void I86::_outsb() /* Opcode 0x6e */
+{
+ icount -= timing.outs8;
+ write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
+ regs.w[SI] += DirVal; /* GOL 11/27/01 */
+}
+
+inline void I86::_outsw() /* Opcode 0x6f */
+{
+ icount -= timing.outs16;
+ write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
+ regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
+}
+
+inline void I86::_jo() /* Opcode 0x70 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(OF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jno() /* Opcode 0x71 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!OF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jb() /* Opcode 0x72 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(CF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnb() /* Opcode 0x73 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!CF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jz() /* Opcode 0x74 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnz() /* Opcode 0x75 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jbe() /* Opcode 0x76 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(CF || ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnbe() /* Opcode 0x77 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!(CF || ZF)) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_js() /* Opcode 0x78 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(SF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jns() /* Opcode 0x79 */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!SF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jp() /* Opcode 0x7a */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(PF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnp() /* Opcode 0x7b */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(!PF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jl() /* Opcode 0x7c */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if((SF!= OF) && !ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnl() /* Opcode 0x7d */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(ZF || (SF == OF)) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jle() /* Opcode 0x7e */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if(ZF || (SF!= OF)) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_jnle() /* Opcode 0x7f */
+{
+ int tmp = (int)((int8_t)FETCH);
+ if((SF == OF) && !ZF) {
+ pc += tmp;
+ icount -= timing.jcc_t;
+ } else {
+ icount -= timing.jcc_nt;
+ }
+}
+
+inline void I86::_80pre() /* Opcode 0x80 */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD eb, d8 */
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 1: /* OR eb, d8 */
+ ORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 2: /* ADC eb, d8 */
+ src += CF;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 3: /* SBB eb, b8 */
+ src += CF;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 4: /* AND eb, d8 */
+ ANDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 5: /* SUB eb, d8 */
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 6: /* XOR eb, d8 */
+ XORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 7: /* CMP eb, d8 */
+ SUBB(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_81pre() /* Opcode 0x81 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = FETCH;
+ src += (FETCH << 8);
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD ew, d16 */
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 1: /* OR ew, d16 */
+ ORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 2: /* ADC ew, d16 */
+ src += CF;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 3: /* SBB ew, d16 */
+ src += CF;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 4: /* AND ew, d16 */
+ ANDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 5: /* SUB ew, d16 */
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 6: /* XOR ew, d16 */
+ XORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;
+ break;
+ case 7: /* CMP ew, d16 */
+ SUBW(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_82pre() /* Opcode 0x82 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMByte(ModRM);
+ unsigned src = FETCH;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD eb, d8 */
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 1: /* OR eb, d8 */
+ ORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 2: /* ADC eb, d8 */
+ src += CF;
+ ADDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 3: /* SBB eb, d8 */
+ src += CF;
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 4: /* AND eb, d8 */
+ ANDB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 5: /* SUB eb, d8 */
+ SUBB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 6: /* XOR eb, d8 */
+ XORB(dst, src);
+ PutbackRMByte(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;
+ break;
+ case 7: /* CMP eb, d8 */
+ SUBB(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_83pre() /* Opcode 0x83 */
+{
+ unsigned ModRM = FETCH;
+ unsigned dst = GetRMWord(ModRM);
+ unsigned src = (uint16_t)((int16_t)((int8_t)FETCH));
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* ADD ew, d16 */
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 1: /* OR ew, d16 */
+ ORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 2: /* ADC ew, d16 */
+ src += CF;
+ ADDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 3: /* SBB ew, d16 */
+ src += CF;
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 4: /* AND ew, d16 */
+ ANDW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 5: /* SUB ew, d16 */
+ SUBW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 6: /* XOR ew, d16 */
+ XORW(dst, src);
+ PutbackRMWord(ModRM, dst);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;
+ break;
+ case 7: /* CMP ew, d16 */
+ SUBW(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_test_br8() /* Opcode 0x84 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;
+ ANDB(dst, src);
+}
+
+inline void I86::_test_wr16() /* Opcode 0x85 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;
+ ANDW(dst, src);
+}
+
+inline void I86::_xchg_br8() /* Opcode 0x86 */
+{
+ DEF_br8(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;
+ RegByte(ModRM) = dst;
+ PutbackRMByte(ModRM, src);
+}
+
+inline void I86::_xchg_wr16() /* Opcode 0x87 */
+{
+ DEF_wr16(dst, src);
+ icount -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;
+ RegWord(ModRM) = dst;
+ PutbackRMWord(ModRM, src);
+}
+
+inline void I86::_mov_br8() /* Opcode 0x88 */
+{
+ unsigned ModRM = FETCH;
+ uint8_t src = RegByte(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;
+ PutRMByte(ModRM, src);
+}
+
+inline void I86::_mov_wr16() /* Opcode 0x89 */
+{
+ unsigned ModRM = FETCH;
+ uint16_t src = RegWord(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;
+ PutRMWord(ModRM, src);
+}
+
+inline void I86::_mov_r8b() /* Opcode 0x8a */
+{
+ unsigned ModRM = FETCH;
+ uint8_t src = GetRMByte(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;
+ RegByte(ModRM) = src;
+}
+
+inline void I86::_mov_r16w() /* Opcode 0x8b */
+{
+ unsigned ModRM = FETCH;
+ uint16_t src = GetRMWord(ModRM);
+ icount -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;
+ RegWord(ModRM) = src;
+}
+
+inline void I86::_mov_wsreg() /* Opcode 0x8c */
+{
+ unsigned ModRM = FETCH;
+ icount -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;
+ if(ModRM & 0x20) {
+ return; /* 1xx is invalid */
+ }
+ PutRMWord(ModRM, sregs[(ModRM & 0x38) >> 3]);
+}
+
+inline void I86::_lea() /* Opcode 0x8d */
+{
+ unsigned ModRM = FETCH;
+ icount -= timing.lea;
+ GetEA(ModRM);
+ RegWord(ModRM) = eo; /* effective offset (no segment part) */
+}
+
+inline void I86::_mov_sregw() /* Opcode 0x8e */
+{
+ unsigned ModRM = FETCH;
+ uint16_t src = GetRMWord(ModRM);
+
+ icount -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;
+ switch((ModRM >> 3) & 7) {
+ case 0: /* mov es, ew */
+ sregs[ES] = src;
+ base[ES] = SegBase(ES);
+ break;
+ case 1: /* mov cs, ew */
+ break; /* doesn't do a jump far */
+ case 2: /* mov ss, ew */
+ sregs[SS] = src;
+ base[SS] = SegBase(SS); /* no interrupt allowed before next instr */
+ instruction(FETCHOP);
+ break;
+ case 3: /* mov ds, ew */
+ sregs[DS] = src;
+ base[DS] = SegBase(DS);
+ break;
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_popw() /* Opcode 0x8f */
+{
+ unsigned ModRM = FETCH;
+ uint16_t tmp;
+ POP(tmp);
+ icount -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;
+ PutRMWord(ModRM, tmp);
+}
+
+#define XchgAXReg(Reg) { \
+ uint16_t tmp; \
+ tmp = regs.w[Reg]; \
+ regs.w[Reg] = regs.w[AX]; \
+ regs.w[AX] = tmp; \
+ icount -= timing.xchg_ar16; \
+}
+
+inline void I86::_nop() /* Opcode 0x90 */
+{
+ /* this is XchgAXReg(AX); */
+ icount -= timing.nop;
+}
+
+inline void I86::_xchg_axcx() /* Opcode 0x91 */
+{
+ XchgAXReg(CX);
+}
+
+inline void I86::_xchg_axdx() /* Opcode 0x92 */
+{
+ XchgAXReg(DX);
+}
+
+inline void I86::_xchg_axbx() /* Opcode 0x93 */
+{
+ XchgAXReg(BX);
+}
+
+inline void I86::_xchg_axsp() /* Opcode 0x94 */
+{
+ XchgAXReg(SP);
+}
+
+inline void I86::_xchg_axbp() /* Opcode 0x95 */
+{
+ XchgAXReg(BP);
+}
+
+inline void I86::_xchg_axsi() /* Opcode 0x96 */
+{
+ XchgAXReg(SI);
+}
+
+inline void I86::_xchg_axdi() /* Opcode 0x97 */
+{
+ XchgAXReg(DI);
+}
+
+inline void I86::_cbw() /* Opcode 0x98 */
+{
+ icount -= timing.cbw;
+ regs.b[AH] = (regs.b[AL] & 0x80) ? 0xff : 0;
+}
+
+inline void I86::_cwd() /* Opcode 0x99 */
+{
+ icount -= timing.cwd;
+ regs.w[DX] = (regs.b[AH] & 0x80) ? 0xffff : 0;
+}
+
+inline void I86::_call_far() /* Opcode 0x9a */
+{
+ unsigned tmp, tmp2;
+ uint16_t ip;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ ip = pc - base[CS];
+ PUSH(sregs[CS]);
+ PUSH(ip);
+ sregs[CS] = (uint16_t)tmp2;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + (uint16_t)tmp) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _retf();
+ }
+#endif
+ icount -= timing.call_far;
+}
+
+inline void I86::_wait() /* Opcode 0x9b */
+{
+ if(test_state) {
+ pc--;
+ }
+ icount -= timing.wait;
+}
+
+inline void I86::_pushf() /* Opcode 0x9c */
+{
+ unsigned tmp;
+ icount -= timing.pushf;
+
+ tmp = CompressFlags();
+ PUSH(tmp | 0xf000);
+}
+
+inline void I86::_popf() /* Opcode 0x9d */
+{
+ unsigned tmp;
+ POP(tmp);
+ icount -= timing.popf;
+ ExpandFlags(tmp);
+
+ if(TF) {
+ trap();
+ }
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if(IF && (int_state & INT_REQ_BIT)) {
+ interrupt(-1);
+ }
+}
+
+inline void I86::_sahf() /* Opcode 0x9e */
+{
+ unsigned tmp = (CompressFlags() & 0xff00) | (regs.b[AH] & 0xd5);
+ icount -= timing.sahf;
+ ExpandFlags(tmp);
+}
+
+inline void I86::_lahf() /* Opcode 0x9f */
+{
+ regs.b[AH] = CompressFlags() & 0xff;
+ icount -= timing.lahf;
+}
+
+inline void I86::_mov_aldisp() /* Opcode 0xa0 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_am8;
+ regs.b[AL] = GetMemB(DS, addr);
+}
+
+inline void I86::_mov_axdisp() /* Opcode 0xa1 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_am16;
+ regs.w[AX] = GetMemW(DS, addr);
+}
+
+inline void I86::_mov_dispal() /* Opcode 0xa2 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_ma8;
+ PutMemB(DS, addr, regs.b[AL]);
+}
+
+inline void I86::_mov_dispax() /* Opcode 0xa3 */
+{
+ unsigned addr;
+
+ addr = FETCH;
+ addr += FETCH << 8;
+
+ icount -= timing.mov_ma16;
+ PutMemW(DS, addr, regs.w[AX]);
+}
+
+inline void I86::_movsb() /* Opcode 0xa4 */
+{
+ uint8_t tmp = GetMemB(DS, regs.w[SI]);
+ PutMemB(ES, regs.w[DI], tmp);
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.movs8;
+}
+
+inline void I86::_movsw() /* Opcode 0xa5 */
+{
+ uint16_t tmp = GetMemW(DS, regs.w[SI]);
+ PutMemW(ES, regs.w[DI], tmp);
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.movs16;
+}
+
+inline void I86::_cmpsb() /* Opcode 0xa6 */
+{
+ unsigned dst = GetMemB(ES, regs.w[DI]);
+ unsigned src = GetMemB(DS, regs.w[SI]);
+ SUBB(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.cmps8;
+}
+
+inline void I86::_cmpsw() /* Opcode 0xa7 */
+{
+ unsigned dst = GetMemW(ES, regs.w[DI]);
+ unsigned src = GetMemW(DS, regs.w[SI]);
+ SUBW(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.cmps16;
+}
+
+inline void I86::_test_ald8() /* Opcode 0xa8 */
+{
+ DEF_ald8(dst, src);
+ icount -= timing.alu_ri8;
+ ANDB(dst, src);
+}
+
+inline void I86::_test_axd16() /* Opcode 0xa9 */
+{
+ DEF_axd16(dst, src);
+ icount -= timing.alu_ri16;
+ ANDW(dst, src);
+}
+
+inline void I86::_stosb() /* Opcode 0xaa */
+{
+ PutMemB(ES, regs.w[DI], regs.b[AL]);
+ regs.w[DI] += DirVal;
+ icount -= timing.stos8;
+}
+
+inline void I86::_stosw() /* Opcode 0xab */
+{
+ PutMemW(ES, regs.w[DI], regs.w[AX]);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.stos16;
+}
+
+inline void I86::_lodsb() /* Opcode 0xac */
+{
+ regs.b[AL] = GetMemB(DS, regs.w[SI]);
+ regs.w[SI] += DirVal;
+ icount -= timing.lods8;
+}
+
+inline void I86::_lodsw() /* Opcode 0xad */
+{
+ regs.w[AX] = GetMemW(DS, regs.w[SI]);
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.lods16;
+}
+
+inline void I86::_scasb() /* Opcode 0xae */
+{
+ unsigned src = GetMemB(ES, regs.w[DI]);
+ unsigned dst = regs.b[AL];
+ SUBB(dst, src);
+ regs.w[DI] += DirVal;
+ icount -= timing.scas8;
+}
+
+inline void I86::_scasw() /* Opcode 0xaf */
+{
+ unsigned src = GetMemW(ES, regs.w[DI]);
+ unsigned dst = regs.w[AX];
+ SUBW(dst, src);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.scas16;
+}
+
+inline void I86::_mov_ald8() /* Opcode 0xb0 */
+{
+ regs.b[AL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_cld8() /* Opcode 0xb1 */
+{
+ regs.b[CL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_dld8() /* Opcode 0xb2 */
+{
+ regs.b[DL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_bld8() /* Opcode 0xb3 */
+{
+ regs.b[BL] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_ahd8() /* Opcode 0xb4 */
+{
+ regs.b[AH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_chd8() /* Opcode 0xb5 */
+{
+ regs.b[CH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_dhd8() /* Opcode 0xb6 */
+{
+ regs.b[DH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_bhd8() /* Opcode 0xb7 */
+{
+ regs.b[BH] = FETCH;
+ icount -= timing.mov_ri8;
+}
+
+inline void I86::_mov_axd16() /* Opcode 0xb8 */
+{
+ regs.b[AL] = FETCH;
+ regs.b[AH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_cxd16() /* Opcode 0xb9 */
+{
+ regs.b[CL] = FETCH;
+ regs.b[CH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_dxd16() /* Opcode 0xba */
+{
+ regs.b[DL] = FETCH;
+ regs.b[DH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_bxd16() /* Opcode 0xbb */
+{
+ regs.b[BL] = FETCH;
+ regs.b[BH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_spd16() /* Opcode 0xbc */
+{
+ regs.b[SPL] = FETCH;
+ regs.b[SPH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_bpd16() /* Opcode 0xbd */
+{
+ regs.b[BPL] = FETCH;
+ regs.b[BPH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_sid16() /* Opcode 0xbe */
+{
+ regs.b[SIL] = FETCH;
+ regs.b[SIH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_mov_did16() /* Opcode 0xbf */
+{
+ regs.b[DIL] = FETCH;
+ regs.b[DIH] = FETCH;
+ icount -= timing.mov_ri16;
+}
+
+inline void I86::_rotshft_bd8() /* Opcode 0xc0 */
+{
+ unsigned ModRM = FETCH;
+ unsigned count = FETCH;
+
+ rotate_shift_byte(ModRM, count);
+}
+
+inline void I86::_rotshft_wd8() /* Opcode 0xc1 */
+{
+ unsigned ModRM = FETCH;
+ unsigned count = FETCH;
+
+ rotate_shift_word(ModRM, count);
+}
+
+inline void I86::_ret_d16() /* Opcode 0xc2 */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+ POP(pc);
+ pc = (pc + base[CS]) & AMASK;
+ regs.w[SP] += count;
+ icount -= timing.ret_near_imm;
+}
+
+inline void I86::_ret() /* Opcode 0xc3 */
+{
+ POP(pc);
+ pc = (pc + base[CS]) & AMASK;
+ icount -= timing.ret_near;
+}
+
+inline void I86::_les_dw() /* Opcode 0xc4 */
+{
+ unsigned ModRM = FETCH;
+ uint16_t tmp = GetRMWord(ModRM);
+ RegWord(ModRM) = tmp;
+ sregs[ES] = GetNextRMWord;
+ base[ES] = SegBase(ES);
+ icount -= timing.load_ptr;
+}
+
+inline void I86::_lds_dw() /* Opcode 0xc5 */
+{
+ unsigned ModRM = FETCH;
+ uint16_t tmp = GetRMWord(ModRM);
+ RegWord(ModRM) = tmp;
+ sregs[DS] = GetNextRMWord;
+ base[DS] = SegBase(DS);
+ icount -= timing.load_ptr;
+}
+
+inline void I86::_mov_bd8() /* Opcode 0xc6 */
+{
+ unsigned ModRM = FETCH;
+ icount -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;
+ PutImmRMByte(ModRM);
+}
+
+inline void I86::_mov_wd16() /* Opcode 0xc7 */
+{
+ unsigned ModRM = FETCH;
+ icount -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;
+ PutImmRMWord(ModRM);
+}
+
+inline void I86::_enter() /* Opcode 0xc8 */
+{
+ unsigned nb = FETCH;
+ unsigned i, level;
+
+ nb += FETCH << 8;
+ level = FETCH;
+ icount -= (level == 0) ? timing.enter0 : (level == 1) ? timing.enter1 : timing.enter_base + level * timing.enter_count;
+ PUSH(regs.w[BP]);
+ regs.w[BP] = regs.w[SP];
+ regs.w[SP] -= nb;
+ for(i = 1; i < level; i++) {
+ PUSH(GetMemW(SS, regs.w[BP] - i * 2));
+ }
+ if(level) {
+ PUSH(regs.w[BP]);
+ }
+}
+
+inline void I86::_leav() /* Opcode 0xc9 */
+{
+ icount -= timing.leave;
+ regs.w[SP] = regs.w[BP];
+ POP(regs.w[BP]);
+}
+
+inline void I86::_retf_d16() /* Opcode 0xca */
+{
+ unsigned count = FETCH;
+ count += FETCH << 8;
+ POP(pc);
+ POP(sregs[CS]);
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ regs.w[SP] += count;
+ icount -= timing.ret_far_imm;
+}
+
+inline void I86::_retf() /* Opcode 0xcb */
+{
+ POP(pc);
+ POP(sregs[CS]);
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ icount -= timing.ret_far;
+}
+
+inline void I86::_int3() /* Opcode 0xcc */
+{
+ icount -= timing.int3;
+ interrupt(3);
+}
+
+inline void I86::_int() /* Opcode 0xcd */
+{
+ unsigned int_num = FETCH;
+ icount -= timing.int_imm;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_int_i86(int_num, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ return;
+ }
+#endif
+ interrupt(int_num);
+}
+
+inline void I86::_into() /* Opcode 0xce */
+{
+ if(OF) {
+ icount -= timing.into_t;
+ interrupt(OVERFLOW_TRAP);
+ } else {
+ icount -= timing.into_nt;
+ }
+}
+
+inline void I86::_iret() /* Opcode 0xcf */
+{
+ icount -= timing.iret;
+ POP(pc);
+ POP(sregs[CS]);
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ _popf();
+
+ /* if the IF is set, and an interrupt is pending, signal an interrupt */
+ if(IF && (int_state & INT_REQ_BIT)) {
+ interrupt(-1);
+ }
+}
+
+inline void I86::_rotshft_b() /* Opcode 0xd0 */
+{
+ rotate_shift_byte(FETCHOP, 1);
+}
+
+inline void I86::_rotshft_w() /* Opcode 0xd1 */
+{
+ rotate_shift_word(FETCHOP, 1);
+}
+
+inline void I86::_rotshft_bcl() /* Opcode 0xd2 */
+{
+ rotate_shift_byte(FETCHOP, regs.b[CL]);
+}
+
+inline void I86::_rotshft_wcl() /* Opcode 0xd3 */
+{
+ rotate_shift_word(FETCHOP, regs.b[CL]);
+}
+
+/* OB: Opcode works on NEC V-Series but not the Variants */
+/* one could specify any byte value as operand but the NECs */
+/* always substitute 0x0a. */
+inline void I86::_aam() /* Opcode 0xd4 */
+{
+ unsigned mult = FETCH;
+ icount -= timing.aam;
+ if(mult == 0) {
+ interrupt(DIVIDE_FAULT);
+ } else {
+ regs.b[AH] = regs.b[AL] / mult;
+ regs.b[AL] %= mult;
+ SetSZPF_Word(regs.w[AX]);
+ }
+}
+
+inline void I86::_aad() /* Opcode 0xd5 */
+{
+ unsigned mult = FETCH;
+ icount -= timing.aad;
+#ifdef HAS_V30
+ regs.b[AL] = regs.b[AH] * 10 + regs.b[AL];
+#else
+ regs.b[AL] = regs.b[AH] * mult + regs.b[AL];
+#endif
+ regs.b[AH] = 0;
+ SetZF(regs.b[AL]);
+ SetPF(regs.b[AL]);
+ SignVal = 0;
+}
+
+inline void I86::_setalc() /* Opcode 0xd6 */
+{
+ regs.b[AL] = (CF) ? 0xff : 0x00;
+ icount -= 3;
+}
+
+inline void I86::_xlat() /* Opcode 0xd7 */
+{
+ unsigned dest = regs.w[BX] + regs.b[AL];
+ icount -= timing.xlat;
+ regs.b[AL] = GetMemB(DS, dest);
+}
+
+inline void I86::_escape() /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */
+{
+ unsigned ModRM = FETCH;
+ icount -= timing.nop;
+ GetRMByte(ModRM);
+}
+
+inline void I86::_loopne() /* Opcode 0xe0 */
+{
+ int disp = (int)((int8_t)FETCH);
+ unsigned tmp = regs.w[CX] - 1;
+ regs.w[CX] = tmp;
+ if(!ZF && tmp) {
+ icount -= timing.loop_t;
+ pc += disp;
+ } else {
+ icount -= timing.loop_nt;
+ }
+}
+
+inline void I86::_loope() /* Opcode 0xe1 */
+{
+ int disp = (int)((int8_t)FETCH);
+ unsigned tmp = regs.w[CX] - 1;
+ regs.w[CX] = tmp;
+ if(ZF && tmp) {
+ icount -= timing.loope_t;
+ pc += disp;
+ } else {
+ icount -= timing.loope_nt;
+ }
+}
+
+inline void I86::_loop() /* Opcode 0xe2 */
+{
+ int disp = (int)((int8_t)FETCH);
+ unsigned tmp = regs.w[CX] - 1;
+ regs.w[CX] = tmp;
+ if(tmp) {
+ icount -= timing.loop_t;
+ pc += disp;
+ } else {
+ icount -= timing.loop_nt;
+ }
+}
+
+inline void I86::_jcxz() /* Opcode 0xe3 */
+{
+ int disp = (int)((int8_t)FETCH);
+ if(regs.w[CX] == 0) {
+ icount -= timing.jcxz_t;
+ pc += disp;
+ } else {
+ icount -= timing.jcxz_nt;
+ }
+}
+
+inline void I86::_inal() /* Opcode 0xe4 */
+{
+ unsigned port = FETCH;
+ icount -= timing.in_imm8;
+ regs.b[AL] = read_port_byte(port);
+}
+
+inline void I86::_inax() /* Opcode 0xe5 */
+{
+ unsigned port = FETCH;
+ icount -= timing.in_imm16;
+ regs.w[AX] = read_port_word(port);
+}
+
+inline void I86::_outal() /* Opcode 0xe6 */
+{
+ unsigned port = FETCH;
+ icount -= timing.out_imm8;
+ write_port_byte(port, regs.b[AL]);
+}
+
+inline void I86::_outax() /* Opcode 0xe7 */
+{
+ unsigned port = FETCH;
+ icount -= timing.out_imm16;
+ write_port_word(port, regs.w[AX]);
+}
+
+inline void I86::_call_d16() /* Opcode 0xe8 */
+{
+ uint16_t ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = pc - base[CS];
+ PUSH(ip);
+ ip += tmp;
+ pc = (ip + base[CS]) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _ret();
+ }
+#endif
+ icount -= timing.call_near;
+}
+
+inline void I86::_jmp_d16() /* Opcode 0xe9 */
+{
+ uint16_t ip, tmp;
+
+ FETCHWORD(tmp);
+ ip = pc - base[CS] + tmp;
+ pc = (ip + base[CS]) & AMASK;
+ icount -= timing.jmp_near;
+}
+
+inline void I86::_jmp_far() /* Opcode 0xea */
+{
+ unsigned tmp, tmp1;
+
+ tmp = FETCH;
+ tmp += FETCH << 8;
+
+ tmp1 = FETCH;
+ tmp1 += FETCH << 8;
+
+ sregs[CS] = (uint16_t)tmp1;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + tmp) & AMASK;
+ icount -= timing.jmp_far;
+}
+
+inline void I86::_jmp_d8() /* Opcode 0xeb */
+{
+ int tmp = (int)((int8_t)FETCH);
+ pc += tmp;
+ icount -= timing.jmp_short;
+}
+
+inline void I86::_inaldx() /* Opcode 0xec */
+{
+ icount -= timing.in_dx8;
+ regs.b[AL] = read_port_byte(regs.w[DX]);
+}
+
+inline void I86::_inaxdx() /* Opcode 0xed */
+{
+ unsigned port = regs.w[DX];
+ icount -= timing.in_dx16;
+ regs.w[AX] = read_port_word(port);
+}
+
+inline void I86::_outdxal() /* Opcode 0xee */
+{
+ icount -= timing.out_dx8;
+ write_port_byte(regs.w[DX], regs.b[AL]);
+}
+
+inline void I86::_outdxax() /* Opcode 0xef */
+{
+ unsigned port = regs.w[DX];
+ icount -= timing.out_dx16;
+ write_port_word(port, regs.w[AX]);
+}
+
+/* I think thats not a V20 instruction...*/
+inline void I86::_lock() /* Opcode 0xf0 */
+{
+ icount -= timing.nop;
+ instruction(FETCHOP); /* un-interruptible */
+}
+
+inline void I86::_rep(int flagval)
+{
+ /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the
+ loop to continue for CMPS and SCAS instructions. */
+
+ unsigned next = FETCHOP;
+ unsigned count = regs.w[CX];
+
+ switch(next) {
+ case 0x26: /* ES: */
+ seg_prefix = true;
+ prefix_seg = ES;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+ case 0x2e: /* CS: */
+ seg_prefix = true;
+ prefix_seg = CS;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+ case 0x36: /* SS: */
+ seg_prefix = true;
+ prefix_seg = SS;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+ case 0x3e: /* DS: */
+ seg_prefix = true;
+ prefix_seg = DS;
+ icount -= timing.override;
+ _rep(flagval);
+ break;
+#ifndef HAS_I86
+ case 0x6c: /* REP INSB */
+ icount -= timing.rep_ins8_base;
+ for(; count > 0; count--) {
+ PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX]));
+ regs.w[DI] += DirVal;
+ icount -= timing.rep_ins8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6d: /* REP INSW */
+ icount -= timing.rep_ins16_base;
+ for(; count > 0; count--) {
+ PutMemW(ES, regs.w[DI], read_port_word(regs.w[DX]));
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.rep_ins16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6e: /* REP OUTSB */
+ icount -= timing.rep_outs8_base;
+ for(; count > 0; count--) {
+ write_port_byte(regs.w[DX], GetMemB(DS, regs.w[SI]));
+ regs.w[SI] += DirVal; /* GOL 11/27/01 */
+ icount -= timing.rep_outs8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0x6f: /* REP OUTSW */
+ icount -= timing.rep_outs16_base;
+ for(; count > 0; count--) {
+ write_port_word(regs.w[DX], GetMemW(DS, regs.w[SI]));
+ regs.w[SI] += 2 * DirVal; /* GOL 11/27/01 */
+ icount -= timing.rep_outs16_count;
+ }
+ regs.w[CX] = count;
+ break;
+#endif
+ case 0xa4: /* REP MOVSB */
+ icount -= timing.rep_movs8_base;
+ for(; count > 0; count--) {
+ uint8_t tmp;
+ tmp = GetMemB(DS, regs.w[SI]);
+ PutMemB(ES, regs.w[DI], tmp);
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.rep_movs8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa5: /* REP MOVSW */
+ icount -= timing.rep_movs16_base;
+ for(; count > 0; count--) {
+ uint16_t tmp;
+ tmp = GetMemW(DS, regs.w[SI]);
+ PutMemW(ES, regs.w[DI], tmp);
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.rep_movs16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa6: /* REP(N)E CMPSB */
+ icount -= timing.rep_cmps8_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned dst, src;
+ dst = GetMemB(ES, regs.w[DI]);
+ src = GetMemB(DS, regs.w[SI]);
+ SUBB(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += DirVal;
+ regs.w[SI] += DirVal;
+ icount -= timing.rep_cmps8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xa7: /* REP(N)E CMPSW */
+ icount -= timing.rep_cmps16_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned dst, src;
+ dst = GetMemW(ES, regs.w[DI]);
+ src = GetMemW(DS, regs.w[SI]);
+ SUBW(src, dst); /* opposite of the usual convention */
+ regs.w[DI] += 2 * DirVal;
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.rep_cmps16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaa: /* REP STOSB */
+ icount -= timing.rep_stos8_base;
+ for(; count > 0; count--) {
+ PutMemB(ES, regs.w[DI], regs.b[AL]);
+ regs.w[DI] += DirVal;
+ icount -= timing.rep_stos8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xab: /* REP STOSW */
+ icount -= timing.rep_stos16_base;
+ for(; count > 0; count--) {
+ PutMemW(ES, regs.w[DI], regs.w[AX]);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.rep_stos16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xac: /* REP LODSB */
+ icount -= timing.rep_lods8_base;
+ for(; count > 0; count--) {
+ regs.b[AL] = GetMemB(DS, regs.w[SI]);
+ regs.w[SI] += DirVal;
+ icount -= timing.rep_lods8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xad: /* REP LODSW */
+ icount -= timing.rep_lods16_base;
+ for(; count > 0; count--) {
+ regs.w[AX] = GetMemW(DS, regs.w[SI]);
+ regs.w[SI] += 2 * DirVal;
+ icount -= timing.rep_lods16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xae: /* REP(N)E SCASB */
+ icount -= timing.rep_scas8_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned src, dst;
+ src = GetMemB(ES, regs.w[DI]);
+ dst = regs.b[AL];
+ SUBB(dst, src);
+ regs.w[DI] += DirVal;
+ icount -= timing.rep_scas8_count;
+ }
+ regs.w[CX] = count;
+ break;
+ case 0xaf: /* REP(N)E SCASW */
+ icount -= timing.rep_scas16_base;
+ for(ZeroVal = !flagval; (ZF == flagval) && (count > 0); count--) {
+ unsigned src, dst;
+ src = GetMemW(ES, regs.w[DI]);
+ dst = regs.w[AX];
+ SUBW(dst, src);
+ regs.w[DI] += 2 * DirVal;
+ icount -= timing.rep_scas16_count;
+ }
+ regs.w[CX] = count;
+ break;
+ default:
+ instruction(next);
+ }
+}
+
+inline void I86::_repne() /* Opcode 0xf2 */
+{
+ _rep(0);
+}
+
+inline void I86::_repe() /* Opcode 0xf3 */
+{
+ _rep(1);
+}
+
+inline void I86::_hlt() /* Opcode 0xf4 */
+{
+ pc--;
+ halted = true;
+ icount -= 2;
+}
+
+inline void I86::_cmc() /* Opcode 0xf5 */
+{
+ icount -= timing.flag_ops;
+ CarryVal = !CF;
+}
+
+inline void I86::_f6pre() /* Opcode 0xf6 */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = (unsigned)GetRMByte(ModRM);
+ unsigned tmp2;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* TEST Eb, data8 */
+ case 1: /* ??? */
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;
+ tmp &= FETCH;
+
+ CarryVal = OverVal = AuxVal = 0;
+ SetSZPF_Byte(tmp);
+ break;
+
+ case 2: /* NOT Eb */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ PutbackRMByte(ModRM, ~tmp);
+ break;
+
+ case 3: /* NEG Eb */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;
+ tmp2 = 0;
+ SUBB(tmp2, tmp);
+ PutbackRMByte(ModRM, tmp2);
+ break;
+
+ case 4: /* MUL AL, Eb */
+ icount -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;
+ {
+ uint16_t result;
+
+ tmp2 = regs.b[AL];
+
+ SetSF((int8_t)tmp2);
+ SetPF(tmp2);
+
+ result = (uint16_t)tmp2 * tmp;
+ regs.w[AX] = (uint16_t)result;
+
+ SetZF(regs.w[AX]);
+ CarryVal = OverVal = (regs.b[AH] != 0);
+ }
+ break;
+
+ case 5: /* IMUL AL, Eb */
+ icount -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;
+ {
+ int16_t result;
+
+ tmp2 = (unsigned)regs.b[AL];
+
+ SetSF((int8_t)tmp2);
+ SetPF(tmp2);
+
+ result = (int16_t)((int8_t)tmp2) * (int16_t)((int8_t)tmp);
+ regs.w[AX] = (uint16_t)result;
+
+ SetZF(regs.w[AX]);
+ CarryVal = OverVal = (result >> 7 != 0) && (result >> 7 != -1);
+ }
+ break;
+
+ case 6: /* DIV AL, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;
+ {
+ uint16_t result;
+
+ result = regs.w[AX];
+
+ if(tmp) {
+ if((result / tmp) > 0xff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.b[AH] = result % tmp;
+ regs.b[AL] = result / tmp;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+ case 7: /* IDIV AL, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;
+ {
+ int16_t result;
+
+ result = regs.w[AX];
+
+ if(tmp) {
+ tmp2 = result % (int16_t)((int8_t)tmp);
+
+ if((result /= (int16_t)((int8_t)tmp)) > 0xff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.b[AL] = (uint8_t)result;
+ regs.b[AH] = tmp2;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_f7pre() /* Opcode 0xf7 */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMWord(ModRM);
+ unsigned tmp2;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* TEST Ew, data16 */
+ case 1: /* ??? */
+ icount -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;
+ tmp2 = FETCH;
+ tmp2 += FETCH << 8;
+
+ tmp &= tmp2;
+
+ CarryVal = OverVal = AuxVal = 0;
+ SetSZPF_Word(tmp);
+ break;
+
+ case 2: /* NOT Ew */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp = ~tmp;
+ PutbackRMWord(ModRM, tmp);
+ break;
+
+ case 3: /* NEG Ew */
+ icount -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;
+ tmp2 = 0;
+ SUBW(tmp2, tmp);
+ PutbackRMWord(ModRM, tmp2);
+ break;
+
+ case 4: /* MUL AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;
+ {
+ uint32_t result;
+ tmp2 = regs.w[AX];
+
+ SetSF((int16_t)tmp2);
+ SetPF(tmp2);
+
+ result = (uint32_t)tmp2 * tmp;
+ regs.w[AX] = (uint16_t)result;
+ result >>= 16;
+ regs.w[DX] = result;
+
+ SetZF(regs.w[AX] | regs.w[DX]);
+ CarryVal = OverVal = (regs.w[DX] != 0);
+ }
+ break;
+
+ case 5: /* IMUL AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;
+ {
+ int32_t result;
+
+ tmp2 = regs.w[AX];
+
+ SetSF((int16_t)tmp2);
+ SetPF(tmp2);
+
+ result = (int32_t)((int16_t)tmp2) * (int32_t)((int16_t)tmp);
+ CarryVal = OverVal = (result >> 15 != 0) && (result >> 15 != -1);
+
+ regs.w[AX] = (uint16_t)result;
+ result = (uint16_t)(result >> 16);
+ regs.w[DX] = result;
+
+ SetZF(regs.w[AX] | regs.w[DX]);
+ }
+ break;
+
+ case 6: /* DIV AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;
+ {
+ uint32_t result;
+
+ result = (regs.w[DX] << 16) + regs.w[AX];
+
+ if(tmp) {
+ tmp2 = result % tmp;
+ if((result / tmp) > 0xffff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.w[DX] = tmp2;
+ result /= tmp;
+ regs.w[AX] = result;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+ case 7: /* IDIV AX, Ew */
+ icount -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;
+ {
+ int32_t result;
+
+ result = (regs.w[DX] << 16) + regs.w[AX];
+
+ if(tmp) {
+ tmp2 = result % (int32_t)((int16_t)tmp);
+ if((result /= (int32_t)((int16_t)tmp)) > 0xffff) {
+ interrupt(DIVIDE_FAULT);
+ break;
+ } else {
+ regs.w[AX] = result;
+ regs.w[DX] = tmp2;
+ }
+ } else {
+ interrupt(DIVIDE_FAULT);
+ break;
+ }
+ }
+ break;
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_clc() /* Opcode 0xf8 */
+{
+ icount -= timing.flag_ops;
+ CarryVal = 0;
+}
+
+inline void I86::_stc() /* Opcode 0xf9 */
+{
+ icount -= timing.flag_ops;
+ CarryVal = 1;
+}
+
+inline void I86::_cli() /* Opcode 0xfa */
+{
+ icount -= timing.flag_ops;
+ SetIF(0);
+}
+
+inline void I86::_sti() /* Opcode 0xfb */
+{
+ icount -= timing.flag_ops;
+ SetIF(1);
+ instruction(FETCHOP); /* no interrupt before next instruction */
+
+ /* if an interrupt is pending, signal an interrupt */
+ if(IF && (int_state & INT_REQ_BIT)) {
+ interrupt(-1);
+ }
+}
+
+inline void I86::_cld() /* Opcode 0xfc */
+{
+ icount -= timing.flag_ops;
+ SetDF(0);
+}
+
+inline void I86::_std() /* Opcode 0xfd */
+{
+ icount -= timing.flag_ops;
+ SetDF(1);
+}
+
+inline void I86::_fepre() /* Opcode 0xfe */
+{
+ unsigned ModRM = FETCH;
+ unsigned tmp = GetRMByte(ModRM);
+ unsigned tmp1;
+
+ icount -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;
+ if((ModRM & 0x38) == 0) {
+ /* INC eb */
+ tmp1 = tmp + 1;
+ SetOFB_Add(tmp1, tmp, 1);
+ } else {
+ /* DEC eb */
+ tmp1 = tmp - 1;
+ SetOFB_Sub(tmp1, 1, tmp);
+ }
+ SetAF(tmp1, tmp, 1);
+ SetSZPF_Byte(tmp1);
+ PutbackRMByte(ModRM, (uint8_t)tmp1);
+}
+
+inline void I86::_ffpre() /* Opcode 0xff */
+{
+ unsigned ModRM = FETCHOP;
+ unsigned tmp;
+ unsigned tmp1;
+ uint16_t ip;
+
+ switch((ModRM >> 3) & 7) {
+ case 0: /* INC ew */
+ icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp + 1;
+ SetOFW_Add(tmp1, tmp, 1);
+ SetAF(tmp1, tmp, 1);
+ SetSZPF_Word(tmp1);
+ PutbackRMWord(ModRM, (uint16_t)tmp1);
+ break;
+ case 1: /* DEC ew */
+ icount -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;
+ tmp = GetRMWord(ModRM);
+ tmp1 = tmp - 1;
+ SetOFW_Sub(tmp1, 1, tmp);
+ SetAF(tmp1, tmp, 1);
+ SetSZPF_Word(tmp1);
+ PutbackRMWord(ModRM, (uint16_t)tmp1);
+ break;
+ case 2: /* CALL ew */
+ icount -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;
+ tmp = GetRMWord(ModRM);
+ ip = pc - base[CS];
+ PUSH(ip);
+ pc = (base[CS] + (uint16_t)tmp) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _ret();
+ }
+#endif
+ break;
+ case 3: /* CALL FAR ea */
+ icount -= timing.call_m32;
+ tmp = sregs[CS]; /* need to skip displacements of ea */
+ tmp1 = GetRMWord(ModRM);
+ ip = pc - base[CS];
+ PUSH(tmp);
+ PUSH(ip);
+ sregs[CS] = GetNextRMWord;
+ base[CS] = SegBase(CS);
+ pc = (base[CS] + tmp1) & AMASK;
+#ifdef I86_PSEUDO_BIOS
+ if(d_bios && d_bios->bios_call_i86(pc, regs.w, sregs, &ZeroVal, &CarryVal)) {
+ /* bios call */
+ _ret();
+ }
+#endif
+ break;
+ case 4: /* JMP ea */
+ icount -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;
+ ip = GetRMWord(ModRM);
+ pc = (base[CS] + ip) & AMASK;
+ break;
+ case 5: /* JMP FAR ea */
+ icount -= timing.jmp_m32;
+ pc = GetRMWord(ModRM);
+ sregs[CS] = GetNextRMWord;
+ base[CS] = SegBase(CS);
+ pc = (pc + base[CS]) & AMASK;
+ break;
+ case 6: /* PUSH ea */
+ icount -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;
+ tmp = GetRMWord(ModRM);
+ PUSH(tmp);
+ break;
+ case 7: /* invalid ??? */
+ icount -= 10;
+ break;
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+ default:
+ __assume(0);
+#endif
+ }
+}
+
+inline void I86::_invalid()
+{
+ /* i8086/i8088 ignore an invalid opcode. */
+ /* i80186/i80188 probably also ignore an invalid opcode. */
+ icount -= 10;
+}
+
+/*
+ NEC V-series Disassembler
+
+ Originally Written for i386 by Ville Linde
+ Converted to NEC-V by Aaron Giles
+*/
+
+enum
+{
+ PARAM_REG8 = 1, /* 8-bit register */
+ PARAM_REG16, /* 16-bit register */
+ PARAM_REG2_8, /* 8-bit register */
+ PARAM_REG2_16, /* 16-bit register */
+ PARAM_RM8, /* 8-bit memory or register */
+ PARAM_RM16, /* 16-bit memory or register */
+ PARAM_RMPTR8, /* 8-bit memory or register */
+ PARAM_RMPTR16, /* 16-bit memory or register */
+ PARAM_I3, /* 3-bit immediate */
+ PARAM_I4, /* 4-bit immediate */
+ PARAM_I8, /* 8-bit signed immediate */
+ PARAM_I16, /* 16-bit signed immediate */
+ PARAM_UI8, /* 8-bit unsigned immediate */
+ PARAM_IMM, /* 16-bit immediate */
+ PARAM_ADDR, /* 16:16 address */
+ PARAM_REL8, /* 8-bit PC-relative displacement */
+ PARAM_REL16, /* 16-bit PC-relative displacement */
+ PARAM_MEM_OFFS, /* 16-bit mem offset */
+ PARAM_SREG, /* segment register */
+ PARAM_SFREG, /* V25/V35 special function register */
+ PARAM_1, /* used by shift/rotate instructions */
+ PARAM_AL,
+ PARAM_CL,
+ PARAM_DL,
+ PARAM_BL,
+ PARAM_AH,
+ PARAM_CH,
+ PARAM_DH,
+ PARAM_BH,
+ PARAM_AW,
+ PARAM_CW,
+ PARAM_DW,
+ PARAM_BW,
+ PARAM_SP,
+ PARAM_BP,
+ PARAM_IX,
+ PARAM_IY
+};
+
+enum
+{
+ MODRM = 1,
+ GROUP,
+ FPU,
+ TWO_BYTE,
+ PREFIX,
+ SEG_PS,
+ SEG_DS0,
+ SEG_DS1,
+ SEG_SS
+};
+
+struct I386_OPCODE {
+ _TCHAR mnemonic[32];
+ UINT32 flags;
+ UINT32 param1;
+ UINT32 param2;
+ UINT32 param3;
+ offs_t dasm_flags;
+};
+
+struct GROUP_OP {
+ _TCHAR mnemonic[32];
+ const I386_OPCODE *opcode;
+};
+
+static const UINT8 *opcode_ptr;
+static const UINT8 *opcode_ptr_base;
+
+static const I386_OPCODE necv_opcode_table1[256] =
+{
+ // 0x00
+ {_T("add"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("add"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("add"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("add"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("add"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("add"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ds1"), 0, 0, 0, 0 },
+ {_T("pop ds1"), 0, 0, 0, 0 },
+ {_T("or"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("or"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("or"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("or"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("or"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("or"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ps"), 0, 0, 0, 0 },
+ {_T("two_byte"), TWO_BYTE, 0, 0, 0 },
+ // 0x10
+ {_T("addc"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("addc"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("addc"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("addc"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("addc"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("addc"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ss"), 0, 0, 0, 0 },
+ {_T("pop ss"), 0, 0, 0, 0 },
+ {_T("subc"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("subc"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("subc"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("subc"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("subc"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("subc"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("push ds0"), 0, 0, 0, 0 },
+ {_T("pop ds0"), 0, 0, 0, 0 },
+ // 0x20
+ {_T("and"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("and"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("and"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("and"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("and"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("and"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ds1:"), SEG_DS1, 0, 0, 0 },
+ {_T("adj4a"), 0, 0, 0, 0 },
+ {_T("sub"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("sub"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("sub"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("sub"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("sub"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("sub"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ps:"), SEG_PS, 0, 0, 0 },
+ {_T("adj4s"), 0, 0, 0, 0 },
+ // 0x30
+ {_T("xor"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("xor"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("xor"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("xor"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("xor"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("xor"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ss:"), SEG_SS, 0, 0, 0 },
+ {_T("adjba"), 0, 0, 0, 0 },
+ {_T("cmp"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("cmp"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("cmp"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("cmp"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("cmp"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("cmp"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("ds0:"), SEG_DS0, 0, 0, 0 },
+ {_T("adjbs"), 0, 0, 0, 0 },
+ // 0x40
+ {_T("inc"), 0, PARAM_AW, 0, 0 },
+ {_T("inc"), 0, PARAM_CW, 0, 0 },
+ {_T("inc"), 0, PARAM_DW, 0, 0 },
+ {_T("inc"), 0, PARAM_BW, 0, 0 },
+ {_T("inc"), 0, PARAM_SP, 0, 0 },
+ {_T("inc"), 0, PARAM_BP, 0, 0 },
+ {_T("inc"), 0, PARAM_IX, 0, 0 },
+ {_T("inc"), 0, PARAM_IY, 0, 0 },
+ {_T("dec"), 0, PARAM_AW, 0, 0 },
+ {_T("dec"), 0, PARAM_CW, 0, 0 },
+ {_T("dec"), 0, PARAM_DW, 0, 0 },
+ {_T("dec"), 0, PARAM_BW, 0, 0 },
+ {_T("dec"), 0, PARAM_SP, 0, 0 },
+ {_T("dec"), 0, PARAM_BP, 0, 0 },
+ {_T("dec"), 0, PARAM_IX, 0, 0 },
+ {_T("dec"), 0, PARAM_IY, 0, 0 },
+ // 0x50
+ {_T("push"), 0, PARAM_AW, 0, 0 },
+ {_T("push"), 0, PARAM_CW, 0, 0 },
+ {_T("push"), 0, PARAM_DW, 0, 0 },
+ {_T("push"), 0, PARAM_BW, 0, 0 },
+ {_T("push"), 0, PARAM_SP, 0, 0 },
+ {_T("push"), 0, PARAM_BP, 0, 0 },
+ {_T("push"), 0, PARAM_IX, 0, 0 },
+ {_T("push"), 0, PARAM_IY, 0, 0 },
+ {_T("pop"), 0, PARAM_AW, 0, 0 },
+ {_T("pop"), 0, PARAM_CW, 0, 0 },
+ {_T("pop"), 0, PARAM_DW, 0, 0 },
+ {_T("pop"), 0, PARAM_BW, 0, 0 },
+ {_T("pop"), 0, PARAM_SP, 0, 0 },
+ {_T("pop"), 0, PARAM_BP, 0, 0 },
+ {_T("pop"), 0, PARAM_IX, 0, 0 },
+ {_T("pop"), 0, PARAM_IY, 0, 0 },
+ // 0x60
+ {_T("push r"), 0, 0, 0, 0 },
+ {_T("pop r"), 0, 0, 0, 0 },
+ {_T("chkind"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("brkn"), 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
+ {_T("repnc"), PREFIX, 0, 0, 0 },
+ {_T("repc"), PREFIX, 0, 0, 0 },
+ {_T("fpo2 0"), 0, 0, 0, 0 }, /* for a coprocessor that was never made */
+ {_T("fpo2 1"), 0, 0, 0, 0 }, /* for a coprocessor that was never made */
+ {_T("push"), 0, PARAM_IMM, 0, 0 },
+ {_T("mul"), MODRM, PARAM_REG16, PARAM_RM16, PARAM_IMM },
+ {_T("push"), 0, PARAM_I8, 0, 0 },
+ {_T("mul"), MODRM, PARAM_REG16, PARAM_RM16, PARAM_I8 },
+ {_T("inmb"), 0, 0, 0, 0 },
+ {_T("inmw"), 0, 0, 0, 0 },
+ {_T("outmb"), 0, 0, 0, 0 },
+ {_T("outmw"), 0, 0, 0, 0 },
+ // 0x70
+ {_T("bv"), 0, PARAM_REL8, 0, 0 },
+ {_T("bnv"), 0, PARAM_REL8, 0, 0 },
+ {_T("bc"), 0, PARAM_REL8, 0, 0 },
+ {_T("bnc"), 0, PARAM_REL8, 0, 0 },
+ {_T("be"), 0, PARAM_REL8, 0, 0 },
+ {_T("bne"), 0, PARAM_REL8, 0, 0 },
+ {_T("bnh"), 0, PARAM_REL8, 0, 0 },
+ {_T("bh"), 0, PARAM_REL8, 0, 0 },
+ {_T("bn"), 0, PARAM_REL8, 0, 0 },
+ {_T("bp"), 0, PARAM_REL8, 0, 0 },
+ {_T("bpe"), 0, PARAM_REL8, 0, 0 },
+ {_T("bpo"), 0, PARAM_REL8, 0, 0 },
+ {_T("blt"), 0, PARAM_REL8, 0, 0 },
+ {_T("bge"), 0, PARAM_REL8, 0, 0 },
+ {_T("ble"), 0, PARAM_REL8, 0, 0 },
+ {_T("bgt"), 0, PARAM_REL8, 0, 0 },
+ // 0x80
+ {_T("immb"), GROUP, 0, 0, 0 },
+ {_T("immw"), GROUP, 0, 0, 0 },
+ {_T("immb"), GROUP, 0, 0, 0 },
+ {_T("immws"), GROUP, 0, 0, 0 },
+ {_T("test"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("test"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("xch"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("xch"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {_T("mov"), MODRM, PARAM_RM16, PARAM_REG16, 0 },
+ {_T("mov"), MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {_T("mov"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_RM16, PARAM_SREG, 0 },
+ {_T("ldea"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_SREG, PARAM_RM16, 0 },
+ {_T("pop"), MODRM, PARAM_RM16, 0, 0 },
+ // 0x90
+ {_T("nop"), 0, 0, 0, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_CW, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_DW, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_BW, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_SP, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_BP, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_IX, 0 },
+ {_T("xch"), 0, PARAM_AW, PARAM_IY, 0 },
+ {_T("cvtbw"), 0, 0, 0, 0 },
+ {_T("cvtwl"), 0, 0, 0, 0 },
+ {_T("call"), 0, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("poll"), 0, 0, 0, 0 },
+ {_T("push psw"), 0, 0, 0, 0 },
+ {_T("pop psw"), 0, 0, 0, 0 },
+ {_T("mov psw,ah"), 0, 0, 0, 0 },
+ {_T("mov ah,psw"), 0, 0, 0, 0 },
+ // 0xa0
+ {_T("mov"), 0, PARAM_AL, PARAM_MEM_OFFS, 0 },
+ {_T("mov"), 0, PARAM_AW, PARAM_MEM_OFFS, 0 },
+ {_T("mov"), 0, PARAM_MEM_OFFS, PARAM_AL, 0 },
+ {_T("mov"), 0, PARAM_MEM_OFFS, PARAM_AW, 0 },
+ {_T("movbkb"), 0, 0, 0, 0 },
+ {_T("movbkw"), 0, 0, 0, 0 },
+ {_T("cmpbkb"), 0, 0, 0, 0 },
+ {_T("cmpbkw"), 0, 0, 0, 0 },
+ {_T("test"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("test"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("stmb"), 0, 0, 0, 0 },
+ {_T("stmw"), 0, 0, 0, 0 },
+ {_T("ldmb"), 0, 0, 0, 0 },
+ {_T("ldmw"), 0, 0, 0, 0 },
+ {_T("cmpmb"), 0, 0, 0, 0 },
+ {_T("cmpmw"), 0, 0, 0, 0 },
+ // 0xb0
+ {_T("mov"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_CL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_DL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_BL, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_AH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_CH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_DH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_BH, PARAM_UI8, 0 },
+ {_T("mov"), 0, PARAM_AW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_CW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_DW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_BW, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_SP, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_BP, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_IX, PARAM_IMM, 0 },
+ {_T("mov"), 0, PARAM_IY, PARAM_IMM, 0 },
+ // 0xc0
+ {_T("shiftbi"), GROUP, 0, 0, 0 },
+ {_T("shiftwi"), GROUP, 0, 0, 0 },
+ {_T("ret"), 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("ret"), 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("mov ds1,"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov ds0,"), MODRM, PARAM_REG16, PARAM_RM16, 0 },
+ {_T("mov"), MODRM, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("mov"), MODRM, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("prepare"), 0, PARAM_I16, PARAM_UI8, 0 },
+ {_T("dispose"), 0, 0, 0, 0 },
+ {_T("retf"), 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("retf"), 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {_T("brk 3"), 0, 0, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("brk"), 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("brkv"), 0, 0, 0, 0 },
+ {_T("reti"), 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ // 0xd0
+ {_T("shiftb"), GROUP, 0, 0, 0 },
+ {_T("shiftw"), GROUP, 0, 0, 0 },
+ {_T("shiftbv"), GROUP, 0, 0, 0 },
+ {_T("shiftwv"), GROUP, 0, 0, 0 },
+ {_T("cvtbd"), 0, PARAM_I8, 0, 0 },
+ {_T("cvtdb"), 0, PARAM_I8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("trans"), 0, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ {_T("escape"), FPU, 0, 0, 0 },
+ // 0xe0
+ {_T("dbnzne"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("dbnze"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("dbnz"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("bcwz"), 0, PARAM_REL8, 0, 0 },
+ {_T("in"), 0, PARAM_AL, PARAM_UI8, 0 },
+ {_T("in"), 0, PARAM_AW, PARAM_UI8, 0 },
+ {_T("out"), 0, PARAM_UI8, PARAM_AL, 0 },
+ {_T("out"), 0, PARAM_UI8, PARAM_AW, 0 },
+ {_T("call"), 0, PARAM_REL16, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("br"), 0, PARAM_REL16, 0, 0 },
+ {_T("br"), 0, PARAM_ADDR, 0, 0 },
+ {_T("br"), 0, PARAM_REL8, 0, 0 },
+ {_T("in"), 0, PARAM_AL, PARAM_DW, 0 },
+ {_T("in"), 0, PARAM_AW, PARAM_DW, 0 },
+ {_T("out"), 0, PARAM_DW, PARAM_AL, 0 },
+ {_T("out"), 0, PARAM_DW, PARAM_AW, 0 },
+ // 0xf0
+ {_T("buslock"), PREFIX, 0, 0, 0 },
+ {_T("brks"), 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, /* V25S/V35S only */
+ {_T("repne"), PREFIX, 0, 0, 0 },
+ {_T("rep"), PREFIX, 0, 0, 0 },
+ {_T("halt"), 0, 0, 0, 0 },
+ {_T("not1 cy"), 0, 0, 0, 0 },
+ {_T("group1b"), GROUP, 0, 0, 0 },
+ {_T("group1w"), GROUP, 0, 0, 0 },
+ {_T("clr1 cy"), 0, 0, 0, 0 },
+ {_T("set1 cy"), 0, 0, 0, 0 },
+ {_T("di"), 0, 0, 0, 0 },
+ {_T("ei"), 0, 0, 0, 0 },
+ {_T("clr1 dir"), 0, 0, 0, 0 },
+ {_T("set1 dir"), 0, 0, 0, 0 },
+ {_T("group2b"), GROUP, 0, 0, 0 },
+ {_T("group2w"), GROUP, 0, 0, 0 }
+};
+
+static const I386_OPCODE necv_opcode_table2[256] =
+{
+ // 0x00
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x10
+ {_T("test1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("test1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("test1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("test1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("clr1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("set1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR8, PARAM_I3, 0 },
+ {_T("not1"), MODRM, PARAM_RMPTR16, PARAM_I4, 0 },
+ // 0x20
+ {_T("add4s"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("sub4s"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("movspa"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("cmp4s"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("rol4"), MODRM, PARAM_RMPTR8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ror4"), MODRM, PARAM_RMPTR8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("brkcs"), MODRM, PARAM_REG2_16, 0, 0, DASMFLAG_STEP_OVER}, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x30
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ins"), MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ext"), MODRM, PARAM_REG2_8, PARAM_REG8, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ins"), MODRM, PARAM_REG2_8, PARAM_I4, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("ext"), MODRM, PARAM_REG2_8, PARAM_I4, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x40
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x50
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x60
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x70
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x80
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0x90
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("retrbi"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("fint"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("tsksw"), MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
+ {_T("movspb"), MODRM, PARAM_REG2_16, 0, 0 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("btclr"), 0, PARAM_SFREG, PARAM_I3, PARAM_REL8 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("stop"), 0, 0, 0, 0 }, /* V25/V35 only */
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xa0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xb0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xc0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xd0
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xe0
+ {_T("brkxa"), 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ // 0xf0
+ {_T("retxa"), 0, PARAM_UI8, 0, 0 }, /* V33,53 only */
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("brkem"), 0, PARAM_UI8, 0, 0 } /* V20,30,40,50 only */
+};
+
+static const I386_OPCODE immb_table[8] =
+{
+ {_T("add"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("or"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("addc"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("subc"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("and"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("sub"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("xor"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("cmp"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }
+};
+
+static const I386_OPCODE immw_table[8] =
+{
+ {_T("add"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("or"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("addc"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("subc"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("and"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("sub"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("xor"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("cmp"), 0, PARAM_RMPTR16, PARAM_IMM, 0 }
+};
+
+static const I386_OPCODE immws_table[8] =
+{
+ {_T("add"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("or"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("addc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("subc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("and"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("sub"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("xor"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("cmp"), 0, PARAM_RMPTR16, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftbi_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("ror"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("shl"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("shr"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("???"), 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {_T("shra"), 0, PARAM_RMPTR8, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftwi_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("ror"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("shl"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("shr"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("???"), 0, PARAM_RMPTR16, PARAM_I8, 0 },
+ {_T("shra"), 0, PARAM_RMPTR16, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE shiftb_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("ror"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("shl"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("shr"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("???"), 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {_T("shra"), 0, PARAM_RMPTR8, PARAM_1, 0 }
+};
+
+static const I386_OPCODE shiftw_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("ror"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("shl"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("shr"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("???"), 0, PARAM_RMPTR16, PARAM_1, 0 },
+ {_T("shra"), 0, PARAM_RMPTR16, PARAM_1, 0 }
+};
+
+static const I386_OPCODE shiftbv_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("ror"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("shl"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("shr"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("???"), 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {_T("shra"), 0, PARAM_RMPTR8, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE shiftwv_table[8] =
+{
+ {_T("rol"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("ror"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("rolc"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("rorc"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("shl"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("shr"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("???"), 0, PARAM_RMPTR16, PARAM_CL, 0 },
+ {_T("shra"), 0, PARAM_RMPTR16, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE group1b_table[8] =
+{
+ {_T("test"), 0, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("not"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("neg"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("mulu"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("mul"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("divu"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("div"), 0, PARAM_RMPTR8, 0, 0 }
+};
+
+static const I386_OPCODE group1w_table[8] =
+{
+ {_T("test"), 0, PARAM_RMPTR16, PARAM_IMM, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("not"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("neg"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("mulu"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("mul"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("divu"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("div"), 0, PARAM_RMPTR16, 0, 0 }
+};
+
+static const I386_OPCODE group2b_table[8] =
+{
+ {_T("inc"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("dec"), 0, PARAM_RMPTR8, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group2w_table[8] =
+{
+ {_T("inc"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("dec"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("call"), 0, PARAM_RMPTR16, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("call far ptr "),0, PARAM_RM16, 0, 0, DASMFLAG_STEP_OVER},
+ {_T("br"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("br far ptr "),0, PARAM_RM16, 0, 0 },
+ {_T("push"), 0, PARAM_RMPTR16, 0, 0 },
+ {_T("???"), 0, 0, 0, 0 }
+};
+
+static const GROUP_OP group_op_table[] =
+{
+ {_T("immb"), immb_table },
+ {_T("immw"), immw_table },
+ {_T("immws"), immws_table },
+ {_T("shiftbi"), shiftbi_table },
+ {_T("shiftwi"), shiftwi_table },
+ {_T("shiftb"), shiftb_table },
+ {_T("shiftw"), shiftw_table },
+ {_T("shiftbv"), shiftbv_table },
+ {_T("shiftwv"), shiftwv_table },
+ {_T("group1b"), group1b_table },
+ {_T("group1w"), group1w_table },
+ {_T("group2b"), group2b_table },
+ {_T("group2w"), group2w_table }
+};
+
+
+
+static const _TCHAR *const nec_reg[8] = { _T("aw"), _T("cw"), _T("dw"), _T("bw"), _T("sp"), _T("bp"), _T("ix"), _T("iy") };
+static const _TCHAR *const nec_reg8[8] = { _T("al"), _T("cl"), _T("dl"), _T("bl"), _T("ah"), _T("ch"), _T("dh"), _T("bh") };
+static const _TCHAR *const nec_sreg[8] = { _T("ds1"), _T("ps"), _T("ss"), _T("ds0"), _T("???"), _T("???"), _T("???"), _T("???") };
+static const _TCHAR *const nec_sfreg[256] =
+{
+ /* 0x00 */
+ _T("p0"), _T("pm0"), _T("pmc0"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("p1"), _T("pm1"), _T("pmc1"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x10 */
+ _T("p2"), _T("pm2"), _T("pmc2"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x20 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x30 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("pt"), _T("???"), _T("???"), _T("pmt"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x40 */
+ _T("intm"), _T("???"), _T("???"), _T("???"), _T("ems0"), _T("ems1"), _T("ems2"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("exic0"), _T("exic1"), _T("exic2"), _T("???"),
+ /* 0x50 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x60 */
+ _T("rxb0"), _T("???"), _T("txb0"), _T("???"), _T("???"), _T("srms0"), _T("stms0"), _T("???"),
+ _T("scm0"), _T("scc0"), _T("brg0"), _T("scs0"), _T("seic0"), _T("sric0"), _T("stic0"), _T("???"),
+ /* 0x70 */
+ _T("rxb1"), _T("???"), _T("txb1"), _T("???"), _T("???"), _T("srms1"), _T("stms1"), _T("???"),
+ _T("scm1"), _T("scc1"), _T("brg1"), _T("scs1"), _T("seic1"), _T("sric1"), _T("stic1"), _T("???"),
+ /* 0x80 */
+ _T("tm0"), _T("???"), _T("md0"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("tm1"), _T("???"), _T("md1"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0x90 */
+ _T("tmc0"), _T("tmc1"), _T("???"), _T("???"), _T("tmms0"), _T("tmms1"), _T("tmms2"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("tmic0"), _T("tmic1"), _T("tmic2"), _T("???"),
+ /* 0xa0 */
+ _T("dmac0"), _T("dmam0"), _T("dmac1"), _T("dmam1"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("dic0"), _T("dic1"), _T("???"), _T("???"),
+ /* 0xb0 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0xc0 */
+ _T("sar0l"), _T("sar0m"), _T("sar0h"), _T("???"), _T("dar0l"), _T("dar0m"), _T("dar0h"), _T("???"),
+ _T("tc0l"), _T("tc0h"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0xd0 */
+ _T("sar1l"), _T("sar1m"), _T("sar1h"), _T("???"), _T("dar1l"), _T("dar1m"), _T("dar1h"), _T("???"),
+ _T("tc1l"), _T("tc1h"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ /* 0xe0 */
+ _T("stbc"), _T("rfm"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("wtc"), _T("???"), _T("flag"), _T("prc"), _T("tbic"), _T("???"), _T("???"), _T("irqs"),
+ /* 0xf0 */
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"), _T("???"),
+ _T("???"), _T("???"), _T("???"), _T("???"), _T("ispr"), _T("???"), _T("???"), _T("idb")
+};
+
+static UINT32 pc;
+static UINT8 modrm;
+static UINT32 segment;
+static offs_t dasm_flags;
+static _TCHAR modrm_string[256];
+
+#define MODRM_REG1 ((modrm >> 3) & 0x7)
+#define MODRM_REG2 (modrm & 0x7)
+
+#define MAX_LENGTH 8
+
+INLINE UINT8 FETCHD(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > MAX_LENGTH)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCHD16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > MAX_LENGTH)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+static _TCHAR *hexstring(UINT32 value, int digits)
+{
+ static _TCHAR buffer[20];
+ buffer[0] = _T('0');
+ if (digits) {
+ _stprintf(&buffer[1], _T("%0*Xh"), digits, value);
+ } else {
+ _stprintf(&buffer[1], _T("%Xh"), value);
+ }
+ return (buffer[1] >= _T('0') && buffer[1] <= _T('9')) ? &buffer[1] : &buffer[0];
+}
+
+static _TCHAR *shexstring(UINT32 value, int digits, int always)
+{
+ static _TCHAR buffer[20];
+ if (value >= 0x80000000) {
+ _stprintf(buffer, _T("-%s"), hexstring(-value, digits));
+ } else if (always) {
+ _stprintf(buffer, _T("+%s"), hexstring(value, digits));
+ } else {
+ return hexstring(value, digits);
+ }
+ return buffer;
+}
+
+static void handle_modrm(_TCHAR* s)
+{
+ INT8 disp8;
+ INT16 disp16;
+ UINT8 mod, rm;
+
+ modrm = FETCHD();
+ mod = (modrm >> 6) & 0x3;
+ rm = (modrm & 0x7);
+
+ if( modrm >= 0xc0 )
+ return;
+
+ switch(segment)
+ {
+ case SEG_PS: s += _stprintf( s, _T("ps:") ); break;
+ case SEG_DS0: s += _stprintf( s, _T("ds0:") ); break;
+ case SEG_DS1: s += _stprintf( s, _T("ds1:") ); break;
+ case SEG_SS: s += _stprintf( s, _T("ss:") ); break;
+ }
+
+ s += _stprintf( s, _T("[") );
+ switch( rm )
+ {
+ case 0: s += _stprintf( s, _T("bw+ix") ); break;
+ case 1: s += _stprintf( s, _T("bw+iy") ); break;
+ case 2: s += _stprintf( s, _T("bp+ix") ); break;
+ case 3: s += _stprintf( s, _T("bp+iy") ); break;
+ case 4: s += _stprintf( s, _T("ix") ); break;
+ case 5: s += _stprintf( s, _T("iy") ); break;
+ case 6:
+ if( mod == 0 ) {
+ disp16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), hexstring((unsigned) (UINT16) disp16, 0) );
+ } else {
+ s += _stprintf( s, _T("bp") );
+ }
+ break;
+ case 7: s += _stprintf( s, _T("bw") ); break;
+ }
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ s += _stprintf( s, _T("%s"), shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), shexstring((INT32)disp16, 0, TRUE) );
+ }
+ s += _stprintf( s, _T("]") );
+}
+
+static _TCHAR* handle_param(_TCHAR* s, UINT32 param)
+{
+ UINT8 i8;
+ UINT16 i16;
+ UINT16 ptr;
+ UINT32 addr;
+ INT8 d8;
+ INT16 d16;
+
+ switch(param)
+ {
+ case PARAM_REG8:
+ s += _stprintf( s, _T("%s"), nec_reg8[MODRM_REG1] );
+ break;
+
+ case PARAM_REG16:
+ s += _stprintf( s, _T("%s"), nec_reg[MODRM_REG1] );
+ break;
+
+ case PARAM_REG2_8:
+ s += _stprintf( s, _T("%s"), nec_reg8[MODRM_REG2] );
+ break;
+
+ case PARAM_REG2_16:
+ s += _stprintf( s, _T("%s"), nec_reg[MODRM_REG2] );
+ break;
+
+ case PARAM_RM8:
+ case PARAM_RMPTR8:
+ if( modrm >= 0xc0 ) {
+ s += _stprintf( s, _T("%s"), nec_reg8[MODRM_REG2] );
+ } else {
+ if (param == PARAM_RMPTR8)
+ s += _stprintf( s, _T("byte ptr ") );
+ s += _stprintf( s, _T("%s"), modrm_string );
+ }
+ break;
+
+ case PARAM_RM16:
+ case PARAM_RMPTR16:
+ if( modrm >= 0xc0 ) {
+ s += _stprintf( s, _T("%s"), nec_reg[MODRM_REG2] );
+ } else {
+ if (param == PARAM_RMPTR16)
+ s += _stprintf( s, _T("word ptr ") );
+ s += _stprintf( s, _T("%s"), modrm_string );
+ }
+ break;
+
+ case PARAM_I3:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%d"), i8 & 0x07 );
+ break;
+
+ case PARAM_I4:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%d"), i8 & 0x0f );
+ break;
+
+ case PARAM_I8:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%s"), shexstring((INT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_I16:
+ i16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), shexstring((INT16)i16, 0, FALSE) );
+ break;
+
+ case PARAM_UI8:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%s"), shexstring((UINT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_IMM:
+ i16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), hexstring(i16, 0) );
+ break;
+
+ case PARAM_ADDR:
+ addr = FETCHD16();
+ ptr = FETCHD16();
+ s += _stprintf( s, _T("%s:"), hexstring(ptr, 4) );
+ s += _stprintf( s, _T("%s"), hexstring(addr, 0) );
+ break;
+
+ case PARAM_REL16:
+ /* make sure to keep the relative offset within the segment */
+ d16 = FETCHD16();
+ s += _stprintf( s, _T("%s"), hexstring((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF), 0) );
+ break;
+
+ case PARAM_REL8:
+ d8 = FETCHD();
+ s += _stprintf( s, _T("%s"), hexstring(pc + d8, 0) );
+ break;
+
+ case PARAM_MEM_OFFS:
+ switch(segment)
+ {
+ case SEG_PS: s += _stprintf( s, _T("ps:") ); break;
+ case SEG_DS0: s += _stprintf( s, _T("ds0:") ); break;
+ case SEG_DS1: s += _stprintf( s, _T("ds1:") ); break;
+ case SEG_SS: s += _stprintf( s, _T("ss:") ); break;
+ }
+
+ i16 = FETCHD16();
+ s += _stprintf( s, _T("[%s]"), hexstring(i16, 0) );
+ break;
+
+ case PARAM_SREG:
+ s += _stprintf( s, _T("%s"), nec_sreg[MODRM_REG1] );
+ break;
+
+ case PARAM_SFREG:
+ i8 = FETCHD();
+ s += _stprintf( s, _T("%s"), nec_sfreg[i8] );
+ break;
+
+ case PARAM_1:
+ s += _stprintf( s, _T("1") );
+ break;
+
+ case PARAM_AL: s += _stprintf( s, _T("al") ); break;
+ case PARAM_CL: s += _stprintf( s, _T("cl") ); break;
+ case PARAM_DL: s += _stprintf( s, _T("dl") ); break;
+ case PARAM_BL: s += _stprintf( s, _T("bl") ); break;
+ case PARAM_AH: s += _stprintf( s, _T("ah") ); break;
+ case PARAM_CH: s += _stprintf( s, _T("ch") ); break;
+ case PARAM_DH: s += _stprintf( s, _T("dh") ); break;
+ case PARAM_BH: s += _stprintf( s, _T("bh") ); break;
+
+ case PARAM_AW: s += _stprintf( s, _T("aw") ); break;
+ case PARAM_CW: s += _stprintf( s, _T("cw") ); break;
+ case PARAM_DW: s += _stprintf( s, _T("dw") ); break;
+ case PARAM_BW: s += _stprintf( s, _T("bw") ); break;
+ case PARAM_SP: s += _stprintf( s, _T("sp") ); break;
+ case PARAM_BP: s += _stprintf( s, _T("bp") ); break;
+ case PARAM_IX: s += _stprintf( s, _T("ix") ); break;
+ case PARAM_IY: s += _stprintf( s, _T("iy") ); break;
+ }
+ return s;
+}
+
+static void handle_fpu(_TCHAR *s, UINT8 op1, UINT8 op2)
+{
+ switch (op1 & 0x7)
+ {
+ case 0: // Group D8
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fadd dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fmul dword ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("fcom dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fcomp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fsub dword ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fsubr dword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fdiv dword ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fdivr dword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fadd st(0),st(%d)"), op2 & 0x7); break;
+ case 1: _stprintf(s, _T("fcom st(0),st(%d)"), op2 & 0x7); break;
+ case 2: _stprintf(s, _T("fsub st(0),st(%d)"), op2 & 0x7); break;
+ case 3: _stprintf(s, _T("fdiv st(0),st(%d)"), op2 & 0x7); break;
+ case 4: _stprintf(s, _T("fmul st(0),st(%d)"), op2 & 0x7); break;
+ case 5: _stprintf(s, _T("fcomp st(0),st(%d)"), op2 & 0x7); break;
+ case 6: _stprintf(s, _T("fsubr st(0),st(%d)"), op2 & 0x7); break;
+ case 7: _stprintf(s, _T("fdivr st(0),st(%d)"), op2 & 0x7); break;
+ }
+ }
+ break;
+ }
+
+ case 1: // Group D9
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fld dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fst dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fstp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fldenv word ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fldcw word ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fstenv word ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fstcw word ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fld st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fxch st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x10: _stprintf(s, _T("fnop")); break;
+ case 0x20: _stprintf(s, _T("fchs")); break;
+ case 0x21: _stprintf(s, _T("fabs")); break;
+ case 0x24: _stprintf(s, _T("ftst")); break;
+ case 0x25: _stprintf(s, _T("fxam")); break;
+ case 0x28: _stprintf(s, _T("fld1")); break;
+ case 0x29: _stprintf(s, _T("fldl2t")); break;
+ case 0x2a: _stprintf(s, _T("fldl2e")); break;
+ case 0x2b: _stprintf(s, _T("fldpi")); break;
+ case 0x2c: _stprintf(s, _T("fldlg2")); break;
+ case 0x2d: _stprintf(s, _T("fldln2")); break;
+ case 0x2e: _stprintf(s, _T("fldz")); break;
+ case 0x30: _stprintf(s, _T("f2xm1")); break;
+ case 0x31: _stprintf(s, _T("fyl2x")); break;
+ case 0x32: _stprintf(s, _T("fptan")); break;
+ case 0x33: _stprintf(s, _T("fpatan")); break;
+ case 0x34: _stprintf(s, _T("fxtract")); break;
+ case 0x35: _stprintf(s, _T("fprem1")); break;
+ case 0x36: _stprintf(s, _T("fdecstp")); break;
+ case 0x37: _stprintf(s, _T("fincstp")); break;
+ case 0x38: _stprintf(s, _T("fprem")); break;
+ case 0x39: _stprintf(s, _T("fyl2xp1")); break;
+ case 0x3a: _stprintf(s, _T("fsqrt")); break;
+ case 0x3b: _stprintf(s, _T("fsincos")); break;
+ case 0x3c: _stprintf(s, _T("frndint")); break;
+ case 0x3d: _stprintf(s, _T("fscale")); break;
+ case 0x3e: _stprintf(s, _T("fsin")); break;
+ case 0x3f: _stprintf(s, _T("fcos")); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 2: // Group DA
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fiadd dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fimul dword ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("ficom dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("ficomp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fisub dword ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fisubr dword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fidiv dword ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fidivr dword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fcmovb st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fcmove st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ _stprintf(s, _T("fcmovbe st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ _stprintf(s, _T("fcmovu st(0),st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+
+ }
+ }
+ break;
+ }
+
+ case 3: // Group DB
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fild dword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fist dword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fistp dword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("??? (FPU)")); break;
+ case 5: _stprintf(s, _T("fld tword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("??? (FPU)")); break;
+ case 7: _stprintf(s, _T("fstp tword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fcmovnb st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fcmovne st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ _stprintf(s, _T("fcmovnbe st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ _stprintf(s, _T("fcmovnu st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x22: _stprintf(s, _T("fclex")); break;
+ case 0x23: _stprintf(s, _T("finit")); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fucomi st(0),st(%d)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fcomi st(0),st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 4: // Group DC
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fadd qword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fmul qword ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("fcom qword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fcomp qword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fsub qword ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fsubr qword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fdiv qword ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fdivr qword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("fadd st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fmul st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ _stprintf(s, _T("fsubr st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fsub st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fdivr st(%d),st(0)"), op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ _stprintf(s, _T("fdiv st(%d),st(0)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 5: // Group DD
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fld qword ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fst qword ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fstp qword ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("frstor %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("??? (FPU)")); break;
+ case 6: _stprintf(s, _T("fsave %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fstsw word ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("ffree st(%d)"), op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ _stprintf(s, _T("fst st(%d)"), op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ _stprintf(s, _T("fstp st(%d)"), op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ _stprintf(s, _T("fucom st(%d), st(0)"), op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fucomp st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 6: // Group DE
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fiadd word ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("fimul word ptr %s"), modrm_string); break;
+ case 2: _stprintf(s, _T("ficom word ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("ficomp word ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fisub word ptr %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fisubr word ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fidiv word ptr %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fidivr word ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ _stprintf(s, _T("faddp st(%d)"), op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ _stprintf(s, _T("fmulp st(%d)"), op2 & 0x7); break;
+
+ case 0x19: _stprintf(s, _T("fcompp")); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ _stprintf(s, _T("fsubrp st(%d)"), op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fsubp st(%d)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fdivrp st(%d), st(0)"), op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ _stprintf(s, _T("fdivp st(%d)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+
+ case 7: // Group DF
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: _stprintf(s, _T("fild word ptr %s"), modrm_string); break;
+ case 1: _stprintf(s, _T("??? (FPU)")); break;
+ case 2: _stprintf(s, _T("fist word ptr %s"), modrm_string); break;
+ case 3: _stprintf(s, _T("fistp word ptr %s"), modrm_string); break;
+ case 4: _stprintf(s, _T("fbld %s"), modrm_string); break;
+ case 5: _stprintf(s, _T("fild qword ptr %s"), modrm_string); break;
+ case 6: _stprintf(s, _T("fbstp %s"), modrm_string); break;
+ case 7: _stprintf(s, _T("fistp qword ptr %s"), modrm_string); break;
+ }
+ } else {
+ switch (op2 & 0x3f)
+ {
+ case 0x20: _stprintf(s, _T("fstsw aw")); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ _stprintf(s, _T("fucomip st(%d)"), op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ _stprintf(s, _T("fcomip st(%d),st(0)"), op2 & 0x7); break;
+
+ default: _stprintf(s, _T("??? (FPU)")); break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void decode_opcode(_TCHAR *s, const I386_OPCODE *op, UINT8 op1 )
+{
+ int i;
+ UINT8 op2;
+
+ switch( op->flags )
+ {
+ case TWO_BYTE:
+ op2 = FETCHD();
+ decode_opcode( s, &necv_opcode_table2[op2], op1 );
+ return;
+
+ case SEG_PS:
+ case SEG_DS0:
+ case SEG_DS1:
+ case SEG_SS:
+ segment = op->flags;
+ op2 = FETCHD();
+ decode_opcode( s, &necv_opcode_table1[op2], op1 );
+ return;
+
+ case PREFIX:
+ s += _stprintf( s, _T("%-8s"), op->mnemonic );
+ op2 = FETCHD();
+ decode_opcode( s, &necv_opcode_table1[op2], op1 );
+ return;
+
+ case GROUP:
+ handle_modrm( modrm_string );
+ for( i=0; i < ARRAY_LENGTH(group_op_table); i++ ) {
+ if( _tcscmp(op->mnemonic, group_op_table[i].mnemonic) == 0 )
+ {
+ decode_opcode( s, &group_op_table[i].opcode[MODRM_REG1], op1 );
+ return;
+ }
+ }
+ goto handle_unknown;
+
+ case FPU:
+ op2 = FETCHD();
+ handle_fpu( s, op1, op2);
+ return;
+
+ case MODRM:
+ handle_modrm( modrm_string );
+ break;
+ }
+
+ s += _stprintf( s, _T("%-8s"), op->mnemonic );
+ dasm_flags = op->dasm_flags;
+
+ if( op->param1 != 0 ) {
+ s = handle_param( s, op->param1 );
+ }
+
+ if( op->param2 != 0 ) {
+ s += _stprintf( s, _T(",") );
+ s = handle_param( s, op->param2 );
+ }
+
+ if( op->param3 != 0 ) {
+ s += _stprintf( s, _T(",") );
+ s = handle_param( s, op->param3 );
+ }
+ return;
+
+handle_unknown:
+ _stprintf(s, _T("???"));
+}
+
+int necv_dasm_one(_TCHAR *buffer, UINT32 eip, const UINT8 *oprom)
+{
+ UINT8 op;
+
+ opcode_ptr = opcode_ptr_base = oprom;
+ pc = eip;
+ dasm_flags = 0;
+ segment = 0;
+
+ op = FETCHD();
+
+ decode_opcode( buffer, &necv_opcode_table1[op], op );
+ return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED;
+}
+
+#define STATE_VERSION 1
+
+void I86::save_state(FILEIO* state_fio)
+{
+ state_fio->FputUint32(STATE_VERSION);
+ state_fio->FputInt32(this_device_id);
+
+ state_fio->Fwrite(®s, sizeof(regs), 1);
+ state_fio->FputUint32(pc);
+ state_fio->FputUint32(prevpc);
+ state_fio->Fwrite(base, sizeof(base), 1);
+ state_fio->Fwrite(sregs, sizeof(sregs), 1);
+ state_fio->FputUint16(flags);
+ state_fio->FputInt32(AuxVal);
+ state_fio->FputInt32(OverVal);
+ state_fio->FputInt32(SignVal);
+ state_fio->FputInt32(ZeroVal);
+ state_fio->FputInt32(CarryVal);
+ state_fio->FputInt32(DirVal);
+ state_fio->FputUint8(ParityVal);
+ state_fio->FputUint8(TF);
+ state_fio->FputUint8(IF);
+ state_fio->FputUint8(MF);
+ state_fio->FputInt32(int_state);
+ state_fio->FputBool(test_state);
+ state_fio->FputBool(busreq);
+ state_fio->FputBool(halted);
+ state_fio->FputInt32(icount);
+ state_fio->FputInt32(extra_icount);
+ state_fio->FputBool(seg_prefix);
+ state_fio->FputUint8(prefix_seg);
+ state_fio->FputUint32(ea);
+ state_fio->FputUint16(eo);
+ state_fio->FputUint8(ea_seg);
+}
+
+bool I86::load_state(FILEIO* state_fio)
+{
+ if(state_fio->FgetUint32() != STATE_VERSION) {
+ return false;
+ }
+ if(state_fio->FgetInt32() != this_device_id) {
+ return false;
+ }
+ state_fio->Fread(®s, sizeof(regs), 1);
+ pc = state_fio->FgetUint32();
+ prevpc = state_fio->FgetUint32();
+ state_fio->Fread(base, sizeof(base), 1);
+ state_fio->Fread(sregs, sizeof(sregs), 1);
+ flags = state_fio->FgetUint16();
+ AuxVal = state_fio->FgetInt32();
+ OverVal = state_fio->FgetInt32();
+ SignVal = state_fio->FgetInt32();
+ ZeroVal = state_fio->FgetInt32();
+ CarryVal = state_fio->FgetInt32();
+ DirVal = state_fio->FgetInt32();
+ ParityVal = state_fio->FgetUint8();
+ TF = state_fio->FgetUint8();
+ IF = state_fio->FgetUint8();
+ MF = state_fio->FgetUint8();
+ int_state = state_fio->FgetInt32();
+ test_state = state_fio->FgetBool();
+ busreq = state_fio->FgetBool();
+ halted = state_fio->FgetBool();
+ icount = state_fio->FgetInt32();
+ extra_icount = state_fio->FgetInt32();
+ seg_prefix = state_fio->FgetBool();
+ prefix_seg = state_fio->FgetUint8();
+ ea = state_fio->FgetUint32();
+ eo = state_fio->FgetUint16();
+ ea_seg = state_fio->FgetUint8();
+ return true;
+}
+
--- /dev/null
+/*
+ Skelton for retropc emulator
+
+ Origin : MAME 0.142
+ Author : Takeda.Toshiya
+ Date : 2011.04.23-
+
+ [ 80x86 ]
+*/
+
+#ifndef _I86_H_
+#define _I86_H_
+
+#include "vm.h"
+#include "../emu.h"
+#include "device.h"
+
+#define SIG_I86_TEST 0
+
+#ifdef USE_DEBUGGER
+class DEBUGGER;
+#endif
+
+class I86 : public DEVICE
+{
+private:
+ /* ---------------------------------------------------------------------------
+ contexts
+ --------------------------------------------------------------------------- */
+
+ DEVICE *d_mem, *d_io, *d_pic, *d_bios;
+#ifdef SINGLE_MODE_DMA
+ DEVICE *d_dma;
+#endif
+#ifdef USE_DEBUGGER
+ DEBUGGER *d_debugger;
+ DEVICE *d_mem_stored, *d_io_stored;
+#endif
+
+ /* ---------------------------------------------------------------------------
+ registers
+ --------------------------------------------------------------------------- */
+
+ union REGTYPE {
+ uint16_t w[8]; /* viewed as 16 bits registers */
+ uint8_t b[16]; /* or as 8 bit registers */
+ } regs;
+ uint32_t pc;
+ uint32_t prevpc;
+ uint32_t base[4];
+ uint16_t sregs[4];
+ uint16_t flags;
+ int32_t AuxVal, OverVal, SignVal, ZeroVal, CarryVal, DirVal;
+ uint8_t ParityVal;
+ uint8_t TF, IF, MF;
+
+ int int_state;
+ bool test_state;
+ bool busreq, halted;
+
+ int icount;
+ int extra_icount;
+
+ bool seg_prefix; /* prefix segment indicator */
+ uint8_t prefix_seg; /* The prefixed segment */
+ unsigned ea;
+ uint16_t eo; /* effective offset of the address (before segment is added) */
+ uint8_t ea_seg; /* effective segment of the address */
+
+ /* ---------------------------------------------------------------------------
+ opecode
+ --------------------------------------------------------------------------- */
+
+ // sub
+ void interrupt(int num);
+ void trap();
+ unsigned GetEA(unsigned ModRM);
+ void rotate_shift_byte(unsigned ModRM, unsigned cnt);
+ void rotate_shift_word(unsigned ModRM, unsigned cnt);
+
+ // opecode
+ void run_one_opecode();
+#ifdef USE_DEBUGGER
+ void run_one_opecode_debugger();
+#endif
+ void instruction(uint8_t code);
+ inline void _add_br8();
+ inline void _add_wr16();
+ inline void _add_r8b();
+ inline void _add_r16w();
+ inline void _add_ald8();
+ inline void _add_axd16();
+ inline void _push_es();
+ inline void _pop_es();
+ inline void _or_br8();
+ inline void _or_wr16();
+ inline void _or_r8b();
+ inline void _or_r16w();
+ inline void _or_ald8();
+ inline void _or_axd16();
+ inline void _push_cs();
+#if defined(HAS_V30)
+ inline void _0fpre();
+#endif
+ inline void _adc_br8();
+ inline void _adc_wr16();
+ inline void _adc_r8b();
+ inline void _adc_r16w();
+ inline void _adc_ald8();
+ inline void _adc_axd16();
+ inline void _push_ss();
+ inline void _pop_ss();
+ inline void _sbb_br8();
+ inline void _sbb_wr16();
+ inline void _sbb_r8b();
+ inline void _sbb_r16w();
+ inline void _sbb_ald8();
+ inline void _sbb_axd16();
+ inline void _push_ds();
+ inline void _pop_ds();
+ inline void _and_br8();
+ inline void _and_wr16();
+ inline void _and_r8b();
+ inline void _and_r16w();
+ inline void _and_ald8();
+ inline void _and_axd16();
+ inline void _es();
+ inline void _daa();
+ inline void _sub_br8();
+ inline void _sub_wr16();
+ inline void _sub_r8b();
+ inline void _sub_r16w();
+ inline void _sub_ald8();
+ inline void _sub_axd16();
+ inline void _cs();
+ inline void _das();
+ inline void _xor_br8();
+ inline void _xor_wr16();
+ inline void _xor_r8b();
+ inline void _xor_r16w();
+ inline void _xor_ald8();
+ inline void _xor_axd16();
+ inline void _ss();
+ inline void _aaa();
+ inline void _cmp_br8();
+ inline void _cmp_wr16();
+ inline void _cmp_r8b();
+ inline void _cmp_r16w();
+ inline void _cmp_ald8();
+ inline void _cmp_axd16();
+ inline void _ds();
+ inline void _aas();
+ inline void _inc_ax();
+ inline void _inc_cx();
+ inline void _inc_dx();
+ inline void _inc_bx();
+ inline void _inc_sp();
+ inline void _inc_bp();
+ inline void _inc_si();
+ inline void _inc_di();
+ inline void _dec_ax();
+ inline void _dec_cx();
+ inline void _dec_dx();
+ inline void _dec_bx();
+ inline void _dec_sp();
+ inline void _dec_bp();
+ inline void _dec_si();
+ inline void _dec_di();
+ inline void _push_ax();
+ inline void _push_cx();
+ inline void _push_dx();
+ inline void _push_bx();
+ inline void _push_sp();
+ inline void _push_bp();
+ inline void _push_si();
+ inline void _push_di();
+ inline void _pop_ax();
+ inline void _pop_cx();
+ inline void _pop_dx();
+ inline void _pop_bx();
+ inline void _pop_sp();
+ inline void _pop_bp();
+ inline void _pop_si();
+ inline void _pop_di();
+ inline void _pusha();
+ inline void _popa();
+ inline void _bound();
+ inline void _repc(int flagval);
+ inline void _push_d16();
+ inline void _imul_d16();
+ inline void _push_d8();
+ inline void _imul_d8();
+ inline void _insb();
+ inline void _insw();
+ inline void _outsb();
+ inline void _outsw();
+ inline void _jo();
+ inline void _jno();
+ inline void _jb();
+ inline void _jnb();
+ inline void _jz();
+ inline void _jnz();
+ inline void _jbe();
+ inline void _jnbe();
+ inline void _js();
+ inline void _jns();
+ inline void _jp();
+ inline void _jnp();
+ inline void _jl();
+ inline void _jnl();
+ inline void _jle();
+ inline void _jnle();
+ inline void _80pre();
+ inline void _81pre();
+ inline void _82pre();
+ inline void _83pre();
+ inline void _test_br8();
+ inline void _test_wr16();
+ inline void _xchg_br8();
+ inline void _xchg_wr16();
+ inline void _mov_br8();
+ inline void _mov_wr16();
+ inline void _mov_r8b();
+ inline void _mov_r16w();
+ inline void _mov_wsreg();
+ inline void _lea();
+ inline void _mov_sregw();
+ inline void _popw();
+ inline void _nop();
+ inline void _xchg_axcx();
+ inline void _xchg_axdx();
+ inline void _xchg_axbx();
+ inline void _xchg_axsp();
+ inline void _xchg_axbp();
+ inline void _xchg_axsi();
+ inline void _xchg_axdi();
+ inline void _cbw();
+ inline void _cwd();
+ inline void _call_far();
+ inline void _wait();
+ inline void _pushf();
+ inline void _popf();
+ inline void _sahf();
+ inline void _lahf();
+ inline void _mov_aldisp();
+ inline void _mov_axdisp();
+ inline void _mov_dispal();
+ inline void _mov_dispax();
+ inline void _movsb();
+ inline void _movsw();
+ inline void _cmpsb();
+ inline void _cmpsw();
+ inline void _test_ald8();
+ inline void _test_axd16();
+ inline void _stosb();
+ inline void _stosw();
+ inline void _lodsb();
+ inline void _lodsw();
+ inline void _scasb();
+ inline void _scasw();
+ inline void _mov_ald8();
+ inline void _mov_cld8();
+ inline void _mov_dld8();
+ inline void _mov_bld8();
+ inline void _mov_ahd8();
+ inline void _mov_chd8();
+ inline void _mov_dhd8();
+ inline void _mov_bhd8();
+ inline void _mov_axd16();
+ inline void _mov_cxd16();
+ inline void _mov_dxd16();
+ inline void _mov_bxd16();
+ inline void _mov_spd16();
+ inline void _mov_bpd16();
+ inline void _mov_sid16();
+ inline void _mov_did16();
+ inline void _rotshft_bd8();
+ inline void _rotshft_wd8();
+ inline void _ret_d16();
+ inline void _ret();
+ inline void _les_dw();
+ inline void _lds_dw();
+ inline void _mov_bd8();
+ inline void _mov_wd16();
+ inline void _enter();
+ inline void _leav(); // _leave()
+ inline void _retf_d16();
+ inline void _retf();
+ inline void _int3();
+ inline void _int();
+ inline void _into();
+ inline void _iret();
+ inline void _rotshft_b();
+ inline void _rotshft_w();
+ inline void _rotshft_bcl();
+ inline void _rotshft_wcl();
+ inline void _aam();
+ inline void _aad();
+ inline void _setalc();
+ inline void _xlat();
+ inline void _escape();
+ inline void _loopne();
+ inline void _loope();
+ inline void _loop();
+ inline void _jcxz();
+ inline void _inal();
+ inline void _inax();
+ inline void _outal();
+ inline void _outax();
+ inline void _call_d16();
+ inline void _jmp_d16();
+ inline void _jmp_far();
+ inline void _jmp_d8();
+ inline void _inaldx();
+ inline void _inaxdx();
+ inline void _outdxal();
+ inline void _outdxax();
+ inline void _lock();
+ inline void _rep(int flagval);
+ inline void _repne();
+ inline void _repe();
+ inline void _hlt();
+ inline void _cmc();
+ inline void _f6pre();
+ inline void _f7pre();
+ inline void _clc();
+ inline void _stc();
+ inline void _cli();
+ inline void _sti();
+ inline void _cld();
+ inline void _std();
+ inline void _fepre();
+ inline void _ffpre();
+ inline void _invalid();
+
+public:
+ I86(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
+ {
+ d_bios = NULL;
+#ifdef SINGLE_MODE_DMA
+ d_dma = NULL;
+#endif
+ busreq = false;
+#if defined(HAS_I86)
+ set_device_name(_T("i8086 CPU"));
+#else
+ set_device_name(_T("i80186 CPU"));
+#endif
+ }
+ ~I86() {}
+
+ // common functions
+ void initialize();
+ void reset();
+ int run(int clock);
+ void write_signal(int id, uint32_t data, uint32_t mask);
+ void set_intr_line(bool line, bool pending, uint32_t bit);
+ void set_extra_clock(int clock)
+ {
+ extra_icount += clock;
+ }
+ int get_extra_clock()
+ {
+ return extra_icount;
+ }
+ uint32_t get_pc()
+ {
+ return prevpc;
+ }
+ uint32_t get_next_pc()
+ {
+ return pc;
+ }
+#ifdef USE_DEBUGGER
+ void *get_debugger()
+ {
+ return d_debugger;
+ }
+ uint32_t get_debug_prog_addr_mask()
+ {
+ return 0xfffff;
+ }
+ uint32_t get_debug_data_addr_mask()
+ {
+ return 0xfffff;
+ }
+ void write_debug_data8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data8(uint32_t addr);
+ void write_debug_data16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_data16(uint32_t addr);
+ void write_debug_io8(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io8(uint32_t addr);
+ void write_debug_io16(uint32_t addr, uint32_t data);
+ uint32_t read_debug_io16(uint32_t addr);
+ bool write_debug_reg(const _TCHAR *reg, uint32_t data);
+ void get_debug_regs_info(_TCHAR *buffer, size_t buffer_len);
+ int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len);
+#endif
+ void save_state(FILEIO* state_fio);
+ bool load_state(FILEIO* state_fio);
+
+ // unique function
+ void set_context_mem(DEVICE* device)
+ {
+ d_mem = device;
+ }
+ void set_context_io(DEVICE* device)
+ {
+ d_io = device;
+ }
+ void set_context_intr(DEVICE* device)
+ {
+ d_pic = device;
+ }
+ void set_context_bios(DEVICE* device)
+ {
+ d_bios = device;
+ }
+#ifdef SINGLE_MODE_DMA
+ void set_context_dma(DEVICE* device)
+ {
+ d_dma = device;
+ }
+#endif
+#ifdef USE_DEBUGGER
+ void set_context_debugger(DEBUGGER* device)
+ {
+ d_debugger = device;
+ }
+#endif
+};
+
+#endif