From f453ff1a210fcb58a682e5196cb90c4c97f72231 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Mon, 25 Mar 2019 20:16:16 +0900 Subject: [PATCH] [VM][LIBCPU_NEWDEV] Remove deprecated classes. --- source/src/vm/libcpu_newdev/i386.cpp | 261 - source/src/vm/libcpu_newdev/i386.h | 111 - source/src/vm/libcpu_newdev/i386_base.cpp | 136 - source/src/vm/libcpu_newdev/i386_base.h | 73 - source/src/vm/libcpu_newdev/i86.cpp | 1476 ----- source/src/vm/libcpu_newdev/i86.h | 98 - source/src/vm/libcpu_newdev/i86_base.cpp | 2792 --------- source/src/vm/libcpu_newdev/i86_base.h | 402 -- source/src/vm/libcpu_newdev/i86_defs.h | 267 - source/src/vm/libcpu_newdev/i86_inlineops.h | 2523 -------- source/src/vm/libcpu_newdev/i86_macros.h | 218 - source/src/vm/libcpu_newdev/libcpu_i286/i186.cpp | 1725 ----- source/src/vm/libcpu_newdev/libcpu_i286/i186.h | 151 - source/src/vm/libcpu_newdev/libcpu_i286/i286.cpp | 2314 ------- source/src/vm/libcpu_newdev/libcpu_i286/i286.h | 168 - source/src/vm/libcpu_newdev/libcpu_i286/i86.cpp | 2455 -------- source/src/vm/libcpu_newdev/libcpu_i286/i86.h | 452 -- source/src/vm/libcpu_newdev/libcpu_i286/i86.txt | 114 - .../src/vm/libcpu_newdev/libcpu_i286/i86inline.h | 988 --- .../vm/libcpu_newdev/libcpu_i286/readme_takeda.txt | 2 - .../vm/libcpu_newdev/libcpu_i386/CMakeLists.txt | 7 - source/src/vm/libcpu_newdev/libcpu_i386/cycles.h | 337 - source/src/vm/libcpu_newdev/libcpu_i386/i386.h | 32 - .../vm/libcpu_newdev/libcpu_i386/i386_base_ext.cpp | 267 - .../vm/libcpu_newdev/libcpu_i386/i386_opdef.cpp | 4160 ------------- .../src/vm/libcpu_newdev/libcpu_i386/i386_opdef.h | 2961 --------- .../vm/libcpu_newdev/libcpu_i386/i386_ops_table.h | 864 --- .../src/vm/libcpu_newdev/libcpu_i386/i386_real.cpp | 836 --- .../src/vm/libcpu_newdev/libcpu_i386/i386_real.h | 175 - .../src/vm/libcpu_newdev/libcpu_i386/i386dasm.cpp | 3052 --------- .../src/vm/libcpu_newdev/libcpu_i386/i386op16.cpp | 3803 ----------- .../vm/libcpu_newdev/libcpu_i386/i386op16_real.cpp | 255 - .../src/vm/libcpu_newdev/libcpu_i386/i386op32.cpp | 3592 ----------- .../src/vm/libcpu_newdev/libcpu_i386/i386ops.cpp | 5211 ---------------- source/src/vm/libcpu_newdev/libcpu_i386/i386ops.h | 36 - source/src/vm/libcpu_newdev/libcpu_i386/i386priv.h | 675 -- .../src/vm/libcpu_newdev/libcpu_i386/i486ops.cpp | 528 -- .../src/vm/libcpu_newdev/libcpu_i386/pentops.cpp | 6578 -------------------- .../vm/libcpu_newdev/libcpu_i386/readme_takeda.txt | 5 - source/src/vm/libcpu_newdev/libcpu_i386/vtlb.cpp | 297 - source/src/vm/libcpu_newdev/libcpu_i386/vtlb.h | 43 - source/src/vm/libcpu_newdev/libcpu_i386/x87ops.cpp | 4996 --------------- .../vm/libcpu_newdev/libcpu_softfloat/README.txt | 78 - .../libcpu_newdev/libcpu_softfloat/fpu_constant.h | 80 - .../vm/libcpu_newdev/libcpu_softfloat/fsincos.c | 655 -- .../src/vm/libcpu_newdev/libcpu_softfloat/fyl2x.c | 484 -- .../src/vm/libcpu_newdev/libcpu_softfloat/mamesf.h | 68 - .../src/vm/libcpu_newdev/libcpu_softfloat/milieu.h | 42 - .../libcpu_softfloat/readme_takeda.txt | 1 - .../libcpu_softfloat/softfloat-macros | 732 --- .../libcpu_softfloat/softfloat-specialize | 471 -- .../vm/libcpu_newdev/libcpu_softfloat/softfloat.c | 4941 --------------- .../vm/libcpu_newdev/libcpu_softfloat/softfloat.h | 461 -- 53 files changed, 63449 deletions(-) delete mode 100644 source/src/vm/libcpu_newdev/i386.cpp delete mode 100644 source/src/vm/libcpu_newdev/i386.h delete mode 100644 source/src/vm/libcpu_newdev/i386_base.cpp delete mode 100644 source/src/vm/libcpu_newdev/i386_base.h delete mode 100644 source/src/vm/libcpu_newdev/i86.cpp delete mode 100644 source/src/vm/libcpu_newdev/i86.h delete mode 100644 source/src/vm/libcpu_newdev/i86_base.cpp delete mode 100644 source/src/vm/libcpu_newdev/i86_base.h delete mode 100644 source/src/vm/libcpu_newdev/i86_defs.h delete mode 100644 source/src/vm/libcpu_newdev/i86_inlineops.h delete mode 100644 source/src/vm/libcpu_newdev/i86_macros.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i186.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i186.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i286.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i286.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i86.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i86.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i86.txt delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/i86inline.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i286/readme_takeda.txt delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/CMakeLists.txt delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/cycles.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386_base_ext.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386_ops_table.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386_real.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386_real.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386dasm.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386op16.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386op16_real.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386op32.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386ops.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386ops.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i386priv.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/i486ops.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/pentops.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/readme_takeda.txt delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/vtlb.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/vtlb.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_i386/x87ops.cpp delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/README.txt delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/fpu_constant.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/fsincos.c delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/fyl2x.c delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/mamesf.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/milieu.h delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/readme_takeda.txt delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-macros delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-specialize delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.c delete mode 100644 source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.h diff --git a/source/src/vm/libcpu_newdev/i386.cpp b/source/src/vm/libcpu_newdev/i386.cpp deleted file mode 100644 index 7ee9facd1..000000000 --- a/source/src/vm/libcpu_newdev/i386.cpp +++ /dev/null @@ -1,261 +0,0 @@ - - -#include "vm.h" -#include "../emu.h" -#include "./i386.h" -#include "./libcpu_i386/i386_real.h" -#ifdef USE_DEBUGGER -#include "debugger.h" -#endif - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#pragma warning( disable : 4018 ) -#pragma warning( disable : 4065 ) -#pragma warning( disable : 4146 ) -#pragma warning( disable : 4244 ) -#pragma warning( disable : 4996 ) -#endif - -#if defined(HAS_I386) - #define CPU_MODEL i386 -#elif defined(HAS_I486) - #define CPU_MODEL i486 -#elif defined(HAS_PENTIUM) - #define CPU_MODEL pentium -#elif defined(HAS_MEDIAGX) - #define CPU_MODEL mediagx -#elif defined(HAS_PENTIUM_PRO) - #define CPU_MODEL pentium_pro -#elif defined(HAS_PENTIUM_MMX) - #define CPU_MODEL pentium_mmx -#elif defined(HAS_PENTIUM2) - #define CPU_MODEL pentium2 -#elif defined(HAS_PENTIUM3) - #define CPU_MODEL pentium3 -#elif defined(HAS_PENTIUM4) - #define CPU_MODEL pentium4 -#endif - -void I386::initialize() -{ - DEVICE::initialize(); - cpucore = new I386_OPS; -#if defined(HAS_I386) - cpucore->cpu_init_i386(); -#elif defined(HAS_I486) - cpucore->cpu_init_i486(); -#elif defined(HAS_PENTIUM) - cpucore->cpu_init_pentium(); -#elif defined(HAS_MEDIAGX) - cpucore->cpu_init_mediagx(); -#elif defined(HAS_PENTIUM_PRO) - cpucore->cpu_init_pentium_pro(); -#elif defined(HAS_PENTIUM_MMX) - cpucore->cpu_init_pentium_mmx(); -#elif defined(HAS_PENTIUM2) - cpucore->cpu_init_pentium2(); -#elif defined(HAS_PENTIUM3) - cpucore->cpu_init_pentium3(); -#elif defined(HAS_PENTIUM4) - cpucore->cpu_init_pentium4(); -#endif - cpucore->set_context_pic(d_pic); - cpucore->set_context_progmem(d_mem); - cpucore->set_context_io(d_io); -#ifdef I386_PSEUDO_BIOS - cpucore->set_context_pseudo_bios(d_bios); -#endif -#ifdef SINGLE_MODE_DMA - cpucore->set_context_dma(d_dma); -#endif - -#ifdef USE_DEBUGGER - cpucore->set_context_emu(emu); - cpucore->set_context_debugger(d_debugger); - cpucore->set_context_progmem_stored(d_mem); - cpucore->set_context_io_stored(d_io); - - d_debugger->set_context_mem(d_mem); - d_debugger->set_context_io(d_io); -#endif - cpucore->set_shutdown_flag(0); -} - -void I386::reset() -{ -#if defined(HAS_I386) - cpucore->cpu_reset_i386(); -#elif defined(HAS_I486) - cpucore->cpu_reset_i486(); -#elif defined(HAS_PENTIUM) - cpucore->cpu_reset_pentium(); -#elif defined(HAS_MEDIAGX) - cpucore->cpu_reset_mediagx(); -#elif defined(HAS_PENTIUM_PRO) - cpucore->cpu_reset_pentium_pro(); -#elif defined(HAS_PENTIUM_MMX) - cpucore->cpu_reset_pentium_mmx(); -#elif defined(HAS_PENTIUM2) - cpucore->cpu_reset_pentium2(); -#elif defined(HAS_PENTIUM3) - cpucore->cpu_reset_pentium3(); -#elif defined(HAS_PENTIUM4) - cpucore->cpu_reset_pentium4(); -#endif -} - -int I386::run(int cycles) -{ - return cpucore->cpu_execute_i386(cycles); -} - - -#ifdef USE_DEBUGGER -void I386::write_debug_data8(uint32_t addr, uint32_t data) -{ - int wait; - d_mem->write_data8w(addr, data, &wait); -} - -uint32_t I386::read_debug_data8(uint32_t addr) -{ - int wait; - return d_mem->read_data8w(addr, &wait); -} - -void I386::write_debug_data16(uint32_t addr, uint32_t data) -{ - int wait; - d_mem->write_data16w(addr, data, &wait); -} - -uint32_t I386::read_debug_data16(uint32_t addr) -{ - int wait; - return d_mem->read_data16w(addr, &wait); -} - -void I386::write_debug_data32(uint32_t addr, uint32_t data) -{ - int wait; - d_mem->write_data32w(addr, data, &wait); -} - -uint32_t I386::read_debug_data32(uint32_t addr) -{ - int wait; - return d_mem->read_data32w(addr, &wait); -} - -void I386::write_debug_io8(uint32_t addr, uint32_t data) -{ - int wait; - d_io->write_io8w(addr, data, &wait); -} - -uint32_t I386::read_debug_io8(uint32_t addr) { - int wait; - return d_io->read_io8w(addr, &wait); -} - -void I386::write_debug_io16(uint32_t addr, uint32_t data) -{ - int wait; - d_io->write_io16w(addr, data, &wait); -} - -uint32_t I386::read_debug_io16(uint32_t addr) { - int wait; - return d_io->read_io16w(addr, &wait); -} - -void I386::write_debug_io32(uint32_t addr, uint32_t data) -{ - int wait; - d_io->write_io32w(addr, data, &wait); -} - -uint32_t I386::read_debug_io32(uint32_t addr) { - int wait; - return d_io->read_io32w(addr, &wait); -} - -bool I386::write_debug_reg(const _TCHAR *reg, uint32_t data) -{ - return cpucore->write_debug_reg(reg, data); -} - -uint32_t I386::read_debug_reg(const _TCHAR *reg) -{ - return cpucore->read_debug_reg(reg); -} - -bool I386::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len) -{ - i386_state *cpustate = cpucore->get_cpu_state(); - my_stprintf_s(buffer, buffer_len, - _T("AX=%04X BX=%04X CX=%04X DX=%04X SP=%04X BP=%04X SI=%04X DI=%04X\n") - _T("DS=%04X ES=%04X SS=%04X CS=%04X IP=%04X FLAG=[%c%c%c%c%c%c%c%c%c]\n") - _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"), - REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI), - cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->eip, - cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'), - cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'), - cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles, - get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame()); - cpustate->prev_total_cycles = cpustate->total_cycles; - return true; -} - -int I386::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len) -{ - return cpucore->debug_dasm(pc, buffer, buffer_len); -} -#endif - -void I386::set_context_bios(DEVICE* device) -{ -#ifdef I386_PSEUDO_BIOS - d_bios = device; - if(cpucore != NULL) cpucore->set_context_pseudo_bios(d_bios); -#endif -} -void I386::set_context_dma(DEVICE* device) -{ -#ifdef SINGLE_MODE_DMA - d_dma = device; - if(cpucore != NULL) cpucore->set_context_dma(d_dma); -#endif -} - -#ifdef USE_DEBUGGER -void I386::set_context_debugger(DEBUGGER* device) -{ - d_debugger = device; - if(cpucore != NULL) { - cpucore->set_context_emu(emu); - cpucore->set_context_debugger(d_debugger); - cpucore->set_context_progmem_stored(d_mem); - cpucore->set_context_io_stored(d_io); - } -} -#endif - - - -bool I386::process_state(FILEIO* state_fio, bool loading) -{ - i386_state *cpustate = cpucore->get_cpu_state(); - if(!(I386_BASE::process_state(state_fio, loading))) return false; -// if(save != NULL && save_size > 0) { -// state_fio->StateBuffer(save, save_size, 1); -// } - - #ifdef USE_DEBUGGER - // post process - if(loading) { - cpustate->prev_total_cycles = cpustate->total_cycles; - } -#endif - return true; -} diff --git a/source/src/vm/libcpu_newdev/i386.h b/source/src/vm/libcpu_newdev/i386.h deleted file mode 100644 index a7c5ccb8e..000000000 --- a/source/src/vm/libcpu_newdev/i386.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - Skelton for retropc emulator - - Origin : MAME i386 core - Author : Takeda.Toshiya - Date : 2009.06.08- - - [ i386/i486/Pentium/MediaGX ] -*/ - -#ifndef _NEWDEV_I386_H_ -#define _NEWDEV_I386_H_ - -#include "vm.h" -#include "../../emu.h" -#include "./i386_base.h" -//#include "./libcpu_i386/i386_real.h" - -#ifdef USE_DEBUGGER -class DEBUGGER; -#endif - -class I386 : public I386_BASE -{ -protected: -#ifdef USE_DEBUGGER - DEBUGGER *d_debugger; -#endif -public: - I386(VM_TEMPLATE* parent_vm, EMU* parent_emu) : I386_BASE(parent_vm, parent_emu) - { -#ifdef USE_DEBUGGER - d_debugger = NULL; -#endif -#if defined(HAS_I386) - set_device_name(_T("i80386 CPU")); -#elif defined(HAS_I486) - set_device_name(_T("i80486 CPU")); -#elif defined(HAS_PENTIUM) - set_device_name(_T("Pentium CPU")); -#elif defined(HAS_MEDIAGX) - set_device_name(_T("Media GX CPU")); -#elif defined(HAS_PENTIUM_PRO) - set_device_name(_T("Pentium Pro CPU")); -#elif defined(HAS_PENTIUM_MMX) - set_device_name(_T("Pentium MMX CPU")); -#elif defined(HAS_PENTIUM2) - set_device_name(_T("Pentium2 CPU")); -#elif defined(HAS_PENTIUM3) - set_device_name(_T("Pentium3 CPU")); -#elif defined(HAS_PENTIUM4) - set_device_name(_T("Pentium4 CPU")); -#endif - } - ~I386() {} - // common functions - void initialize(); - void reset(); - int run(int cycles); - //int cpu_execute(void *p, int cycles); -#ifdef USE_DEBUGGER - bool is_cpu() - { - return true; - } - bool is_debugger_available() - { - return true; - } - void *get_debugger() - { - return d_debugger; - } - uint32_t get_debug_prog_addr_mask() - { - return 0xffffffff; - } - uint32_t get_debug_data_addr_mask() - { - return 0xffffffff; - } - 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_data32(uint32_t addr, uint32_t data); - uint32_t read_debug_data32(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_io32(uint32_t addr); - void write_debug_io32(uint32_t addr, uint32_t data); - uint32_t read_debug_io16(uint32_t addr); - bool write_debug_reg(const _TCHAR *reg, uint32_t data); - uint32_t read_debug_reg(const _TCHAR *reg); - bool get_debug_regs_info(_TCHAR *buffer, size_t buffer_len); - int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len); -#endif - bool process_state(FILEIO *state_fio, bool loading); - - // unique function - void set_context_bios(DEVICE* device); - void set_context_dma(DEVICE* device); - -#ifdef USE_DEBUGGER - void set_context_debugger(DEBUGGER* device); -#endif - -}; - -#endif diff --git a/source/src/vm/libcpu_newdev/i386_base.cpp b/source/src/vm/libcpu_newdev/i386_base.cpp deleted file mode 100644 index 8ae81a5e6..000000000 --- a/source/src/vm/libcpu_newdev/i386_base.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - Skelton for retropc emulator - - Origin : MAME i386 core - Author : Takeda.Toshiya - Date : 2009.06.08- - - [ i386/i486/Pentium/MediaGX ] -*/ - -#include "i386_base.h" -#include "libcpu_i386/i386_opdef.h" - -void I386_BASE::initialize() -{ - DEVICE::initialize(); - cpucore = new I386_OPS_BASE; - cpucore->cpu_init_i386(); - cpucore->set_context_pic(d_pic); - cpucore->set_context_progmem(d_mem); - cpucore->set_context_io(d_io); - cpucore->set_shutdown_flag(0); -} - -void I386_BASE::release() -{ - cpucore->i386_vtlb_free(); - cpucore->i386_free_state(); - delete cpucore; -} - -void I386_BASE::reset() -{ - cpucore->cpu_reset_i386(); -} - -int I386_BASE::run(int cycles) -{ - return cpucore->cpu_execute_i386(cycles); -} - -void I386_BASE::write_signal(int id, uint32_t data, uint32_t mask) -{ - if(id == SIG_CPU_NMI) { - cpucore->i386_set_irq_line( INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE); - } else if(id == SIG_CPU_IRQ) { - cpucore->i386_set_irq_line( INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE); - } else if(id == SIG_CPU_BUSREQ) { - cpucore->set_busreq(((data & mask) != 0)); - } else if(id == SIG_I386_A20) { - cpucore->i386_set_a20_line( data & mask); - } -} - -void I386_BASE::set_intr_line(bool line, bool pending, uint32_t bit) -{ - cpucore->i386_set_irq_line(INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE); -} - -void I386_BASE::set_extra_clock(int cycles) -{ - cpucore->set_extra_clock(cycles); -} - -int I386_BASE::get_extra_clock() -{ - return cpucore->get_extra_clock(); -} - -uint32_t I386_BASE::get_pc() -{ - return cpucore->get_prev_pc(); -} - -uint32_t I386_BASE::get_next_pc() -{ - return cpucore->get_pc(); -} - -void I386_BASE::set_address_mask(uint32_t mask) -{ - cpucore->set_address_mask(mask); - - // TODO: how does A20M and the tlb interact - cpucore->vtlb_flush_dynamic(); -} - -uint32_t I386_BASE::get_address_mask() -{ - return cpucore->get_address_mask(); -} -void I386_BASE::set_shutdown_flag(int shutdown) -{ - cpucore->set_shutdown_flag(shutdown); -} - -int I386_BASE::get_shutdown_flag() -{ - return cpucore->get_shutdown_flag(); -} - -void I386_BASE::set_context_mem(DEVICE* device) -{ - d_mem = device; - if(cpucore != NULL) cpucore->set_context_progmem(d_mem); -} - -void I386_BASE::set_context_io(DEVICE* device) -{ - d_io = device; - if(cpucore != NULL) cpucore->set_context_io(d_io); -} - -void I386_BASE::set_context_intr(DEVICE* device) -{ - d_pic = device; - if(cpucore != NULL) cpucore->set_context_pic(d_pic); -} - - -#include "../../fileio.h" - -#define STATE_VERSION 4 - -bool I386_BASE::process_state(FILEIO* state_fio, bool loading) -{ - if(!state_fio->StateCheckUint32(STATE_VERSION)) { - return false; - } - if(!state_fio->StateCheckInt32(this_device_id)) { - return false; - } - if(cpucore == NULL) return false; - return cpucore->process_state(state_fio, loading); -} - diff --git a/source/src/vm/libcpu_newdev/i386_base.h b/source/src/vm/libcpu_newdev/i386_base.h deleted file mode 100644 index f3db2572b..000000000 --- a/source/src/vm/libcpu_newdev/i386_base.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Skelton for retropc emulator - - Origin : MAME i386 core - Author : Takeda.Toshiya - Date : 2009.06.08- - - [ i386/i486/Pentium/MediaGX ] -*/ - -#ifndef _I386_BASE_H_ -#define _I386_BASE_H_ - -//#include "vm.h" -//#include "../emu.h" -#include -#include "./device.h" -#include "libcpu_i386/i386priv.h" - -#define SIG_I386_A20 1 - -class VM_TEMPLATE; -class EMU; -class DEBUGGER; -class I386_OPS_BASE; -class FILEIO; - -class I386_BASE : public DEVICE -{ -protected: - I386_OPS_BASE *cpucore; - DEVICE *d_mem, *d_io, *d_pic; - - DEVICE *d_bios; - DEVICE *d_dma; - -public: - I386_BASE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) - { - d_bios = NULL; - d_dma = NULL; - cpucore = NULL; - set_device_name(_T("i80x86 CPU BASE")); - } - ~I386_BASE() {} - - // common functions - virtual void initialize(); - void release(); - virtual void reset(); - virtual int run(int cycles); - 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 cycles); - int get_extra_clock(); - uint32_t get_pc(); - uint32_t get_next_pc(); - - virtual bool process_state(FILEIO* state_fio, bool loading); - // unique function - void set_context_mem(DEVICE* device); - void set_context_io(DEVICE* device); - void set_context_intr(DEVICE* device); - - virtual void set_context_bios(DEVICE* device) {} - virtual void set_context_dma(DEVICE* device) {} - void set_address_mask(uint32_t mask); - uint32_t get_address_mask(); - void set_shutdown_flag(int shutdown); - int get_shutdown_flag(); -}; - -#endif diff --git a/source/src/vm/libcpu_newdev/i86.cpp b/source/src/vm/libcpu_newdev/i86.cpp deleted file mode 100644 index 6d56f19bf..000000000 --- a/source/src/vm/libcpu_newdev/i86.cpp +++ /dev/null @@ -1,1476 +0,0 @@ -/* - 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 -#include "./i86_macros.h" - -extern 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}; - - DEVICE::initialize(); - 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]; - } - //memcpy(parity_table, _i80x86_parity_table, sizeof(uint8_t) * 256); -#if defined(HAS_I86) - timing = _i80x86_timing_tbl_i8086; -#else - timing = _i80x86_timing_tbl_i80186; -#endif - d_mem_stored = d_mem; - d_io_stored = d_io; -#ifdef USE_DEBUGGER - 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; - } -} - -void I86::run_one_opecode_debugger() -{ -#ifdef USE_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(); - d_debugger->now_waiting = true; - while(d_debugger->now_debugging && d_debugger->now_suspended) { - emu->sleep(10); - } - d_debugger->now_waiting = false; - } - 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(); - } -#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); -#ifdef SINGLE_MODE_DMA - if(d_dma) { - d_dma->do_dma(); - } -#endif - 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); - } - icount -= extra_icount; - extra_icount = 0; -} - -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 - } -} - -#if defined(HAS_V30) -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 - - -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 -} - - -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; -} - -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); -} - -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; -} - - -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; -} - -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); - } -} - - -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 - } -} - - diff --git a/source/src/vm/libcpu_newdev/i86.h b/source/src/vm/libcpu_newdev/i86.h deleted file mode 100644 index a3fb2e69f..000000000 --- a/source/src/vm/libcpu_newdev/i86.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - Skelton for retropc emulator - - Origin : MAME 0.142 - Author : Takeda.Toshiya - Date : 2011.04.23- - - [ 80x86 ] -*/ - -#ifndef _LIBNEWDEV_I86_H_ -#define _LIBNEWDEV_I86_H_ - -#include "vm.h" -#include "../emu.h" -#include "./i86_base.h" - -#ifdef USE_DEBUGGER -class DEBUGGER; -#endif - -class I86 : public I86_BASE -{ -private: - /* --------------------------------------------------------------------------- - contexts - --------------------------------------------------------------------------- */ - -#ifdef SINGLE_MODE_DMA - DEVICE *d_dma; -#endif -#ifdef USE_DEBUGGER - DEBUGGER *d_debugger; -#endif - // opecode - void run_one_opecode(); - void run_one_opecode_debugger(); - void instruction(uint8_t code); - void _repc(int flagval); - void _call_far(); - void _int(); - void _aad(); - void _call_d16(); - void _rep(int flagval); - void _ffpre(); -#if defined(HAS_V30) - void _0fpre(); /* Opcode 0x0f */ -#endif -public: - I86(VM_TEMPLATE* parent_vm, EMU* parent_emu) : I86_BASE(parent_vm, parent_emu) - { -#ifdef SINGLE_MODE_DMA - d_dma = NULL; -#endif - busreq = false; -#if defined(HAS_I86) - set_device_name(_T("i8086 CPU")); -#elif defined(HAS_V30) - set_device_name(_T("V30 CPU")); -#else - set_device_name(_T("i80186 CPU")); -#endif - } - ~I86() {} - - // common functions - void initialize(); - void reset(); - int run(int clock); -#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; - } -#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 -}; - -#endif diff --git a/source/src/vm/libcpu_newdev/i86_base.cpp b/source/src/vm/libcpu_newdev/i86_base.cpp deleted file mode 100644 index 8b6d9ff5f..000000000 --- a/source/src/vm/libcpu_newdev/i86_base.cpp +++ /dev/null @@ -1,2792 +0,0 @@ -/* - 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_base.h" -#include "./i86_macros.h" -int necv_dasm_one(_TCHAR *buffer, UINT32 eip, const UINT8 *oprom); - -void I86_BASE::initialize() -{ - static const BREGS reg_name[8] = {AL, CL, DL, BL, AH, CH, DH, BH}; - - DEVICE::initialize(); - 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]; - } - //memcpy(parity_table, _i80x86_parity_table, sizeof(uint8_t) * 256); - timing = _i80x86_timing_tbl_i8086; - - d_mem_stored = d_mem; - d_io_stored = d_io; -} - -void I86_BASE::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); - seg_prefix = false; -} - -int I86_BASE::run(int clock) -{ - /* return now if BUSREQ */ - if(busreq) { - 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; - run_one_opecode(); - 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) { - run_one_opecode(); - } - /* if busreq is raised, spin cpu while remained clock */ - if(icount > 0 && busreq) { - icount = 0; - } - return first_icount - icount; - } -} - - -void I86_BASE::run_one_opecode_debugger() -{ -} - - -void I86_BASE::run_one_opecode() -{ - seg_prefix = false; - 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); - } - icount -= extra_icount; - extra_icount = 0; -} - -void I86_BASE::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_BASE::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_BASE::write_debug_data8(uint32_t addr, uint32_t data) -{ - int wait; - d_mem_stored->write_data8w(addr, data, &wait); -} - -uint32_t I86_BASE::read_debug_data8(uint32_t addr) -{ - int wait; - return d_mem_stored->read_data8w(addr, &wait); -} - -void I86_BASE::write_debug_data16(uint32_t addr, uint32_t data) -{ - int wait; - d_mem_stored->write_data16w(addr, data, &wait); -} - -uint32_t I86_BASE::read_debug_data16(uint32_t addr) -{ - int wait; - return d_mem_stored->read_data16w(addr, &wait); -} - -void I86_BASE::write_debug_io8(uint32_t addr, uint32_t data) -{ - int wait; - d_io_stored->write_io8w(addr, data, &wait); -} - -uint32_t I86_BASE::read_debug_io8(uint32_t addr) { - int wait; - return d_io_stored->read_io8w(addr, &wait); -} - -void I86_BASE::write_debug_io16(uint32_t addr, uint32_t data) -{ - int wait; - d_io_stored->write_io16w(addr, data, &wait); -} - -uint32_t I86_BASE::read_debug_io16(uint32_t addr) { - int wait; - return d_io_stored->read_io16w(addr, &wait); -} - -bool I86_BASE::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_BASE::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_BASE::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_BASE::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_BASE::trap() -{ - instruction(FETCHOP); - interrupt(1); -} - -unsigned I86_BASE::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_BASE::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_BASE::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_BASE::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; - case 0x0f: _invalid(); break; - 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; - case 0x60: _invalid(); break; - case 0x61: _invalid(); break; - case 0x62: _invalid(); break; - - case 0x63: _invalid(); break; - case 0x64: _invalid(); break; - case 0x65: _invalid(); break; - case 0x66: _invalid(); break; - case 0x67: _invalid(); break; - 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; - 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; - case 0xc0: _invalid(); break; - case 0xc1: _invalid(); break; - 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; - case 0xc8: _invalid(); break; - case 0xc9: _invalid(); break; - 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; - case 0xd6: _invalid(); break; - 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 - } -} - -void I86_BASE::_repc(int flagval) -{ -} - -//!! -void I86_BASE::_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; - icount -= timing.call_far; -} - -void I86_BASE::_int() /* Opcode 0xcd */ -{ - unsigned int_num = FETCH; - icount -= timing.int_imm; - interrupt(int_num); -} -void I86_BASE::_aad() /* Opcode 0xd5 */ -{ - unsigned mult = FETCH; - icount -= timing.aad; - regs.b[AL] = regs.b[AH] * mult + regs.b[AL]; - regs.b[AH] = 0; - SetZF(regs.b[AL]); - SetPF(regs.b[AL]); - SignVal = 0; -} -void I86_BASE::_call_d16() /* Opcode 0xe8 */ -{ - uint16_t ip, tmp; - - FETCHWORD(tmp); - ip = pc - base[CS]; - PUSH(ip); - ip += tmp; - pc = (ip + base[CS]) & AMASK; - icount -= timing.call_near; -} - -void I86_BASE::_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; - 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); - } -} -void I86_BASE::_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; - 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; - 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 - } -} - - -/* - 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_BASE::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_BASE::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; -} - diff --git a/source/src/vm/libcpu_newdev/i86_base.h b/source/src/vm/libcpu_newdev/i86_base.h deleted file mode 100644 index 652690033..000000000 --- a/source/src/vm/libcpu_newdev/i86_base.h +++ /dev/null @@ -1,402 +0,0 @@ -/* - Skelton for retropc emulator - - Origin : MAME 0.142 - Author : Takeda.Toshiya - Date : 2011.04.23- - - [ 80x86 ] -*/ - -#ifndef _LIBNEWDEV_I86_BASE_H_ -#define _LIBNEWDEV_I86_BASE_H_ - -#include "../../common.h" -#include "./device.h" -#include "./i86_defs.h" -#define SIG_I86_TEST 0 - -class I86_BASE : public DEVICE -{ -protected: - /* --------------------------------------------------------------------------- - contexts - --------------------------------------------------------------------------- */ - - DEVICE *d_mem, *d_io, *d_pic, *d_bios; - DEVICE *d_mem_stored, *d_io_stored; - - /* --------------------------------------------------------------------------- - 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; - struct { - struct { - WREGS w[256]; - BREGS b[256]; - } reg; - struct { - WREGS w[256]; - BREGS b[256]; - } RM; - } Mod_RM; - - 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 */ - - struct i80x86_timing timing; - /* --------------------------------------------------------------------------- - 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 - virtual void run_one_opecode(); - virtual void run_one_opecode_debugger(); - virtual void instruction(uint8_t code); - - virtual void _repc(int flagval); - virtual void _call_far(); - virtual void _int(); - virtual void _aad(); - virtual void _call_d16(); - virtual void _rep(int flagval); - virtual void _ffpre(); - - 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(); - 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 _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 _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 _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 _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 _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 _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 _invalid(); - -public: - I86_BASE(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) - { - busreq = false; - d_bios = NULL; - d_pic = NULL; - d_mem = d_mem_stored = NULL; - d_io = d_io_stored = NULL; - set_device_name(_T("i8086 CPU")); - } - ~I86_BASE() {} - - // common functions - virtual void initialize(); - virtual void reset(); - virtual 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; - } - 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); - - 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; - } -}; -#include "i86_inlineops.h" - -#endif diff --git a/source/src/vm/libcpu_newdev/i86_defs.h b/source/src/vm/libcpu_newdev/i86_defs.h deleted file mode 100644 index f907fb6e4..000000000 --- a/source/src/vm/libcpu_newdev/i86_defs.h +++ /dev/null @@ -1,267 +0,0 @@ -#ifndef __LIBNEWDEV_I86_DEFS_H__ -#define __LIBNEWDEV_I86_DEFS_H__ - -#ifndef INLINE -#define INLINE inline -#endif - -#define offs_t UINT32 - - -#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; - -/************************************************************************/ - -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 */ -}; - -//static const uint8_t _i80x86_parity_table[256] = { -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 -}; - -static const struct i80x86_timing _i80x86_timing_tbl_i8086 = { - 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 */ -}; -/* these come from the Intel 80186 datasheet */ -static const struct i80x86_timing _i80x86_timing_tbl_i80186 = { - 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 */ -}; - -// 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 - -#endif diff --git a/source/src/vm/libcpu_newdev/i86_inlineops.h b/source/src/vm/libcpu_newdev/i86_inlineops.h deleted file mode 100644 index b8a82e75b..000000000 --- a/source/src/vm/libcpu_newdev/i86_inlineops.h +++ /dev/null @@ -1,2523 +0,0 @@ -#ifndef __LIBNEWDEV_I86_INLINEOPS_H__ -#define __LIBNEWDEV_I86_INLINEOPS_H__ -#include "./i86_macros.h" - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_add_ald8() /* Opcode 0x04 */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - ADDB(dst, src); - regs.b[AL] = dst; -} - -inline void I86_BASE::_add_axd16() /* Opcode 0x05 */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - ADDW(dst, src); - regs.w[AX] = dst; -} - -inline void I86_BASE::_push_es() /* Opcode 0x06 */ -{ - icount -= timing.push_seg; - PUSH(sregs[ES]); -} - -inline void I86_BASE::_pop_es() /* Opcode 0x07 */ -{ - POP(sregs[ES]); - base[ES] = SegBase(ES); - icount -= timing.pop_seg; -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_or_ald8() /* Opcode 0x0c */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - ORB(dst, src); - regs.b[AL] = dst; -} - -inline void I86_BASE::_or_axd16() /* Opcode 0x0d */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - ORW(dst, src); - regs.w[AX] = dst; -} - -inline void I86_BASE::_push_cs() /* Opcode 0x0e */ -{ - icount -= timing.push_seg; - PUSH(sregs[CS]); -} - - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_adc_ald8() /* Opcode 0x14 */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - src += CF; - ADDB(dst, src); - regs.b[AL] = dst; -} - -inline void I86_BASE::_adc_axd16() /* Opcode 0x15 */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - src += CF; - ADDW(dst, src); - regs.w[AX] = dst; -} - -inline void I86_BASE::_push_ss() /* Opcode 0x16 */ -{ - PUSH(sregs[SS]); - icount -= timing.push_seg; -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_sbb_ald8() /* Opcode 0x1c */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - src += CF; - SUBB(dst, src); - regs.b[AL] = dst; -} - -inline void I86_BASE::_sbb_axd16() /* Opcode 0x1d */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - src += CF; - SUBW(dst, src); - regs.w[AX] = dst; -} - -inline void I86_BASE::_push_ds() /* Opcode 0x1e */ -{ - PUSH(sregs[DS]); - icount -= timing.push_seg; -} - -inline void I86_BASE::_pop_ds() /* Opcode 0x1f */ -{ - POP(sregs[DS]); - base[DS] = SegBase(DS); - icount -= timing.push_seg; -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_and_ald8() /* Opcode 0x24 */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - ANDB(dst, src); - regs.b[AL] = dst; -} - -inline void I86_BASE::_and_axd16() /* Opcode 0x25 */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - ANDW(dst, src); - regs.w[AX] = dst; -} - -inline void I86_BASE::_es() /* Opcode 0x26 */ -{ - seg_prefix = true; - prefix_seg = ES; - icount -= timing.override; - instruction(FETCHOP); -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_sub_ald8() /* Opcode 0x2c */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - SUBB(dst, src); - regs.b[AL] = dst; -} - -inline void I86_BASE::_sub_axd16() /* Opcode 0x2d */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - SUBW(dst, src); - regs.w[AX] = dst; -} - -inline void I86_BASE::_cs() /* Opcode 0x2e */ -{ - seg_prefix = true; - prefix_seg = CS; - icount -= timing.override; - instruction(FETCHOP); -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_xor_ald8() /* Opcode 0x34 */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - XORB(dst, src); - regs.b[AL] = dst; -} - -inline void I86_BASE::_xor_axd16() /* Opcode 0x35 */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - XORW(dst, src); - regs.w[AX] = dst; -} - -inline void I86_BASE::_ss() /* Opcode 0x36 */ -{ - seg_prefix = true; - prefix_seg = SS; - icount -= timing.override; - instruction(FETCHOP); -} - -inline void I86_BASE::_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_BASE::_cmp_br8() /* Opcode 0x38 */ -{ - DEF_br8(dst, src); - icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8; - SUBB(dst, src); -} - -inline void I86_BASE::_cmp_wr16() /* Opcode 0x39 */ -{ - DEF_wr16(dst, src); - icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16; - SUBW(dst, src); -} - -inline void I86_BASE::_cmp_r8b() /* Opcode 0x3a */ -{ - DEF_r8b(dst, src); - icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8; - SUBB(dst, src); -} - -inline void I86_BASE::_cmp_r16w() /* Opcode 0x3b */ -{ - DEF_r16w(dst, src); - icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16; - SUBW(dst, src); -} - -inline void I86_BASE::_cmp_ald8() /* Opcode 0x3c */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - SUBB(dst, src); -} - -inline void I86_BASE::_cmp_axd16() /* Opcode 0x3d */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - SUBW(dst, src); -} - -inline void I86_BASE::_ds() /* Opcode 0x3e */ -{ - seg_prefix = true; - prefix_seg = DS; - icount -= timing.override; - instruction(FETCHOP); -} - -inline void I86_BASE::_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_BASE::_inc_ax() /* Opcode 0x40 */ -{ - IncWordReg(AX); -} - -inline void I86_BASE::_inc_cx() /* Opcode 0x41 */ -{ - IncWordReg(CX); -} - -inline void I86_BASE::_inc_dx() /* Opcode 0x42 */ -{ - IncWordReg(DX); -} - -inline void I86_BASE::_inc_bx() /* Opcode 0x43 */ -{ - IncWordReg(BX); -} - -inline void I86_BASE::_inc_sp() /* Opcode 0x44 */ -{ - IncWordReg(SP); -} - -inline void I86_BASE::_inc_bp() /* Opcode 0x45 */ -{ - IncWordReg(BP); -} - -inline void I86_BASE::_inc_si() /* Opcode 0x46 */ -{ - IncWordReg(SI); -} - -inline void I86_BASE::_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_BASE::_dec_ax() /* Opcode 0x48 */ -{ - DecWordReg(AX); -} - -inline void I86_BASE::_dec_cx() /* Opcode 0x49 */ -{ - DecWordReg(CX); -} - -inline void I86_BASE::_dec_dx() /* Opcode 0x4a */ -{ - DecWordReg(DX); -} - -inline void I86_BASE::_dec_bx() /* Opcode 0x4b */ -{ - DecWordReg(BX); -} - -inline void I86_BASE::_dec_sp() /* Opcode 0x4c */ -{ - DecWordReg(SP); -} - -inline void I86_BASE::_dec_bp() /* Opcode 0x4d */ -{ - DecWordReg(BP); -} - -inline void I86_BASE::_dec_si() /* Opcode 0x4e */ -{ - DecWordReg(SI); -} - -inline void I86_BASE::_dec_di() /* Opcode 0x4f */ -{ - DecWordReg(DI); -} - -inline void I86_BASE::_push_ax() /* Opcode 0x50 */ -{ - icount -= timing.push_r16; - PUSH(regs.w[AX]); -} - -inline void I86_BASE::_push_cx() /* Opcode 0x51 */ -{ - icount -= timing.push_r16; - PUSH(regs.w[CX]); -} - -inline void I86_BASE::_push_dx() /* Opcode 0x52 */ -{ - icount -= timing.push_r16; - PUSH(regs.w[DX]); -} - -inline void I86_BASE::_push_bx() /* Opcode 0x53 */ -{ - icount -= timing.push_r16; - PUSH(regs.w[BX]); -} - -inline void I86_BASE::_push_sp() /* Opcode 0x54 */ -{ - unsigned tmp = regs.w[SP]; - - icount -= timing.push_r16; - PUSH(tmp - 2); -} - -inline void I86_BASE::_push_bp() /* Opcode 0x55 */ -{ - icount -= timing.push_r16; - PUSH(regs.w[BP]); -} - -inline void I86_BASE::_push_si() /* Opcode 0x56 */ -{ - icount -= timing.push_r16; - PUSH(regs.w[SI]); -} - -inline void I86_BASE::_push_di() /* Opcode 0x57 */ -{ - icount -= timing.push_r16; - PUSH(regs.w[DI]); -} - -inline void I86_BASE::_pop_ax() /* Opcode 0x58 */ -{ - icount -= timing.pop_r16; - POP(regs.w[AX]); -} - -inline void I86_BASE::_pop_cx() /* Opcode 0x59 */ -{ - icount -= timing.pop_r16; - POP(regs.w[CX]); -} - -inline void I86_BASE::_pop_dx() /* Opcode 0x5a */ -{ - icount -= timing.pop_r16; - POP(regs.w[DX]); -} - -inline void I86_BASE::_pop_bx() /* Opcode 0x5b */ -{ - icount -= timing.pop_r16; - POP(regs.w[BX]); -} - -inline void I86_BASE::_pop_sp() /* Opcode 0x5c */ -{ - unsigned tmp; - - icount -= timing.pop_r16; - POP(tmp); - regs.w[SP] = tmp; -} - -inline void I86_BASE::_pop_bp() /* Opcode 0x5d */ -{ - icount -= timing.pop_r16; - POP(regs.w[BP]); -} - -inline void I86_BASE::_pop_si() /* Opcode 0x5e */ -{ - icount -= timing.pop_r16; - POP(regs.w[SI]); -} - -inline void I86_BASE::_pop_di() /* Opcode 0x5f */ -{ - icount -= timing.pop_r16; - POP(regs.w[DI]); -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_push_d16() /* Opcode 0x68 */ -{ - unsigned tmp = FETCH; - icount -= timing.push_imm; - tmp += FETCH << 8; - PUSH(tmp); -} - -inline void I86_BASE::_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_BASE::_push_d8() /* Opcode 0x6a */ -{ - unsigned tmp = (uint16_t)((int16_t)((int8_t)FETCH)); - icount -= timing.push_imm; - PUSH(tmp); -} - -inline void I86_BASE::_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_BASE::_insb() /* Opcode 0x6c */ -{ - icount -= timing.ins8; - PutMemB(ES, regs.w[DI], read_port_byte(regs.w[DX])); - regs.w[DI] += DirVal; -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_test_br8() /* Opcode 0x84 */ -{ - DEF_br8(dst, src); - icount -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8; - ANDB(dst, src); -} - -inline void I86_BASE::_test_wr16() /* Opcode 0x85 */ -{ - DEF_wr16(dst, src); - icount -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16; - ANDW(dst, src); -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_lea() /* Opcode 0x8d */ -{ - unsigned ModRM = FETCH; - icount -= timing.lea; - GetEA(ModRM); - RegWord(ModRM) = eo; /* effective offset (no segment part) */ -} - -inline void I86_BASE::_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_BASE::_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_BASE::_nop() /* Opcode 0x90 */ -{ - /* this is XchgAXReg(AX); */ - icount -= timing.nop; -} - -inline void I86_BASE::_xchg_axcx() /* Opcode 0x91 */ -{ - XchgAXReg(CX); -} - -inline void I86_BASE::_xchg_axdx() /* Opcode 0x92 */ -{ - XchgAXReg(DX); -} - -inline void I86_BASE::_xchg_axbx() /* Opcode 0x93 */ -{ - XchgAXReg(BX); -} - -inline void I86_BASE::_xchg_axsp() /* Opcode 0x94 */ -{ - XchgAXReg(SP); -} - -inline void I86_BASE::_xchg_axbp() /* Opcode 0x95 */ -{ - XchgAXReg(BP); -} - -inline void I86_BASE::_xchg_axsi() /* Opcode 0x96 */ -{ - XchgAXReg(SI); -} - -inline void I86_BASE::_xchg_axdi() /* Opcode 0x97 */ -{ - XchgAXReg(DI); -} - -inline void I86_BASE::_cbw() /* Opcode 0x98 */ -{ - icount -= timing.cbw; - regs.b[AH] = (regs.b[AL] & 0x80) ? 0xff : 0; -} - -inline void I86_BASE::_cwd() /* Opcode 0x99 */ -{ - icount -= timing.cwd; - regs.w[DX] = (regs.b[AH] & 0x80) ? 0xffff : 0; -} - - -inline void I86_BASE::_wait() /* Opcode 0x9b */ -{ - if(test_state) { - pc--; - } - icount -= timing.wait; -} - -inline void I86_BASE::_pushf() /* Opcode 0x9c */ -{ - unsigned tmp; - icount -= timing.pushf; - - tmp = CompressFlags(); - PUSH(tmp | 0xf000); -} - -inline void I86_BASE::_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_BASE::_sahf() /* Opcode 0x9e */ -{ - unsigned tmp = (CompressFlags() & 0xff00) | (regs.b[AH] & 0xd5); - icount -= timing.sahf; - ExpandFlags(tmp); -} - -inline void I86_BASE::_lahf() /* Opcode 0x9f */ -{ - regs.b[AH] = CompressFlags() & 0xff; - icount -= timing.lahf; -} - -inline void I86_BASE::_mov_aldisp() /* Opcode 0xa0 */ -{ - unsigned addr; - - addr = FETCH; - addr += FETCH << 8; - - icount -= timing.mov_am8; - regs.b[AL] = GetMemB(DS, addr); -} - -inline void I86_BASE::_mov_axdisp() /* Opcode 0xa1 */ -{ - unsigned addr; - - addr = FETCH; - addr += FETCH << 8; - - icount -= timing.mov_am16; - regs.w[AX] = GetMemW(DS, addr); -} - -inline void I86_BASE::_mov_dispal() /* Opcode 0xa2 */ -{ - unsigned addr; - - addr = FETCH; - addr += FETCH << 8; - - icount -= timing.mov_ma8; - PutMemB(DS, addr, regs.b[AL]); -} - -inline void I86_BASE::_mov_dispax() /* Opcode 0xa3 */ -{ - unsigned addr; - - addr = FETCH; - addr += FETCH << 8; - - icount -= timing.mov_ma16; - PutMemW(DS, addr, regs.w[AX]); -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_test_ald8() /* Opcode 0xa8 */ -{ - DEF_ald8(dst, src); - icount -= timing.alu_ri8; - ANDB(dst, src); -} - -inline void I86_BASE::_test_axd16() /* Opcode 0xa9 */ -{ - DEF_axd16(dst, src); - icount -= timing.alu_ri16; - ANDW(dst, src); -} - -inline void I86_BASE::_stosb() /* Opcode 0xaa */ -{ - PutMemB(ES, regs.w[DI], regs.b[AL]); - regs.w[DI] += DirVal; - icount -= timing.stos8; -} - -inline void I86_BASE::_stosw() /* Opcode 0xab */ -{ - PutMemW(ES, regs.w[DI], regs.w[AX]); - regs.w[DI] += 2 * DirVal; - icount -= timing.stos16; -} - -inline void I86_BASE::_lodsb() /* Opcode 0xac */ -{ - regs.b[AL] = GetMemB(DS, regs.w[SI]); - regs.w[SI] += DirVal; - icount -= timing.lods8; -} - -inline void I86_BASE::_lodsw() /* Opcode 0xad */ -{ - regs.w[AX] = GetMemW(DS, regs.w[SI]); - regs.w[SI] += 2 * DirVal; - icount -= timing.lods16; -} - -inline void I86_BASE::_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_BASE::_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_BASE::_mov_ald8() /* Opcode 0xb0 */ -{ - regs.b[AL] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_cld8() /* Opcode 0xb1 */ -{ - regs.b[CL] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_dld8() /* Opcode 0xb2 */ -{ - regs.b[DL] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_bld8() /* Opcode 0xb3 */ -{ - regs.b[BL] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_ahd8() /* Opcode 0xb4 */ -{ - regs.b[AH] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_chd8() /* Opcode 0xb5 */ -{ - regs.b[CH] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_dhd8() /* Opcode 0xb6 */ -{ - regs.b[DH] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_bhd8() /* Opcode 0xb7 */ -{ - regs.b[BH] = FETCH; - icount -= timing.mov_ri8; -} - -inline void I86_BASE::_mov_axd16() /* Opcode 0xb8 */ -{ - regs.b[AL] = FETCH; - regs.b[AH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_mov_cxd16() /* Opcode 0xb9 */ -{ - regs.b[CL] = FETCH; - regs.b[CH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_mov_dxd16() /* Opcode 0xba */ -{ - regs.b[DL] = FETCH; - regs.b[DH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_mov_bxd16() /* Opcode 0xbb */ -{ - regs.b[BL] = FETCH; - regs.b[BH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_mov_spd16() /* Opcode 0xbc */ -{ - regs.b[SPL] = FETCH; - regs.b[SPH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_mov_bpd16() /* Opcode 0xbd */ -{ - regs.b[BPL] = FETCH; - regs.b[BPH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_mov_sid16() /* Opcode 0xbe */ -{ - regs.b[SIL] = FETCH; - regs.b[SIH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_mov_did16() /* Opcode 0xbf */ -{ - regs.b[DIL] = FETCH; - regs.b[DIH] = FETCH; - icount -= timing.mov_ri16; -} - -inline void I86_BASE::_rotshft_bd8() /* Opcode 0xc0 */ -{ - unsigned ModRM = FETCH; - unsigned count = FETCH; - - rotate_shift_byte(ModRM, count); -} - -inline void I86_BASE::_rotshft_wd8() /* Opcode 0xc1 */ -{ - unsigned ModRM = FETCH; - unsigned count = FETCH; - - rotate_shift_word(ModRM, count); -} - -inline void I86_BASE::_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_BASE::_ret() /* Opcode 0xc3 */ -{ - POP(pc); - pc = (pc + base[CS]) & AMASK; - icount -= timing.ret_near; -} - -inline void I86_BASE::_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_BASE::_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_BASE::_mov_bd8() /* Opcode 0xc6 */ -{ - unsigned ModRM = FETCH; - icount -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8; - PutImmRMByte(ModRM); -} - -inline void I86_BASE::_mov_wd16() /* Opcode 0xc7 */ -{ - unsigned ModRM = FETCH; - icount -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16; - PutImmRMWord(ModRM); -} - -inline void I86_BASE::_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_BASE::_leav() /* Opcode 0xc9 */ -{ - icount -= timing.leave; - regs.w[SP] = regs.w[BP]; - POP(regs.w[BP]); -} - -inline void I86_BASE::_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_BASE::_retf() /* Opcode 0xcb */ -{ - POP(pc); - POP(sregs[CS]); - base[CS] = SegBase(CS); - pc = (pc + base[CS]) & AMASK; - icount -= timing.ret_far; -} - -inline void I86_BASE::_int3() /* Opcode 0xcc */ -{ - icount -= timing.int3; - interrupt(3); -} - -inline void I86_BASE::_into() /* Opcode 0xce */ -{ - if(OF) { - icount -= timing.into_t; - interrupt(OVERFLOW_TRAP); - } else { - icount -= timing.into_nt; - } -} - -inline void I86_BASE::_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_BASE::_rotshft_b() /* Opcode 0xd0 */ -{ - rotate_shift_byte(FETCHOP, 1); -} - -inline void I86_BASE::_rotshft_w() /* Opcode 0xd1 */ -{ - rotate_shift_word(FETCHOP, 1); -} - -inline void I86_BASE::_rotshft_bcl() /* Opcode 0xd2 */ -{ - rotate_shift_byte(FETCHOP, regs.b[CL]); -} - -inline void I86_BASE::_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_BASE::_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_BASE::_setalc() /* Opcode 0xd6 */ -{ - regs.b[AL] = (CF) ? 0xff : 0x00; - icount -= 3; -} - -inline void I86_BASE::_xlat() /* Opcode 0xd7 */ -{ - unsigned dest = regs.w[BX] + regs.b[AL]; - icount -= timing.xlat; - regs.b[AL] = GetMemB(DS, dest); -} - -inline void I86_BASE::_escape() /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */ -{ - unsigned ModRM = FETCH; - icount -= timing.nop; - GetRMByte(ModRM); -} - -inline void I86_BASE::_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_BASE::_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_BASE::_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_BASE::_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_BASE::_inal() /* Opcode 0xe4 */ -{ - unsigned port = FETCH; - icount -= timing.in_imm8; - regs.b[AL] = read_port_byte(port); -} - -inline void I86_BASE::_inax() /* Opcode 0xe5 */ -{ - unsigned port = FETCH; - icount -= timing.in_imm16; - regs.w[AX] = read_port_word(port); -} - -inline void I86_BASE::_outal() /* Opcode 0xe6 */ -{ - unsigned port = FETCH; - icount -= timing.out_imm8; - write_port_byte(port, regs.b[AL]); -} - -inline void I86_BASE::_outax() /* Opcode 0xe7 */ -{ - unsigned port = FETCH; - icount -= timing.out_imm16; - write_port_word(port, regs.w[AX]); -} - - -inline void I86_BASE::_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_BASE::_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_BASE::_jmp_d8() /* Opcode 0xeb */ -{ - int tmp = (int)((int8_t)FETCH); - pc += tmp; - icount -= timing.jmp_short; -} - -inline void I86_BASE::_inaldx() /* Opcode 0xec */ -{ - icount -= timing.in_dx8; - regs.b[AL] = read_port_byte(regs.w[DX]); -} - -inline void I86_BASE::_inaxdx() /* Opcode 0xed */ -{ - unsigned port = regs.w[DX]; - icount -= timing.in_dx16; - regs.w[AX] = read_port_word(port); -} - -inline void I86_BASE::_outdxal() /* Opcode 0xee */ -{ - icount -= timing.out_dx8; - write_port_byte(regs.w[DX], regs.b[AL]); -} - -inline void I86_BASE::_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_BASE::_lock() /* Opcode 0xf0 */ -{ - icount -= timing.nop; - instruction(FETCHOP); /* un-interruptible */ -} - - -inline void I86_BASE::_repne() /* Opcode 0xf2 */ -{ - _rep(0); -} - -inline void I86_BASE::_repe() /* Opcode 0xf3 */ -{ - _rep(1); -} - -inline void I86_BASE::_hlt() /* Opcode 0xf4 */ -{ - pc--; - halted = true; - icount -= 2; -} - -inline void I86_BASE::_cmc() /* Opcode 0xf5 */ -{ - icount -= timing.flag_ops; - CarryVal = !CF; -} - -inline void I86_BASE::_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_BASE::_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_BASE::_clc() /* Opcode 0xf8 */ -{ - icount -= timing.flag_ops; - CarryVal = 0; -} - -inline void I86_BASE::_stc() /* Opcode 0xf9 */ -{ - icount -= timing.flag_ops; - CarryVal = 1; -} - -inline void I86_BASE::_cli() /* Opcode 0xfa */ -{ - icount -= timing.flag_ops; - SetIF(0); -} - -inline void I86_BASE::_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_BASE::_cld() /* Opcode 0xfc */ -{ - icount -= timing.flag_ops; - SetDF(0); -} - -inline void I86_BASE::_std() /* Opcode 0xfd */ -{ - icount -= timing.flag_ops; - SetDF(1); -} - -inline void I86_BASE::_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_BASE::_invalid() -{ - /* i8086/i8088 ignore an invalid opcode. */ - /* i80186/i80188 probably also ignore an invalid opcode. */ - icount -= 10; -} - -// Below are workaround VMs using another CPU. -#undef SetTF -#undef SetIF -#undef SetDF -#undef SetMD - -#undef SetOFW_Add -#undef SetOFB_Add -#undef SetOFW_Sub -#undef SetOFB_Sub - -#undef SetCFB -#undef SetCFW -#undef SetAF -#undef SetSF -#undef SetZF -#undef SetPF - -#undef SetSZPF_Byte -#undef SetSZPF_Word - -#undef ADDB -#undef ADDW - -#undef SUBB -#undef SUBW - -#undef ORB -#undef ORW - -#undef ANDB -#undef ANDW - -#undef XORB -#undef XORW - -#undef CF -#undef SF -#undef ZF -#undef PF -#undef AF -#undef OF -#undef DF -#undef MD - -/************************************************************************/ - -#undef AMASK - -#undef read_mem_byte -#undef read_mem_word -#undef write_mem_byte -#undef write_mem_word - -#undef read_port_byte -#undef read_port_word -#undef write_port_byte -#undef write_port_word - -/************************************************************************/ - -#undef SegBase - -#undef DefaultSeg -#undef DefaultBase - -#undef GetMemB -#undef GetMemW -#undef PutMemB -#undef PutMemW - -#undef ReadByte -#undef ReadWord -#undef WriteByte -#undef WriteWord -#undef FETCH -#undef FETCHOP -#undef FETCHWORD -#undef PUSH -#undef POP - -/************************************************************************/ - -#undef CompressFlags -#undef ExpandFlags -#undef RegWord -#undef RegByte -#undef GetRMWord -#undef PutbackRMWord -#undef GetNextRMWord -#undef GetRMWordOffset -#undef GetRMByteOffset -#undef PutRMWord -#undef PutRMWordOffset -#undef PutRMByteOffset -#undef PutImmRMWord -#undef GetRMByte -#undef PutRMByte -#undef PutImmRMByte -#undef PutbackRMByte -#undef DEF_br8 -#undef DEF_wr16 -#undef DEF_r8b -#undef DEF_r16w -#undef DEF_ald8 -#undef DEF_axd16 - -#endif diff --git a/source/src/vm/libcpu_newdev/i86_macros.h b/source/src/vm/libcpu_newdev/i86_macros.h deleted file mode 100644 index 486769d24..000000000 --- a/source/src/vm/libcpu_newdev/i86_macros.h +++ /dev/null @@ -1,218 +0,0 @@ - -/************************************************************************/ - -#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) - -/************************************************************************/ - -/* Highly useful macro for compile-time knowledge of an array size */ -#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])) - diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i186.cpp b/source/src/vm/libcpu_newdev/libcpu_i286/i186.cpp deleted file mode 100644 index 1d6bf4018..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i186.cpp +++ /dev/null @@ -1,1725 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -// Peripheral code from rmnimbus driver by Phill Harvey-Smith which is -// based on the Leland sound driver by Aaron Giles and Paul Leaman - -#include "emu.h" -#include "i186.h" -#include "debugger.h" -#include "i86inline.h" - -#define LOG_PORTS 0 -#define LOG_INTERRUPTS 0 -#define LOG_INTERRUPTS_EXT 0 -#define LOG_TIMER 0 -#define LOG_DMA 0 - -/* external int priority masks */ - -#define EXTINT_CTRL_PRI_MASK 0x07 -#define EXTINT_CTRL_MSK 0x08 -#define EXTINT_CTRL_LTM 0x10 -#define EXTINT_CTRL_CASCADE 0x20 -#define EXTINT_CTRL_SFNM 0x40 - -/* DMA control register */ - -#define DEST_MIO 0x8000 -#define DEST_DECREMENT 0x4000 -#define DEST_INCREMENT 0x2000 -#define DEST_NO_CHANGE (DEST_DECREMENT | DEST_INCREMENT) -#define DEST_INCDEC_MASK (DEST_DECREMENT | DEST_INCREMENT) -#define SRC_MIO 0x1000 -#define SRC_DECREMENT 0x0800 -#define SRC_INCREMENT 0x0400 -#define SRC_NO_CHANGE (SRC_DECREMENT | SRC_INCREMENT) -#define SRC_INCDEC_MASK (SRC_DECREMENT | SRC_INCREMENT) -#define TERMINATE_ON_ZERO 0x0200 -#define INTERRUPT_ON_ZERO 0x0100 -#define SYNC_MASK 0x00C0 -#define SYNC_SOURCE 0x0040 -#define SYNC_DEST 0x0080 -#define CHANNEL_PRIORITY 0x0020 -#define TIMER_DRQ 0x0010 -#define CHG_NOCHG 0x0004 -#define ST_STOP 0x0002 -#define BYTE_WORD 0x0001 - -/* these come from the Intel 80186 datasheet */ -const uint8_t i80186_cpu_device::m_i80186_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 */ -}; - -const device_type I80186 = device_creator; -const device_type I80188 = device_creator; - -i80188_cpu_device::i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : i80186_cpu_device(mconfig, I80188, "I80188", tag, owner, clock, "i80188", __FILE__, 8) -{ - memcpy(m_timing, m_i80186_timing, sizeof(m_i80186_timing)); - m_fetch_xor = 0; - static_set_irq_acknowledge_callback(*this, device_irq_acknowledge_delegate(FUNC(i80186_cpu_device::int_callback), this)); -} - -i80186_cpu_device::i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : i8086_common_cpu_device(mconfig, I80186, "I80186", tag, owner, clock, "i80186", __FILE__) - , m_program_config("program", ENDIANNESS_LITTLE, 16, 20, 0) - , m_io_config("io", ENDIANNESS_LITTLE, 16, 16, 0) - , m_read_slave_ack_func(*this) - , m_out_chip_select_func(*this) - , m_out_tmrout0_func(*this) - , m_out_tmrout1_func(*this) -{ - memcpy(m_timing, m_i80186_timing, sizeof(m_i80186_timing)); - m_fetch_xor = BYTE_XOR_LE(0); - static_set_irq_acknowledge_callback(*this, device_irq_acknowledge_delegate(FUNC(i80186_cpu_device::int_callback), this)); -} - -i80186_cpu_device::i80186_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source, int data_bus_size) - : i8086_common_cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) - , m_program_config("program", ENDIANNESS_LITTLE, data_bus_size, 20, 0) - , m_io_config("io", ENDIANNESS_LITTLE, data_bus_size, 16, 0) - , m_read_slave_ack_func(*this) - , m_out_chip_select_func(*this) - , m_out_tmrout0_func(*this) - , m_out_tmrout1_func(*this) -{ -} - - - -uint8_t i80186_cpu_device::fetch_op() -{ - uint8_t data = m_direct_opcodes->read_byte(pc(), m_fetch_xor); - m_ip++; - return data; -} - -uint8_t i80186_cpu_device::fetch() -{ - uint8_t data = m_direct_opcodes->read_byte(pc(), m_fetch_xor); - m_ip++; - return data; -} - -void i80186_cpu_device::execute_run() -{ - while(m_icount > 0 ) - { - if ( m_seg_prefix_next ) - { - m_seg_prefix = true; - m_seg_prefix_next = false; - } - else - { - m_prev_ip = m_ip; - m_seg_prefix = false; - - /* Dispatch IRQ */ - if ( m_pending_irq && m_no_interrupt == 0 ) - { - if ( m_pending_irq & NMI_IRQ ) - { - interrupt(2); - m_pending_irq &= ~NMI_IRQ; - m_halt = false; - } - else if ( m_IF ) - { - /* the actual vector is retrieved after pushing flags */ - /* and clearing the IF */ - interrupt(-1); - m_halt = false; - } - } - - if(m_halt) - { - m_icount = 0; - return; - } - - /* No interrupt allowed between last instruction and this one */ - if ( m_no_interrupt ) - { - m_no_interrupt--; - } - - /* trap should allow one instruction to be executed */ - if ( m_fire_trap ) - { - if ( m_fire_trap >= 2 ) - { - interrupt(1); - m_fire_trap = 0; - } - else - { - m_fire_trap++; - } - } - } - - debugger_instruction_hook( this, pc() ); - - uint8_t op = fetch_op(); - - switch(op) - { - case 0x60: // i_pusha - { - uint32_t tmp = m_regs.w[SP]; - - PUSH(m_regs.w[AX]); - PUSH(m_regs.w[CX]); - PUSH(m_regs.w[DX]); - PUSH(m_regs.w[BX]); - PUSH(tmp); - PUSH(m_regs.w[BP]); - PUSH(m_regs.w[SI]); - PUSH(m_regs.w[DI]); - CLK(PUSHA); - } - break; - - case 0x61: // i_popa - m_regs.w[DI] = POP(); - m_regs.w[SI] = POP(); - m_regs.w[BP] = POP(); - POP(); - m_regs.w[BX] = POP(); - m_regs.w[DX] = POP(); - m_regs.w[CX] = POP(); - m_regs.w[AX] = POP(); - CLK(POPA); - break; - - case 0x62: // i_bound - { - uint32_t low,high,tmp; - m_modrm = fetch(); - low = GetRMWord(); - high = GetnextRMWord(); - tmp = RegWord(); - if (tmphigh) - interrupt(5); - CLK(BOUND); - logerror("%06x: bound %04x high %04x low %04x tmp\n", pc(), high, low, tmp); - } - break; - - case 0x68: // i_push_d16 - PUSH( fetch_word() ); - CLK(PUSH_IMM); - break; - - case 0x69: // i_imul_d16 - { - uint32_t tmp; - DEF_r16w(); - tmp = fetch_word(); - m_dst = (int32_t)((int16_t)m_src)*(int32_t)((int16_t)tmp); - m_CarryVal = m_OverVal = (((int32_t)m_dst) >> 15 != 0) && (((int32_t)m_dst) >> 15 != -1); - RegWord(m_dst); - CLKM(IMUL_RRI16, IMUL_RMI16); - } - break; - - case 0x6a: // i_push_d8 - PUSH( (uint16_t)((int16_t)((int8_t)fetch())) ); - CLK(PUSH_IMM); - break; - - case 0x6b: // i_imul_d8 - { - uint32_t src2; - DEF_r16w(); - src2= (uint16_t)((int16_t)((int8_t)fetch())); - m_dst = (int32_t)((int16_t)m_src)*(int32_t)((int16_t)src2); - m_CarryVal = m_OverVal = (((int32_t)m_dst) >> 15 != 0) && (((int32_t)m_dst) >> 15 != -1); - RegWord(m_dst); - CLKM(IMUL_RRI8, IMUL_RMI8); - } - break; - - case 0x6c: // i_insb - i_insb(); - break; - - case 0x6d: // i_insw - i_insw(); - break; - - case 0x6e: // i_outsb - i_outsb(); - break; - - case 0x6f: // i_outsw - i_outsw(); - break; - - case 0x8e: // i_mov_sregw - m_modrm = fetch(); - m_src = GetRMWord(); - CLKM(MOV_SR,MOV_SM); - switch (m_modrm & 0x38) - { - case 0x00: /* mov es,ew */ - m_sregs[ES] = m_src; - break; - case 0x10: /* mov ss,ew */ - m_sregs[SS] = m_src; - m_no_interrupt = 1; - break; - case 0x18: /* mov ds,ew */ - m_sregs[DS] = m_src; - break; - default: - logerror("%06x: Mov Sreg - Invalid register\n", pc()); - m_ip = m_prev_ip; - interrupt(6); - break; - } - break; - - case 0xc0: // i_rotshft_bd8 - { - uint8_t c; - m_modrm = fetch(); - m_src = GetRMByte(); - m_dst = m_src; - c = fetch() & 0x1f; - CLKM(ROT_REG_BASE,ROT_M8_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x30: - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x38: SHRA_BYTE(c); break; - } - } - } - break; - - case 0xc1: // i_rotshft_wd8 - { - uint8_t c; - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - c = fetch() & 0x1f; - CLKM(ROT_REG_BASE,ROT_M16_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x30: - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x38: SHRA_WORD(c); break; - } - } - } - break; - - case 0xc8: // i_enter - { - uint16_t nb = fetch(); - uint32_t level; - - nb |= fetch() << 8; - level = fetch(); - CLK(!level ? ENTER0 : (level == 1) ? ENTER1 : ENTER_BASE); - if(level > 1) - m_icount -= level * m_timing[ENTER_COUNT]; - PUSH(m_regs.w[BP]); - m_regs.w[BP] = m_regs.w[SP]; - m_regs.w[SP] -= nb; - for (int i=1; i0); PutbackRMByte(m_dst); break; - case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x30: - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x38: SHRA_BYTE(c); break; - } - } - } - break; - - case 0xd3: // i_rotshft_wcl - { - uint8_t c; - - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - c = m_regs.b[CL] & 0x1f; - CLKM(ROT_REG_BASE,ROT_M16_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x30: - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x38: SHRA_WORD(c); break; - } - } - } - break; - - case 0xd8: // i_esc - case 0xd9: - case 0xda: - case 0xdb: - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: - if(m_reloc & 0x8000) - { - m_ip = m_prev_ip; - interrupt(7); - break; - } - m_modrm = fetch(); - GetRMByte(); - CLK(NOP); - // The 80187 has the FSTSW AX instruction - if((m_modrm == 0xe0) && (op == 0xdf)) - m_regs.w[AX] = 0xffff; // FPU not present - break; - - case 0xf2: // i_repne - case 0xf3: - { - bool pass = false; - uint8_t next = repx_op(); - uint16_t c = m_regs.w[CX]; - - switch (next) - { - case 0x6c: CLK(OVERRIDE); if (c) do { i_insb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6d: CLK(OVERRIDE); if (c) do { i_insw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6e: CLK(OVERRIDE); if (c) do { i_outsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6f: CLK(OVERRIDE); if (c) do { i_outsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - default: - // Decrement IP and pass on - m_ip -= 1 + (m_seg_prefix_next ? 1 : 0); - pass = true; - break; - } - if(!pass) - { - if(c) - m_ip = m_prev_ip; - break; - } - } - // through to default - default: - if(!common_op(op)) - { - m_icount -= 10; // UD fault timing? - logerror("%06x: Invalid Opcode %02x\n", pc(), op); - m_ip = m_prev_ip; - interrupt(6); // 80186 has #UD - break; - } - } - } -} - -void i80186_cpu_device::device_start() -{ - i8086_common_cpu_device::device_start(); - state_add( I8086_ES, "ES", m_sregs[ES] ).formatstr("%04X"); - state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().formatstr("%04X"); - state_add( I8086_SS, "SS", m_sregs[SS] ).formatstr("%04X"); - state_add( I8086_DS, "DS", m_sregs[DS] ).formatstr("%04X"); - state_add( I8086_VECTOR, "V", m_int_vector).formatstr("%02X"); - - state_add( I8086_PC, "PC", m_pc ).callimport().formatstr("%05X"); - state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%05X").noshow(); - state_add( I8086_HALT, "HALT", m_halt ).mask(1); - - // register for savestates - save_item(NAME(m_timer[0].control)); - save_item(NAME(m_timer[0].maxA)); - save_item(NAME(m_timer[0].maxB)); - save_item(NAME(m_timer[0].active_count)); - save_item(NAME(m_timer[0].count)); - save_item(NAME(m_timer[1].control)); - save_item(NAME(m_timer[1].maxA)); - save_item(NAME(m_timer[1].maxB)); - save_item(NAME(m_timer[1].active_count)); - save_item(NAME(m_timer[1].count)); - save_item(NAME(m_timer[2].control)); - save_item(NAME(m_timer[2].maxA)); - save_item(NAME(m_timer[2].count)); - save_item(NAME(m_dma[0].source)); - save_item(NAME(m_dma[0].dest)); - save_item(NAME(m_dma[0].count)); - save_item(NAME(m_dma[0].control)); - save_item(NAME(m_dma[1].source)); - save_item(NAME(m_dma[1].dest)); - save_item(NAME(m_dma[1].count)); - save_item(NAME(m_dma[1].control)); - save_item(NAME(m_intr.pending)); - save_item(NAME(m_intr.ack_mask)); - save_item(NAME(m_intr.priority_mask)); - save_item(NAME(m_intr.in_service)); - save_item(NAME(m_intr.request)); - save_item(NAME(m_intr.status)); - save_item(NAME(m_intr.poll_status)); - save_item(NAME(m_intr.timer)); - save_item(NAME(m_intr.dma)); - save_item(NAME(m_intr.ext)); - save_item(NAME(m_intr.ext_state)); - save_item(NAME(m_mem.lower)); - save_item(NAME(m_mem.upper)); - save_item(NAME(m_mem.middle)); - save_item(NAME(m_mem.middle_size)); - save_item(NAME(m_mem.peripheral)); - save_item(NAME(m_reloc)); - - // zerofill - memset(m_timer, 0, sizeof(m_timer)); - memset(m_dma, 0, sizeof(m_dma)); - memset(&m_intr, 0, sizeof(intr_state)); - memset(&m_mem, 0, sizeof(mem_state)); - m_reloc = 0; - - m_timer[0].int_timer = timer_alloc(TIMER_INT0); - m_timer[1].int_timer = timer_alloc(TIMER_INT1); - m_timer[2].int_timer = timer_alloc(TIMER_INT2); - - m_out_tmrout0_func.resolve_safe(); - m_out_tmrout1_func.resolve_safe(); - m_read_slave_ack_func.resolve_safe(0); - m_out_chip_select_func.resolve_safe(); -} - -void i80186_cpu_device::device_reset() -{ - i8086_common_cpu_device::device_reset(); - /* reset the interrupt state */ - m_intr.priority_mask = 0x0007; - m_intr.timer = 0x000f; - m_intr.dma[0] = 0x000f; - m_intr.dma[1] = 0x000f; - m_intr.ext[0] = 0x000f; - m_intr.ext[1] = 0x000f; - m_intr.ext[2] = 0x000f; - m_intr.ext[3] = 0x000f; - m_intr.in_service = 0x0000; - - m_intr.pending = 0x0000; - m_intr.ack_mask = 0x0000; - m_intr.request = 0x0000; - m_intr.status = 0x0000; - m_intr.poll_status = 0x0000; - m_intr.ext_state = 0x00; - m_reloc = 0x20ff; - - for (auto & elem : m_dma) - { - elem.drq_state = false; - elem.control = 0; - } - - for (auto & elem : m_timer) - { - elem.control = 0; - elem.maxA = 0; - elem.maxB = 0; - elem.active_count = false; - elem.count = 0; - } -} - -uint8_t i80186_cpu_device::read_port_byte(uint16_t port) -{ - if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) - { - uint16_t ret = internal_port_r(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7), (port & 1) ? 0xff00 : 0x00ff); - return (port & 1) ? (ret >> 8) : (ret & 0xff); - } - return m_io->read_byte(port); -} - -uint16_t i80186_cpu_device::read_port_word(uint16_t port) -{ - if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) - { - if(port & 1) - { - uint8_t low = read_port_byte(port); - return read_port_byte(port + 1) << 8 | low; - } - return internal_port_r(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7)); - } - return m_io->read_word_unaligned(port); -} - -void i80186_cpu_device::write_port_byte(uint16_t port, uint8_t data) -{ - if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) - internal_port_w(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7), (port & 1) ? (data << 8) : data, (port & 1) ? 0xff00 : 0x00ff); - else - m_io->write_byte(port, data); -} - -void i80186_cpu_device::write_port_word(uint16_t port, uint16_t data) -{ - if(!(m_reloc & 0x1000) && (port >> 8) == (m_reloc & 0xff)) - { - if(port & 1) - { - write_port_byte(port, data & 0xff); - write_port_byte(port + 1, data >> 8); - } - else - internal_port_w(*m_io, (port >> 1) - ((m_reloc & 0xff) << 7), data); - } - else - m_io->write_word_unaligned(port, data); -} - -/************************************* - * - * 80186 interrupt controller - * - *************************************/ -IRQ_CALLBACK_MEMBER(i80186_cpu_device::int_callback) -{ - uint8_t vector; - uint16_t old; - uint16_t oldreq; - - if (LOG_INTERRUPTS) - logerror("(%f) **** Acknowledged interrupt vector %02X\n", machine().time().as_double(), m_intr.poll_status & 0x1f); - - /* clear the interrupt */ - set_input_line(0, CLEAR_LINE); - m_intr.pending = 0; - - oldreq = m_intr.request; - - /* clear the request and set the in-service bit */ - if(m_intr.ack_mask & 0xf0) - { - int i; - for(i = 0; i < 4; i++) - if((m_intr.ack_mask >> (i + 4)) & 1) - break; - if(!(m_intr.ext[i] & EXTINT_CTRL_LTM)) - m_intr.request &= ~m_intr.ack_mask; - } - else - m_intr.request &= ~m_intr.ack_mask; - - if((LOG_INTERRUPTS) && (m_intr.request!=oldreq)) - logerror("intr.request changed from %02X to %02X\n",oldreq,m_intr.request); - - old = m_intr.in_service; - - m_intr.in_service |= m_intr.ack_mask; - - if((LOG_INTERRUPTS) && (m_intr.in_service!=old)) - logerror("intr.in_service changed from %02X to %02X\n",old,m_intr.in_service); - - if (m_intr.ack_mask == 0x0001) - { - switch (m_intr.poll_status & 0x1f) - { - case 0x08: m_intr.status &= ~0x01; break; - case 0x12: m_intr.status &= ~0x02; break; - case 0x13: m_intr.status &= ~0x04; break; - } - } - m_intr.ack_mask = 0; - - /* a request no longer pending */ - m_intr.poll_status &= ~0x8000; - - /* return the vector */ - switch(m_intr.poll_status & 0x1F) - { - case 0x0C: vector = (m_intr.ext[0] & EXTINT_CTRL_CASCADE) ? m_read_slave_ack_func(0) : (m_intr.poll_status & 0x1f); break; - case 0x0D: vector = (m_intr.ext[1] & EXTINT_CTRL_CASCADE) ? m_read_slave_ack_func(1) : (m_intr.poll_status & 0x1f); break; - default: - vector = m_intr.poll_status & 0x1f; break; - } - - if (LOG_INTERRUPTS) - { - logerror("intr.ext[0]=%04X intr.ext[1]=%04X\n",m_intr.ext[0],m_intr.ext[1]); - logerror("Int %02X Calling vector %02X\n",m_intr.poll_status,vector); - } - - return vector; -} - - -void i80186_cpu_device::update_interrupt_state() -{ - int new_vector = 0; - int Priority; - int IntNo; - - if (LOG_INTERRUPTS) - logerror("update_interrupt_status: req=%04X stat=%04X serv=%04X priority_mask=%4X\n", m_intr.request, m_intr.status, m_intr.in_service, m_intr.priority_mask); - - /* loop over priorities */ - for (Priority = 0; Priority <= m_intr.priority_mask; Priority++) - { - /* note: by checking 4 bits, we also verify that the mask is off */ - if ((m_intr.timer & 0x0F) == Priority) - { - /* if we're already servicing something at this level, don't generate anything new */ - if (m_intr.in_service & 0x01) - return; - - /* if there's something pending, generate an interrupt */ - if (m_intr.status & 0x07) - { - if (m_intr.status & 1) - new_vector = 0x08; - else if (m_intr.status & 2) - new_vector = 0x12; - else if (m_intr.status & 4) - new_vector = 0x13; - else - logerror("Invalid timer interrupt!\n"); - - /* set the clear mask and generate the int */ - m_intr.ack_mask = 0x0001; - goto generate_int; - } - } - - /* check DMA interrupts */ - for (IntNo = 0; IntNo < 2; IntNo++) - if ((m_intr.dma[IntNo] & 0x0F) == Priority) - { - /* if we're already servicing something at this level, don't generate anything new */ - if (m_intr.in_service & (0x04 << IntNo)) - return; - - /* if there's something pending, generate an interrupt */ - if (m_intr.request & (0x04 << IntNo)) - { - new_vector = 0x0a + IntNo; - - /* set the clear mask and generate the int */ - m_intr.ack_mask = 0x0004 << IntNo; - goto generate_int; - } - } - - /* check external interrupts */ - for (IntNo = 0; IntNo < 4; IntNo++) - { - if ((m_intr.ext[IntNo] & 0x0F) == Priority) - { - if (LOG_INTERRUPTS) - logerror("Int%d priority=%d\n",IntNo,Priority); - - /* if we're already servicing something at this level, don't generate anything new */ - if ((m_intr.in_service & (0x10 << IntNo)) && !(m_intr.ext[IntNo] & EXTINT_CTRL_SFNM)) - return; - - /* if there's something pending, generate an interrupt */ - if (m_intr.request & (0x10 << IntNo)) - { - if((IntNo >= 2) && (m_intr.ext[IntNo - 2] & EXTINT_CTRL_CASCADE)) - { - logerror("i186: %06x: irq %d use when set for cascade mode\n", pc(), IntNo); - m_intr.request &= ~(0x10 << IntNo); - continue; - } - /* otherwise, generate an interrupt for this request */ - new_vector = 0x0c + IntNo; - - /* set the clear mask and generate the int */ - m_intr.ack_mask = 0x0010 << IntNo; - goto generate_int; - } - else if ((m_intr.in_service & (0x10 << IntNo)) && (m_intr.ext[IntNo] & EXTINT_CTRL_SFNM)) - return; // if an irq is in service and sfnm is enabled, stop here - } - } - } - m_intr.pending = 0; - set_input_line(0, CLEAR_LINE); - return; - -generate_int: - /* generate the appropriate interrupt */ - m_intr.poll_status = 0x8000 | new_vector; - if (!m_intr.pending) - set_input_line(0, ASSERT_LINE); - m_intr.pending = 1; - if (LOG_INTERRUPTS) logerror("(%f) **** Requesting interrupt vector %02X\n", machine().time().as_double(), new_vector); -} - - -void i80186_cpu_device::handle_eoi(int data) -{ - int Priority; - int IntNo; - int handled=0; - - /* specific case */ - if (!(data & 0x8000)) - { - /* turn off the appropriate in-service bit */ - switch (data & 0x1f) - { - case 0x08: m_intr.in_service &= ~0x01; break; - case 0x12: m_intr.in_service &= ~0x01; break; - case 0x13: m_intr.in_service &= ~0x01; break; - case 0x0a: m_intr.in_service &= ~0x04; break; - case 0x0b: m_intr.in_service &= ~0x08; break; - case 0x0c: m_intr.in_service &= ~0x10; break; - case 0x0d: m_intr.in_service &= ~0x20; break; - case 0x0e: m_intr.in_service &= ~0x40; break; - case 0x0f: m_intr.in_service &= ~0x80; break; - default: logerror("%05X:ERROR - 80186 EOI with unknown vector %02X\n", pc(), data & 0x1f); - } - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for vector %02X\n", machine().time().as_double(), data & 0x1f); - } - - /* non-specific case */ - else - { - /* loop over priorities */ - for (Priority = 0; ((Priority <= 7) && !handled); Priority++) - { - /* check for in-service timers */ - if ((m_intr.timer & 0x07) == Priority && (m_intr.in_service & 0x01)) - { - m_intr.in_service &= ~0x01; - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for timer\n", machine().time().as_double()); - handled=1; - } - - /* check for in-service DMA interrupts */ - for (IntNo = 0; ((IntNo < 2) && !handled) ; IntNo++) - if ((m_intr.dma[IntNo] & 0x07) == Priority && (m_intr.in_service & (0x04 << IntNo))) - { - m_intr.in_service &= ~(0x04 << IntNo); - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for DMA%d\n", machine().time().as_double(), IntNo); - handled=1; - } - - /* check external interrupts */ - for (IntNo = 0; ((IntNo < 4) && !handled) ; IntNo++) - if ((m_intr.ext[IntNo] & 0x07) == Priority && (m_intr.in_service & (0x10 << IntNo))) - { - m_intr.in_service &= ~(0x10 << IntNo); - if (LOG_INTERRUPTS) logerror("(%f) **** Got EOI for INT%d\n", machine().time().as_double(), IntNo); - handled=1; - } - } - } - update_interrupt_state(); -} - -/* Trigger an external interrupt, optionally supplying the vector to take */ -void i80186_cpu_device::external_int(uint16_t intno, int state) -{ - if (!(m_intr.ext_state & (1 << intno)) == !state) - return; - - if (LOG_INTERRUPTS_EXT) logerror("generating external int %02X\n",intno); - - if (!state) - { - m_intr.request &= ~(0x10 << intno); - m_intr.ack_mask &= ~(0x10 << intno); - m_intr.ext_state &= ~(1 << intno); - } - else // Turn on the requested request bit and handle interrupt - { - m_intr.request |= (0x10 << intno); - m_intr.ext_state |= (1 << intno); - } - update_interrupt_state(); -} - -/************************************* - * - * 80186 internal timers - * - *************************************/ - -void i80186_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch(id) - { - case TIMER_INT0: - case TIMER_INT1: - case TIMER_INT2: - { - int which = param; - timer_state *t = &m_timer[which]; - - if (LOG_TIMER) logerror("Hit interrupt callback for timer %d\n", which); - - /* set the max count bit */ - t->control |= 0x0020; - - /* request an interrupt */ - if (t->control & 0x2000) - { - m_intr.status |= 0x01 << which; - update_interrupt_state(); - if (LOG_TIMER) logerror(" Generating timer interrupt\n"); - } - - if(which == 2) - { - if((m_dma[0].control & (TIMER_DRQ | ST_STOP)) == TIMER_DRQ) - drq_callback(0); - if((m_dma[1].control & (TIMER_DRQ | ST_STOP)) == TIMER_DRQ) - drq_callback(1); - if((m_timer[0].control & 0x800c) == 0x8008) - inc_timer(0); - if((m_timer[1].control & 0x800c) == 0x8008) - inc_timer(1); - } - else - { - if(!(t->control & 2)) - { - if(which) - m_out_tmrout1_func(1); - else - m_out_tmrout0_func(1); - } - else - { - if(which) - m_out_tmrout1_func(t->active_count); - else - m_out_tmrout0_func(t->active_count); - } - } - - /* if we're continuous or altcounting, reset */ - if((t->control & 1) || ((t->control & 2) && (which != 2) && !t->active_count)) - { - int count; - if((t->control & 2) && (which != 2)) - { - count = t->active_count ? t->maxA : t->maxB; - if(!t->active_count) - { - t->active_count = 1; - t->control |= 0x1000; - } - else - { - t->active_count = 0; - t->control &= ~0x1000; - } - } - else - count = t->maxA; - - count = count ? count : 0x10000; - if(!(t->control & 4)) - t->int_timer->adjust((attotime::from_hz(clock()/8) * count), which); - if (LOG_TIMER) logerror(" Repriming interrupt\n"); - } - else - { - t->int_timer->adjust(attotime::never, which); - t->control &= ~0x9000; - } - t->count = 0; - break; - } - - default: - break; - } -} - - -void i80186_cpu_device::internal_timer_sync(int which) -{ - timer_state *t = &m_timer[which]; - - /* if we have a timing timer running, adjust the count */ - if ((t->control & 0x8000) && !(t->control & 0x0c)) - t->count = (((which != 2) && t->active_count) ? t->maxB : t->maxA) - t->int_timer->remaining().as_ticks(clock() / 8); -} - -void i80186_cpu_device::inc_timer(int which) -{ - timer_state *t = &m_timer[which]; - - t->count++; - if (t->control & 2) - { - if (t->count == (t->active_count ? t->maxB : t->maxA)) - device_timer(*t->int_timer, which, which, nullptr); - } - else if (t->count == t->maxA) - device_timer(*t->int_timer, which, which, nullptr); -} - -void i80186_cpu_device::internal_timer_update(int which, int new_count, int new_maxA, int new_maxB, int new_control) -{ - timer_state *t = &m_timer[which]; - int update_int_timer = 0; - - if (LOG_TIMER) - logerror("internal_timer_update: %d, new_count=%d, new_maxA=%d, new_maxB=%d,new_control=%d\n", which, new_count, new_maxA, new_maxB, new_control); - - /* if we have a new count and we're on, update things */ - if (new_count != -1) - { - if (t->control & 0x8000) - { - internal_timer_sync(which); - update_int_timer = 1; - } - t->count = new_count; - } - - /* if we have a new max and we're on, update things */ - if (new_maxA != -1 && new_maxA != t->maxA) - { - if (t->control & 0x8000) - { - internal_timer_sync(which); - update_int_timer = 1; - } - - t->maxA = new_maxA; - - if (new_maxA == 0) - { - new_maxA = 0x10000; - } - } - - /* if we have a new max and we're on, update things */ - if (new_maxB != -1 && new_maxB != t->maxB) - { - if (t->control & 0x8000) - { - internal_timer_sync(which); - update_int_timer = 1; - } - - t->maxB = new_maxB; - - if (new_maxB == 0) - { - new_maxB = 0x10000; - } - } - - /* handle control changes */ - if (new_control != -1) - { - int diff; - uint16_t resbits = (which == 2) ? 0x1fde : 0x1fc0; - - /* merge back in the bits we don't modify */ - new_control = (new_control & ~resbits) | (t->control & resbits); - - /* handle the /INH bit */ - if (!(new_control & 0x4000)) - new_control = (new_control & ~0x8000) | (t->control & 0x8000); - new_control &= ~0x4000; - - /* check for control bits we don't handle */ - diff = new_control ^ t->control; - if (diff & 0x0010) - logerror("%05X:ERROR! -unsupported timer mode %04X\n", pc(), new_control); - - /* if we have real changes, update things */ - if (diff != 0) - { - /* if we're going off, make sure our timers are gone */ - if ((diff & 0x8000) && !(new_control & 0x8000)) - { - /* compute the final count */ - internal_timer_sync(which); - update_int_timer = 1; - } - - /* if we're going on, start the timers running except with external clock or prescale */ - else if ((diff & 0x8000) && (new_control & 0x8000) && !(new_control & 0xc)) - { - update_int_timer = 1; - } - - /* if something about the interrupt timer changed, force an update */ - if (!(diff & 0x8000) && (diff & 0x2000)) - { - internal_timer_sync(which); - update_int_timer = 1; - } - } - - /* set the new control register */ - t->control = new_control; - } - - /* update the interrupt timer */ - if (update_int_timer) - { - t->active_count = 0; - t->control &= ~0x1000; - if ((t->control & 0x8000) && !(t->control & 4)) - { - int diff = t->maxA - t->count; - if (diff <= 0) - diff += 0x10000; - t->int_timer->adjust(attotime::from_hz(clock()/8) * diff, which); - if (LOG_TIMER) logerror("Set interrupt timer for %d\n", which); - } - else - { - t->int_timer->adjust(attotime::never, which); - } - } -} - - - -/************************************* - * - * 80186 internal DMA - * - *************************************/ - -void i80186_cpu_device::update_dma_control(int which, int new_control) -{ - dma_state *d = &m_dma[which]; - int diff; - - /* handle the CHG bit */ - if (!(new_control & CHG_NOCHG)) - new_control = (new_control & ~ST_STOP) | (d->control & ST_STOP); - new_control &= ~CHG_NOCHG; - - /* check for control bits we don't handle */ - diff = new_control ^ d->control; - if ((LOG_DMA) && (diff & 0x6811)) - logerror("%05X:ERROR! - unsupported DMA mode %04X\n", pc(), new_control); - - if (LOG_DMA) logerror("Initiated DMA %d - count = %04X, source = %04X, dest = %04X\n", which, d->count, d->source, d->dest); - - /* set the new control register */ - d->control = new_control; -} - -void i80186_cpu_device::drq_callback(int which) -{ - dma_state *dma = &m_dma[which]; - - uint16_t dma_word; - uint8_t dma_byte; - uint8_t incdec_size; - - if (LOG_DMA>1) - logerror("Control=%04X, src=%05X, dest=%05X, count=%04X\n",dma->control,dma->source,dma->dest,dma->count); - - if (!(dma->control & ST_STOP)) - { - if(LOG_DMA) - logerror("%05X:ERROR! - drq%d with dma channel stopped\n", pc(), which); - return; - } - - address_space *dest_space = (dma->control & DEST_MIO) ? m_program : m_io; - address_space *src_space = (dma->control & SRC_MIO) ? m_program : m_io; - - // Do the transfer, 80188 is incapable of word transfers - if ((dma->control & BYTE_WORD) && (m_program->data_width() == 16)) - { - dma_word = src_space->read_word_unaligned(dma->source); - dest_space->write_word_unaligned(dma->dest, dma_word); - incdec_size = 2; - } - else - { - dma_byte = src_space->read_byte(dma->source); - dest_space->write_byte(dma->dest, dma_byte); - incdec_size = 1; - } - - // Increment or Decrement destination and source pointers as needed - switch (dma->control & DEST_INCDEC_MASK) - { - case DEST_DECREMENT: - dma->dest -= incdec_size; - break; - case DEST_INCREMENT: - dma->dest += incdec_size; - break; - } - - switch (dma->control & SRC_INCDEC_MASK) - { - case SRC_DECREMENT: - dma->source -= incdec_size; - break; - case SRC_INCREMENT: - dma->source += incdec_size; - break; - } - - // decrement count - dma->count -= 1; - - // Terminate if count is zero, and terminate flag set - if (((dma->control & TERMINATE_ON_ZERO) || !(dma->control & SYNC_MASK)) && (dma->count == 0)) - { - dma->control &= ~ST_STOP; - if (LOG_DMA) logerror("DMA terminated\n"); - } - - // Interrupt if count is zero, and interrupt flag set - if ((dma->control & INTERRUPT_ON_ZERO) && (dma->count == 0)) - { - if (LOG_DMA>1) logerror("DMA%d - requesting interrupt: count = %04X, source = %04X\n", which, dma->count, dma->source); - m_intr.request |= 0x04 << which; - update_interrupt_state(); - } -} - -READ16_MEMBER(i80186_cpu_device::internal_port_r) -{ - int temp, which; - - switch (offset) - { - case 0x11: - if (LOG_PORTS) logerror("%05X:ERROR - read from 80186 EOI\n", pc()); - break; - - case 0x12: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt poll\n", pc()); - if (m_intr.poll_status & 0x8000) - int_callback(*this, 0); - return m_intr.poll_status; - - case 0x13: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt poll status\n", pc()); - return m_intr.poll_status; - - case 0x14: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt mask\n", pc()); - temp = (m_intr.timer >> 3) & 0x01; - temp |= (m_intr.dma[0] >> 1) & 0x04; - temp |= (m_intr.dma[1] >> 0) & 0x08; - temp |= (m_intr.ext[0] << 1) & 0x10; - temp |= (m_intr.ext[1] << 2) & 0x20; - temp |= (m_intr.ext[2] << 3) & 0x40; - temp |= (m_intr.ext[3] << 4) & 0x80; - return temp; - - case 0x15: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt priority mask\n", pc()); - return m_intr.priority_mask; - - case 0x16: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt in-service\n", pc()); - return m_intr.in_service; - - case 0x17: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt request\n", pc()); - temp = m_intr.request & ~0x0001; - if (m_intr.status & 0x0007) - temp |= 1; - return temp; - - case 0x18: - if (LOG_PORTS) logerror("%05X:read 80186 interrupt status\n", pc()); - return m_intr.status; - - case 0x19: - if (LOG_PORTS) logerror("%05X:read 80186 timer interrupt control\n", pc()); - return m_intr.timer; - - case 0x1a: - if (LOG_PORTS) logerror("%05X:read 80186 DMA 0 interrupt control\n", pc()); - return m_intr.dma[0]; - - case 0x1b: - if (LOG_PORTS) logerror("%05X:read 80186 DMA 1 interrupt control\n", pc()); - return m_intr.dma[1]; - - case 0x1c: - if (LOG_PORTS) logerror("%05X:read 80186 INT 0 interrupt control\n", pc()); - return m_intr.ext[0]; - - case 0x1d: - if (LOG_PORTS) logerror("%05X:read 80186 INT 1 interrupt control\n", pc()); - return m_intr.ext[1]; - - case 0x1e: - if (LOG_PORTS) logerror("%05X:read 80186 INT 2 interrupt control\n", pc()); - return m_intr.ext[2]; - - case 0x1f: - if (LOG_PORTS) logerror("%05X:read 80186 INT 3 interrupt control\n", pc()); - return m_intr.ext[3]; - - case 0x28: - case 0x2c: - case 0x30: - if (LOG_PORTS) logerror("%05X:read 80186 Timer %d count\n", pc(), (offset - 0x28) / 4); - which = (offset - 0x28) / 4; - if (ACCESSING_BITS_0_7) - internal_timer_sync(which); - return m_timer[which].count; - - case 0x29: - case 0x2d: - case 0x31: - if (LOG_PORTS) logerror("%05X:read 80186 Timer %d max A\n", pc(), (offset - 0x29) / 4); - which = (offset - 0x29) / 4; - return m_timer[which].maxA; - - case 0x2a: - case 0x2e: - if (LOG_PORTS) logerror("%05X:read 80186 Timer %d max B\n", pc(), (offset - 0x2a) / 4); - which = (offset - 0x2a) / 4; - return m_timer[which].maxB; - - case 0x2b: - case 0x2f: - case 0x33: - if (LOG_PORTS) logerror("%05X:read 80186 Timer %d control\n", pc(), (offset - 0x2b) / 4); - which = (offset - 0x2b) / 4; - return m_timer[which].control; - - case 0x50: - if (LOG_PORTS) logerror("%05X:read 80186 upper chip select\n", pc()); - return m_mem.upper; - - case 0x51: - if (LOG_PORTS) logerror("%05X:read 80186 lower chip select\n", pc()); - return m_mem.lower; - - case 0x52: - if (LOG_PORTS) logerror("%05X:read 80186 peripheral chip select\n", pc()); - return m_mem.peripheral; - - case 0x53: - if (LOG_PORTS) logerror("%05X:read 80186 middle chip select\n", pc()); - return m_mem.middle; - - case 0x54: - if (LOG_PORTS) logerror("%05X:read 80186 middle P chip select\n", pc()); - return m_mem.middle_size; - - case 0x60: - case 0x68: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower source address\n", pc(), (offset - 0x60) / 8); - which = (offset - 0x60) / 8; - return m_dma[which].source; - - case 0x61: - case 0x69: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper source address\n", pc(), (offset - 0x61) / 8); - which = (offset - 0x61) / 8; - return m_dma[which].source >> 16; - - case 0x62: - case 0x6a: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d lower dest address\n", pc(), (offset - 0x62) / 8); - which = (offset - 0x62) / 8; - return m_dma[which].dest; - - case 0x63: - case 0x6b: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d upper dest address\n", pc(), (offset - 0x63) / 8); - which = (offset - 0x63) / 8; - return m_dma[which].dest >> 16; - - case 0x64: - case 0x6c: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d transfer count\n", pc(), (offset - 0x64) / 8); - which = (offset - 0x64) / 8; - return m_dma[which].count; - - case 0x65: - case 0x6d: - if (LOG_PORTS) logerror("%05X:read 80186 DMA%d control\n", pc(), (offset - 0x65) / 8); - which = (offset - 0x65) / 8; - return m_dma[which].control; - - case 0x7f: - return m_reloc; - - default: - if (LOG_PORTS) logerror("%05X:read 80186 port %02X\n", pc(), offset); - break; - } - - return 0x0000; -} - -/************************************* - * - * 80186 internal I/O writes - * - *************************************/ - -WRITE16_MEMBER(i80186_cpu_device::internal_port_w) -{ - int which; - - switch (offset) - { - case 0x11: - if (LOG_PORTS) logerror("%05X:80186 EOI = %04X\n", pc(), data); - handle_eoi(0x8000); - update_interrupt_state(); - break; - - case 0x12: - if (LOG_PORTS) logerror("%05X:ERROR - write to 80186 interrupt poll = %04X\n", pc(), data); - break; - - case 0x13: - if (LOG_PORTS) logerror("%05X:ERROR - write to 80186 interrupt poll status = %04X\n", pc(), data); - break; - - case 0x14: - if (LOG_PORTS) logerror("%05X:80186 interrupt mask = %04X\n", pc(), data); - m_intr.timer = (m_intr.timer & ~0x08) | ((data << 3) & 0x08); - m_intr.dma[0] = (m_intr.dma[0] & ~0x08) | ((data << 1) & 0x08); - m_intr.dma[1] = (m_intr.dma[1] & ~0x08) | ((data << 0) & 0x08); - m_intr.ext[0] = (m_intr.ext[0] & ~0x08) | ((data >> 1) & 0x08); - m_intr.ext[1] = (m_intr.ext[1] & ~0x08) | ((data >> 2) & 0x08); - m_intr.ext[2] = (m_intr.ext[2] & ~0x08) | ((data >> 3) & 0x08); - m_intr.ext[3] = (m_intr.ext[3] & ~0x08) | ((data >> 4) & 0x08); - update_interrupt_state(); - break; - - case 0x15: - if (LOG_PORTS) logerror("%05X:80186 interrupt priority mask = %04X\n", pc(), data); - m_intr.priority_mask = data & 0x0007; - update_interrupt_state(); - break; - - case 0x16: - if (LOG_PORTS) logerror("%05X:80186 interrupt in-service = %04X\n", pc(), data); - m_intr.in_service = data & 0x00ff; - update_interrupt_state(); - break; - - case 0x17: - if (LOG_PORTS) logerror("%05X:80186 interrupt request = %04X\n", pc(), data); - m_intr.request = (m_intr.request & ~0x000c) | (data & 0x000c); - update_interrupt_state(); - break; - - case 0x18: - if (LOG_PORTS) logerror("%05X:WARNING - wrote to 80186 interrupt status = %04X\n", pc(), data); - m_intr.status = (m_intr.status & ~0x8007) | (data & 0x8007); - update_interrupt_state(); - break; - - case 0x19: - if (LOG_PORTS) logerror("%05X:80186 timer interrupt contol = %04X\n", pc(), data); - m_intr.timer = data & 0x000f; - update_interrupt_state(); - break; - - case 0x1a: - if (LOG_PORTS) logerror("%05X:80186 DMA 0 interrupt control = %04X\n", pc(), data); - m_intr.dma[0] = data & 0x000f; - update_interrupt_state(); - break; - - case 0x1b: - if (LOG_PORTS) logerror("%05X:80186 DMA 1 interrupt control = %04X\n", pc(), data); - m_intr.dma[1] = data & 0x000f; - update_interrupt_state(); - break; - - case 0x1c: - if (LOG_PORTS) logerror("%05X:80186 INT 0 interrupt control = %04X\n", pc(), data); - m_intr.ext[0] = data & 0x007f; - update_interrupt_state(); - break; - - case 0x1d: - if (LOG_PORTS) logerror("%05X:80186 INT 1 interrupt control = %04X\n", pc(), data); - m_intr.ext[1] = data & 0x007f; - update_interrupt_state(); - break; - - case 0x1e: - if (LOG_PORTS) logerror("%05X:80186 INT 2 interrupt control = %04X\n", pc(), data); - m_intr.ext[2] = data & 0x001f; - update_interrupt_state(); - break; - - case 0x1f: - if (LOG_PORTS) logerror("%05X:80186 INT 3 interrupt control = %04X\n", pc(), data); - m_intr.ext[3] = data & 0x001f; - update_interrupt_state(); - break; - - case 0x28: - case 0x2c: - case 0x30: - if (LOG_PORTS) logerror("%05X:80186 Timer %d count = %04X\n", pc(), (offset - 0x28) / 4, data); - which = (offset - 0x28) / 4; - internal_timer_update(which, data, -1, -1, -1); - break; - - case 0x29: - case 0x2d: - case 0x31: - if (LOG_PORTS) logerror("%05X:80186 Timer %d max A = %04X\n", pc(), (offset - 0x29) / 4, data); - which = (offset - 0x29) / 4; - internal_timer_update(which, -1, data, -1, -1); - break; - - case 0x2a: - case 0x2e: - if (LOG_PORTS) logerror("%05X:80186 Timer %d max B = %04X\n", pc(), (offset - 0x2a) / 4, data); - which = (offset - 0x2a) / 4; - internal_timer_update(which, -1, -1, data, -1); - break; - - case 0x2b: - case 0x2f: - case 0x33: - if (LOG_PORTS) logerror("%05X:80186 Timer %d control = %04X\n", pc(), (offset - 0x2b) / 4, data); - which = (offset - 0x2b) / 4; - internal_timer_update(which, -1, -1, -1, data); - break; - - case 0x50: - if (LOG_PORTS) logerror("%05X:80186 upper chip select = %04X\n", pc(), data); - m_mem.upper = data | 0xc038; - m_out_chip_select_func(0, m_mem.upper, 0xffff); - break; - - case 0x51: - if (LOG_PORTS) logerror("%05X:80186 lower chip select = %04X\n", pc(), data); - m_mem.lower = (data & 0x3fff) | 0x0038; - m_out_chip_select_func(1, m_mem.lower, 0xffff); - break; - - case 0x52: - if (LOG_PORTS) logerror("%05X:80186 peripheral chip select = %04X\n", pc(), data); - m_mem.peripheral = data | 0x0038; - m_out_chip_select_func(2, m_mem.peripheral, 0xffff); - break; - - case 0x53: - if (LOG_PORTS) logerror("%05X:80186 middle chip select = %04X\n", pc(), data); - m_mem.middle = data | 0x01f8; - m_out_chip_select_func(3, m_mem.middle, 0xffff); - break; - - case 0x54: - if (LOG_PORTS) logerror("%05X:80186 middle P chip select = %04X\n", pc(), data); - m_mem.middle_size = data | 0x8038; - m_out_chip_select_func(4, m_mem.middle_size, 0xffff); - break; - - case 0x60: - case 0x68: - if (LOG_PORTS) logerror("%05X:80186 DMA%d lower source address = %04X\n", pc(), (offset - 0x60) / 8, data); - which = (offset - 0x60) / 8; - m_dma[which].source = (m_dma[which].source & ~0x0ffff) | (data & 0x0ffff); - break; - - case 0x61: - case 0x69: - if (LOG_PORTS) logerror("%05X:80186 DMA%d upper source address = %04X\n", pc(), (offset - 0x61) / 8, data); - which = (offset - 0x61) / 8; - m_dma[which].source = (m_dma[which].source & ~0xf0000) | ((data << 16) & 0xf0000); - break; - - case 0x62: - case 0x6a: - if (LOG_PORTS) logerror("%05X:80186 DMA%d lower dest address = %04X\n", pc(), (offset - 0x62) / 8, data); - which = (offset - 0x62) / 8; - m_dma[which].dest = (m_dma[which].dest & ~0x0ffff) | (data & 0x0ffff); - break; - - case 0x63: - case 0x6b: - if (LOG_PORTS) logerror("%05X:80186 DMA%d upper dest address = %04X\n", pc(), (offset - 0x63) / 8, data); - which = (offset - 0x63) / 8; - m_dma[which].dest = (m_dma[which].dest & ~0xf0000) | ((data << 16) & 0xf0000); - break; - - case 0x64: - case 0x6c: - if (LOG_PORTS) logerror("%05X:80186 DMA%d transfer count = %04X\n", pc(), (offset - 0x64) / 8, data); - which = (offset - 0x64) / 8; - m_dma[which].count = data; - break; - - case 0x65: - case 0x6d: - if (LOG_PORTS) logerror("%05X:80186 DMA%d control = %04X\n", pc(), (offset - 0x65) / 8, data); - which = (offset - 0x65) / 8; - update_dma_control(which, data); - if((m_dma[which].control & (SYNC_MASK | ST_STOP | TIMER_DRQ)) == ST_STOP) - { - // TODO: don't do this - while(m_dma[which].control & ST_STOP) - drq_callback(which); - } - break; - - case 0x7f: - if (LOG_PORTS) logerror("%05X:80186 relocation register = %04X\n", pc(), data); - if ((data & 0x1fff) != (m_reloc & 0x1fff)) - { - uint32_t newmap = (data & 0xfff) << 8; - uint32_t oldmap = (m_reloc & 0xfff) << 8; - if (m_reloc & 0x1000) - m_program->unmap_readwrite(oldmap, oldmap + 0xff); - if (data & 0x1000) // TODO: make work with 80188 if needed - m_program->install_readwrite_handler(newmap, newmap + 0xff, read16_delegate(FUNC(i80186_cpu_device::internal_port_r), this), write16_delegate(FUNC(i80186_cpu_device::internal_port_w), this)); - } - m_reloc = data; - - break; - - default: - if (LOG_PORTS) logerror("%05X:80186 port %02X = %04X\n", pc(), offset, data); - break; - } -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i186.h b/source/src/vm/libcpu_newdev/libcpu_i286/i186.h deleted file mode 100644 index 74a659c64..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i186.h +++ /dev/null @@ -1,151 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -#ifndef I186_H__ -#define I186_H__ - -#include "i86.h" - -extern const device_type I80186; -extern const device_type I80188; - -class i80186_cpu_device : public i8086_common_cpu_device -{ -public: - // construction/destruction - i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - i80186_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source, int data_bus_size); - - template static devcb_base &static_set_read_slave_ack_callback(device_t &device, _Object object) { return downcast(device).m_read_slave_ack_func.set_callback(object); } - template static devcb_base &static_set_chip_select_callback(device_t &device, _Object object) { return downcast(device).m_out_chip_select_func.set_callback(object); } - template static devcb_base &static_set_tmrout0_handler(device_t &device, _Object object) { return downcast(device).m_out_tmrout0_func.set_callback(object); } - template static devcb_base &static_set_tmrout1_handler(device_t &device, _Object object) { return downcast(device).m_out_tmrout1_func.set_callback(object); } - - IRQ_CALLBACK_MEMBER(int_callback); - DECLARE_WRITE_LINE_MEMBER(drq0_w) { if(state) drq_callback(0); m_dma[0].drq_state = state; } - DECLARE_WRITE_LINE_MEMBER(drq1_w) { if(state) drq_callback(1); m_dma[1].drq_state = state; } - DECLARE_WRITE_LINE_MEMBER(tmrin0_w) { if(state && (m_timer[0].control & 0x8004) == 0x8004) { inc_timer(0); } } - DECLARE_WRITE_LINE_MEMBER(tmrin1_w) { if(state && (m_timer[1].control & 0x8004) == 0x8004) { inc_timer(1); } } - DECLARE_WRITE_LINE_MEMBER(int0_w) { external_int(0, state); } - DECLARE_WRITE_LINE_MEMBER(int1_w) { external_int(1, state); } - DECLARE_WRITE_LINE_MEMBER(int2_w) { external_int(2, state); } - DECLARE_WRITE_LINE_MEMBER(int3_w) { external_int(3, state); } - - // device_memory_interface overrides - virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override; - -protected: - // device_execute_interface overrides - virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const override { return (clocks / 2); } - virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const override { return (cycles * 2); } - virtual void execute_run() override; - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - virtual uint32_t execute_input_lines() const override { return 1; } - virtual uint8_t fetch_op() override; - virtual uint8_t fetch() override; - uint32_t pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; } - - virtual uint8_t read_port_byte(uint16_t port) override; - virtual uint16_t read_port_word(uint16_t port) override; - virtual void write_port_byte(uint16_t port, uint8_t data) override; - virtual void write_port_word(uint16_t port, uint16_t data) override; - - static const uint8_t m_i80186_timing[200]; - -private: - void update_interrupt_state(); - void handle_eoi(int data); - void external_int(uint16_t intno, int state); - void internal_timer_sync(int which); - void internal_timer_update(int which, int new_count, int new_maxA, int new_maxB, int new_control); - void update_dma_control(int which, int new_control); - void drq_callback(int which); - void inc_timer(int which); - DECLARE_READ16_MEMBER(internal_port_r); - DECLARE_WRITE16_MEMBER(internal_port_w); - - struct mem_state - { - uint16_t lower; - uint16_t upper; - uint16_t middle; - uint16_t middle_size; - uint16_t peripheral; - }; - - struct timer_state - { - uint16_t control; - uint16_t maxA; - uint16_t maxB; - bool active_count; - uint16_t count; - emu_timer *int_timer; - }; - - struct dma_state - { - bool drq_state; - uint32_t source; - uint32_t dest; - uint16_t count; - uint16_t control; - }; - - struct intr_state - { - uint8_t pending; - uint16_t ack_mask; - uint16_t priority_mask; - uint16_t in_service; - uint16_t request; - uint16_t status; - uint16_t poll_status; - uint16_t timer; - uint16_t dma[2]; - uint16_t ext[4]; - uint8_t ext_state; - }; - - timer_state m_timer[3]; - dma_state m_dma[2]; - intr_state m_intr; - mem_state m_mem; - - static const device_timer_id TIMER_INT0 = 0; - static const device_timer_id TIMER_INT1 = 1; - static const device_timer_id TIMER_INT2 = 2; - - uint16_t m_reloc; - - address_space_config m_program_config; - address_space_config m_opcodes_config; - address_space_config m_io_config; - - devcb_read8 m_read_slave_ack_func; - devcb_write16 m_out_chip_select_func; - devcb_write_line m_out_tmrout0_func; - devcb_write_line m_out_tmrout1_func; -}; - -class i80188_cpu_device : public i80186_cpu_device -{ -public: - // construction/destruction - i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - -#define MCFG_80186_IRQ_SLAVE_ACK(_devcb) \ - devcb = &i80186_cpu_device::static_set_read_slave_ack_callback(*device, DEVCB_##_devcb); - -#define MCFG_80186_CHIP_SELECT_CB(_devcb) \ - devcb = &i80186_cpu_device::static_set_chip_select_callback(*device, DEVCB_##_devcb); - -#define MCFG_80186_TMROUT0_HANDLER(_devcb) \ - devcb = &i80186_cpu_device::static_set_tmrout0_handler(*device, DEVCB_##_devcb); - -#define MCFG_80186_TMROUT1_HANDLER(_devcb) \ - devcb = &i80186_cpu_device::static_set_tmrout1_handler(*device, DEVCB_##_devcb); - -#endif diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i286.cpp b/source/src/vm/libcpu_newdev/libcpu_i286/i286.cpp deleted file mode 100644 index bfbc2a853..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i286.cpp +++ /dev/null @@ -1,2314 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -#include "../../device.h" -#include "./i286.h" -#include "../../debugger.h" -#include "i86inline.h" - - -#ifndef __BIG_ENDIAN__ -#define LSB_FIRST -#endif - -#ifndef INLINE -#define INLINE inline -#endif -/*****************************************************************************/ -/* 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)) - -/* emumem.h */ -// macros for accessing bytes and words within larger chunks - -// read/write a byte to a 16-bit space -#define BYTE_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(1,0)) -#define BYTE_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,1)) - -// read/write a byte to a 32-bit space -#define BYTE4_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(3,0)) -#define BYTE4_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,3)) - -// read/write a word to a 32-bit space -#define WORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) -#define WORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,2)) - -// read/write a byte to a 64-bit space -#define BYTE8_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(7,0)) -#define BYTE8_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,7)) - -// read/write a word to a 64-bit space -#define WORD2_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6,0)) -#define WORD2_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,6)) - -// read/write a dword to a 64-bit space -#define DWORD_XOR_BE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(4,0)) -#define DWORD_XOR_LE(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,4)) - - -// helpers for checking address alignment -#define WORD_ALIGNED(a) (((a) & 1) == 0) -#define DWORD_ALIGNED(a) (((a) & 3) == 0) -#define QWORD_ALIGNED(a) (((a) & 7) == 0) - -// 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) -}; - -/* - * Descriptor format - * Data Segment - * 48. . . . . . .40. . . . . . .32. . . . . . .24. . . . . . .16. . . . . . . 8. . . . . . . 0 - * P|DPL|1|0|E|W|A| BASE 23-16 | BASE 15-0 | LIMIT | - * Code Segment - * 48. . . . . . .40. . . . . . .32. . . . . . .24. . . . . . .16. . . . . . . 8. . . . . . . 0 - * P|DPL|1|1|C|R|A| BASE 23-16 | BASE 15-0 | LIMIT | - * System - * 48. . . . . . .40. . . . . . .32. . . . . . .24. . . . . . .16. . . . . . . 8. . . . . . . 0 - * P|DPL|0| TYPE | BASE 23-16 | BASE 15-0 | LIMIT | - * - * P == Present - * A == Accessed - * E == Expand Down - * W == Read/Write - * C == Conforming - * R == Readable - * DPL == Descriptor Privilege Level - * - * Bits 48-64 are ignored but reserved for the 80386 - */ - -#define LIMIT(desc) (desc[0]&0xffff) -#define BASE(desc) ((desc[1]&0xffff)|((desc[2]&0xff)<<16)) -#define RIGHTS(desc) ((desc[2]>>8)&0xff) - -#define ACCESS(r) (r&1) -#define SET_ACC(desc) (desc[2]|=0x100) -#define RW(r) ((r>>1)&1) -#define READ(r) ((r>>1)&1) -#define CONF(r) ((r>>2)&1) -#define EXPDOWN(r) ((r>>2)&1) -#define CODE(r) ((r>>3)&1) -#define SEGDESC(r) ((r>>4)&1) -#define DPL(r) ((r>>5)&3) -#define PRES(r) ((r>>7)&1) -#define GATE(r) (r&31) -#define GATESEL(desc) (desc[1]) -#define GATEOFF(desc) (desc[0]) -#define GATECNT(desc) (desc[2]&31) - -#define RPL(s) (s&3) -#define IDX(s) (s&(~7)) -#define IDXTBL(s) (s&(~3)) -#define TBL(s) (s&4) - -#define TSSDESCIDLE 1 -#define LDTDESC 2 -#define TSSDESCBUSY 3 -#define CALLGATE 4 -#define TASKGATE 5 -#define INTGATE 6 -#define TRAPGATE 7 - -#define TSS_BACK 0 -#define TSS_SP0 1 -#define TSS_SS0 2 -#define TSS_SP1 3 -#define TSS_SS1 4 -#define TSS_SP2 5 -#define TSS_SS2 6 -#define TSS_IP 7 -#define TSS_FLAG 8 -#define TSS_AX 9 -#define TSS_CX 10 -#define TSS_DX 11 -#define TSS_BX 12 -#define TSS_SP 13 -#define TSS_BP 14 -#define TSS_SI 15 -#define TSS_DI 16 -#define TSS_ES 17 -#define TSS_CS 18 -#define TSS_SS 19 -#define TSS_DS 20 -#define TSS_LDT 21 - -#define PMAX(a,b) ((a 0x0fffff) ? 0xffffffff : 0x00000000); -} - -void i80286_cpu_device::device_start() -{ - i8086_common_cpu_device::device_start(); - // ToDo - state_add( I286_ES, "ES", m_sregs[ES] ).formatstr("%04X"); - state_add( I286_ES_BASE, "ESBASE", m_base[ES]).formatstr("%06X"); - state_add( I286_ES_LIMIT, "ESLIMIT", m_limit[ES]).formatstr("%04X"); - state_add( I286_ES_FLAGS, "ESFLAGS", m_rights[ES]).formatstr("%02X"); - state_add( I286_CS, "CS", m_sregs[CS] ).callimport().formatstr("%04X"); - state_add( I286_CS_BASE, "CSBASE", m_base[CS]).callimport().formatstr("%06X"); - state_add( I286_CS_LIMIT, "CSLIMIT", m_limit[CS]).formatstr("%04X"); - state_add( I286_CS_FLAGS, "CSFLAGS", m_rights[CS]).formatstr("%02X"); - state_add( I286_SS, "SS", m_sregs[SS] ).formatstr("%04X"); - state_add( I286_SS_BASE, "SSBASE", m_base[SS]).formatstr("%06X"); - state_add( I286_SS_LIMIT, "SSLIMIT", m_limit[SS]).formatstr("%04X"); - state_add( I286_SS_FLAGS, "SSFLAGS", m_rights[SS]).formatstr("%02X"); - state_add( I286_DS, "DS", m_sregs[DS] ).formatstr("%04X"); - state_add( I286_DS_BASE, "DSBASE", m_base[DS]).formatstr("%06X"); - state_add( I286_DS_LIMIT, "DSLIMIT", m_limit[DS]).formatstr("%04X"); - state_add( I286_DS_FLAGS, "DSFLAGS", m_rights[DS]).formatstr("%02X"); - state_add( I286_GDTR_BASE, "GDTRBASE", m_gdtr.base).formatstr("%06X"); - state_add( I286_GDTR_LIMIT, "GDTRLIMIT", m_gdtr.limit).formatstr("%04X"); - state_add( I286_IDTR_BASE, "IDTRBASE", m_idtr.base).formatstr("%06X"); - state_add( I286_IDTR_LIMIT, "IDTRLIMIT", m_idtr.limit).formatstr("%04X"); - state_add( I286_LDTR, "LDTR", m_ldtr.sel ).formatstr("%04X"); - state_add( I286_LDTR_BASE, "LDTRBASE", m_ldtr.base).formatstr("%06X"); - state_add( I286_LDTR_LIMIT, "LDTRLIMIT", m_ldtr.limit).formatstr("%04X"); - state_add( I286_LDTR_FLAGS, "LDTRFLAGS", m_ldtr.rights).formatstr("%02X"); - state_add( I286_TR, "TR", m_tr.sel ).formatstr("%04X"); - state_add( I286_TR_BASE, "TRBASE", m_tr.base).formatstr("%06X"); - state_add( I286_TR_LIMIT, "TRLIMIT", m_tr.limit).formatstr("%04X"); - state_add( I286_TR_FLAGS, "TRFLAGS", m_tr.rights).formatstr("%02X"); - state_add( I286_MSW, "MSW", m_msw ).formatstr("%04X"); - state_add( I286_VECTOR, "V", m_int_vector).formatstr("%02X"); - - state_add( I286_PC, "PC", m_pc).callimport().formatstr("%06X"); - state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%06X").noshow(); - state_add( I8086_HALT, "HALT", m_halt ).mask(1); - - //m_out_shutdown_func.resolve_safe(); - write_signals(&out_shutdown, 0); -} - -//------------------------------------------------- -// state_import - import state into the device, -// after it has been set -//------------------------------------------------- - -void i80286_cpu_device::state_import(const device_state_entry &entry) -{ - switch (entry.index()) - { - case I286_IP: - case I286_CS_BASE: - m_pc = m_base[CS] + m_ip; - break; - - case I286_CS: - // TODO: should this call data_descriptor to update the current segment? - break; - - case STATE_GENPC: - case STATE_GENPCBASE: - if (m_pc - m_base[CS] > m_limit[CS]) - { - // TODO: should this call data_descriptor instead of ignoring jumps outside the current segment? - if (PM) - { - m_pc = m_base[CS] + m_ip; - } - else - { - m_sregs[CS] = m_pc >> 4; - m_base[CS] = m_sregs[CS] << 4; - } - } - m_ip = m_pc - m_base[CS]; - break; - } -} - - -//------------------------------------------------- -// state_string_export - export state as a string -// for the debugger -//------------------------------------------------- - -void i80286_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const -{ - switch (entry.index()) - { - case STATE_GENFLAGS: - { - uint16_t flags = CompressFlags(); - str = string_format("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", - flags & 0x8000 ? '0':'.', - flags & 0x4000 ? 'N':'.', - flags & 0x2000 ? 'I':'.', - flags & 0x1000 ? 'I':'.', - flags & 0x0800 ? 'O':'.', - flags & 0x0400 ? 'D':'.', - flags & 0x0200 ? 'I':'.', - flags & 0x0100 ? 'T':'.', - flags & 0x0080 ? 'S':'.', - flags & 0x0040 ? 'Z':'.', - flags & 0x0020 ? '0':'.', - flags & 0x0010 ? 'A':'.', - flags & 0x0008 ? '0':'.', - flags & 0x0004 ? 'P':'.', - flags & 0x0002 ? '1':'.', - flags & 0x0001 ? 'C':'.'); - } - break; - } -} - -bool i80286_cpu_device::memory_translate(address_spacenum spacenum, int intention, offs_t &address) -{ - if(spacenum == AS_PROGRAM) - address &= m_amask; - - return true; -} - -void i80286_cpu_device::set_irq_line(int irqline, int state) -{ - if (state != CLEAR_LINE && cpustate->halted) - { - cpustate->halted = 0; - } - try - { - if (irqline == INPUT_LINE_NMI) - { - if (state != CLEAR_LINE) { - m_pending_irq |= NMI_IRQ; - } else { - //m_pending_irq &= ~NMI_IRQ; - } - if (m_nmi_state == (uint32_t)state) { - return; - } - m_nmi_state = (uint32_t)state; - - /* on a rising edge, signal the NMI */ - if (state != CLEAR_LINE) { - interrupt(I8086_NMI_INT_VECTOR, 2, -1); - m_nmi_state = CLEAR_LINE; - } - } else { - if(state == CLEAR_LINE) { - m_pending_irq &= ~INT_IRQ; - } else { - m_pending_irq |= INT_IRQ; - } - m_irq_state = state; - /* if the IF is set, signal an interrupt */ - if (state != CLEAR_LINE && m_IF) { - if(m_pic != NULL) { - interrupt(m_pic->get_intr_ack(), 2, -1); - } - m_irq_state = CLEAR_LINE; - } - } - } - catch (UINT32 e) - { - trap(e); - } -} - -void i80286_cpu_device::write_signal(int id, uint32_t data, uint32_t mask) -{ - bool b_state = (data & mask); - uint32_t state = b_state ? HOLD_LINE : CLEARLINE; - if(id == SIG_CPU_NMI) { - set_irq_line(INPUT_LINE_NMI, state); - } else if(id == SIG_CPU_IRQ) { - set_irq_line(INPUT_LINE_IRQ, state); - } else if(id == SIG_I86_A20) { - m_amask = b_state ? 0x00ffffff : 0x000fffff; // i80286_set_a20_line() - write_signals(&out_a20, (b_state) ? 0xffffffff : 0x00000000); - } else if(id == SIG_CPU_BUSREQ) { - m_busreq = (data & mask); - } else if(id == SIG_I86_TEST) { - m_test = (data & mask); - } -} -// when a cpu reset happens on a AT the bios checks for 9 in byte 0xf -// of the nvram. if yes, after init, it sets the stack pointer to the value in 0040:0067 -// in the bios data segment then pops es and ds off that stack, does popa then a far ret. - -void i80286_cpu_device::trap(uint32_t error) -{ - int error_code = error & 0xffff; - uint16_t number = error >> 16; - if(error_code == 0xffff) { - error_code = -1; - } - m_ip = m_prev_ip; - try - { - switch(number) - { - case FAULT_DE: - case FAULT_TS: - case FAULT_NP: - case FAULT_SS: - case FAULT_GP: - m_trap_level++; - if(m_trap_level == 2) - throw TRAP(FAULT_DF,0); - if(m_trap_level == 3) - break; - interrupt_descriptor(number,1,error_code); - break; - case FAULT_DF: - interrupt_descriptor(number,1,0); - break; - default: - interrupt_descriptor(number,1,-1); - } - } - catch(uint32_t e) - { - trap(e); - } - if(m_trap_level == 3) - { - m_shutdown = true; - //m_out_shutdown_func(true); - write_signals(&out_shutdown, 0xffffffff); - } - m_trap_level = 0; -} - -uint32_t i80286_cpu_device::selector_address(uint16_t sel) -{ - uint32_t base; - uint16_t limit; - if(TBL(sel)) - { - base = m_ldtr.base; - limit = m_ldtr.limit; - } - else - { - base = m_gdtr.base; - limit = m_gdtr.limit; - } - return ((IDX(sel) >= limit) || !IDXTBL(sel) ? -1 : base + IDX(sel)); -} - -int i80286_cpu_device::verify(uint16_t selector, int operation, uint8_t rights, bool valid) -{ - if(!IDXTBL(selector) && !valid) - return FAULT_GP; - if(!SEGDESC(rights)) - return FAULT_GP; - - switch (operation) - { - case I8086_READ: - if(CODE(rights) && !READ(rights)) - return FAULT_GP; - break; - case I8086_WRITE: - if(CODE(rights) || !RW(rights)) - return FAULT_GP; - break; - case I8086_FETCH: - if(!CODE(rights)) - return FAULT_GP; - break; - } - return 0; -} - -void i80286_cpu_device::pop_seg(int reg) -{ - uint16_t sel; - if(PM) - check_permission(SS, m_regs.w[SP], 2, I8086_READ); - sel = read_word(m_base[SS] + m_regs.w[SP]); - data_descriptor(reg, sel); - m_regs.w[SP] += 2; -} - -void i80286_cpu_device::data_descriptor(int reg, uint16_t selector, int cpl, uint32_t trap, uint16_t offset, int size) -{ - if(PM) - { - uint16_t desc[3]; - uint8_t r; - uint32_t addr; - if((reg != SS) && !IDXTBL(selector)) - { - m_sregs[reg] = 0; - m_limit[reg] = 0; - m_base[reg] = 0; - m_rights[reg] = 0; - m_valid[reg] = 0; - return; - } - - if((addr = selector_address(selector)) == -1) - throw trap; - - desc[0] = read_word(addr); - desc[1] = read_word(addr + 2); - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - - if(!SEGDESC(r)) - throw trap; - - if(reg == SS) - { - if(!IDXTBL(selector)) - throw trap; - if(DPL(r) != cpl) - throw trap; - if(RPL(selector) != cpl) - throw trap; - if(!RW(r) || CODE(r)) - throw trap; - if(!PRES(r)) - throw TRAP(FAULT_SS, (IDXTBL(selector) + (trap & 1))); - } - else - { - if((DPL(r) < PMAX(cpl, RPL(selector))) && (!CODE(r) || (CODE(r) && !CONF(r)))) - throw trap; - if(CODE(r) && !READ(r)) - throw trap; - if(!PRES(r)) - throw TRAP(FAULT_NP, (IDXTBL(selector) + (trap & 1))); - } - - if(offset + size) - { - if((CODE(r) || !EXPDOWN(r)) && ((offset + size - 1) > LIMIT(desc))) - throw (reg==SS) ? TRAP(FAULT_SS, (trap & 1)) : trap; - - if(!CODE(r) && EXPDOWN(r) && ((offset <= LIMIT(desc)) || ((offset + size - 1) > 0xffff))) - throw (reg==SS) ? TRAP(FAULT_SS, (trap & 1)) : trap; - } - - SET_ACC(desc); - write_word(addr + 4, desc[2]); - m_sregs[reg] = selector; - m_limit[reg] = LIMIT(desc); - m_base[reg] = BASE(desc); - m_rights[reg] = RIGHTS(desc); - } - else - { - m_sregs[reg] = selector; - m_base[reg] = selector << 4; - } - m_valid[reg] = 1; -} - -void i80286_cpu_device::data_descriptor(int reg, uint16_t selector) -{ - data_descriptor(reg, selector, CPL, TRAP(FAULT_GP,IDXTBL(selector))); -} - -void i80286_cpu_device::switch_task(uint16_t ntask, int type) -{ - uint16_t ndesc[3], desc[3], ntss[22], otss[22], flags; - uint8_t r, lr; - uint32_t naddr, oaddr, ldtaddr; - int i; - logerror("i286: %06x This program uses TSSs, how rare. Please report this to the developers.\n", pc()); - - if(TBL(ntask)) - throw TRAP(FAULT_TS, IDXTBL(ntask)); - - if((naddr = selector_address(ntask)) == -1) - throw TRAP(FAULT_TS, IDXTBL(ntask)); - - oaddr = selector_address(m_tr.sel); - ndesc[0] = read_word(naddr); - ndesc[1] = read_word(naddr + 2); - ndesc[2] = read_word(naddr + 4); - desc[2] = read_word(oaddr + 4); - r = RIGHTS(ndesc); - - if(SEGDESC(r) || ((GATE(r) & ~2) != TSSDESCIDLE)) - throw TRAP(FAULT_GP, IDXTBL(ntask)); - - if(!PRES(r)) - throw TRAP(FAULT_NP, IDXTBL(ntask)); - - if(LIMIT(ndesc) < 43) - throw TRAP(FAULT_TS, IDXTBL(ntask)); - - flags = CompressFlags(); - - if(type == NT_CALL) - write_word(BASE(ndesc) + TSS_BACK * 2, m_tr.sel); - - if(type == NT_IRET) - flags &= ~0x4000; - - otss[TSS_IP] = m_ip; - otss[TSS_FLAG] = flags; - otss[TSS_AX] = m_regs.w[AX]; - otss[TSS_CX] = m_regs.w[CX]; - otss[TSS_DX] = m_regs.w[DX]; - otss[TSS_BX] = m_regs.w[BX]; - otss[TSS_SP] = m_regs.w[SP]; - otss[TSS_BP] = m_regs.w[BP]; - otss[TSS_SI] = m_regs.w[SI]; - otss[TSS_DI] = m_regs.w[DI]; - otss[TSS_ES] = m_sregs[ES]; - otss[TSS_CS] = m_sregs[CS]; - otss[TSS_SS] = m_sregs[SS]; - otss[TSS_DS] = m_sregs[DS]; - - for (i = 14; i < 42; i += 2) - write_word(m_tr.base + i, otss[i / 2]); - - for (i = 0; i < 44; i += 2) - ntss[i / 2] = read_word(BASE(ndesc) + i); - - // jmp does both - if(type != NT_CALL) - { - desc[2] &= ~0x200; // mark idle - write_word(oaddr + 4, desc[2]); - } - - if(type != NT_IRET) - { - ndesc[2] |= 0x200; - write_word(naddr + 4, ndesc[2]); - } - - m_tr.sel = ntask; - m_tr.limit = LIMIT(ndesc); - m_tr.base = BASE(ndesc); - m_tr.rights = RIGHTS(ndesc); - - load_flags(ntss[TSS_FLAG], 0); - m_regs.w[AX] = ntss[TSS_AX]; - m_regs.w[CX] = ntss[TSS_CX]; - m_regs.w[DX] = ntss[TSS_DX]; - m_regs.w[BX] = ntss[TSS_BX]; - m_regs.w[SP] = ntss[TSS_SP]; - m_regs.w[BP] = ntss[TSS_BP]; - m_regs.w[SI] = ntss[TSS_SI]; - m_regs.w[DI] = ntss[TSS_DI]; - - if(TBL(ntss[TSS_LDT])) - throw TRAP(FAULT_TS, IDXTBL(ntss[TSS_LDT])); - - if(IDXTBL(ntss[TSS_LDT])) - { - if((ldtaddr = selector_address(ntss[TSS_LDT])) == -1) - throw TRAP(FAULT_TS, IDXTBL(ntss[TSS_LDT])); - - desc[0] = read_word(ldtaddr); - desc[1] = read_word(ldtaddr + 2); - desc[2] = read_word(ldtaddr + 4); - lr = RIGHTS(desc); - - if(SEGDESC(lr) || (GATE(lr) != LDTDESC)) - throw TRAP(FAULT_TS, IDXTBL(ntss[TSS_LDT])); - - if(!PRES(lr)) - throw TRAP(FAULT_TS, IDXTBL(ntss[TSS_LDT])); - - m_ldtr.sel = ntss[TSS_LDT]; - m_ldtr.limit = LIMIT(desc); - m_ldtr.base = BASE(desc); - m_ldtr.rights = RIGHTS(desc); - } - else - { - m_ldtr.sel = 0; - m_ldtr.limit = 0; - m_ldtr.base = 0; - m_ldtr.rights = 0; - } - - if(type == NT_CALL) - m_NT = 1; - - m_msw |= 8; - // Docs explicitly say SS is loaded first. Why? Because the DPL - // of the TSS is compared to the DPL of SS which is CPL - data_descriptor(SS, ntss[TSS_SS], RPL(ntss[TSS_CS]), TRAP(FAULT_TS, IDXTBL(ntss[TSS_SS]))); - - try - { - code_descriptor(ntss[TSS_CS], ntss[TSS_IP], 0); - } - catch (uint32_t e) - { - int error_code = e & 0xffff; - if(error_code == FAULT_GP) - e = TRAP(FAULT_TS, (e >> 16)); // #NP fault is correct - throw e; - } - - data_descriptor(ES, ntss[TSS_ES], CPL, TRAP(FAULT_TS, IDXTBL(ntss[TSS_ES]))); - data_descriptor(DS, ntss[TSS_DS], CPL, TRAP(FAULT_TS, IDXTBL(ntss[TSS_DS]))); -} - -void i80286_cpu_device::code_descriptor(uint16_t selector, uint16_t offset, int gate) -{ - if(PM) - { - uint16_t desc[3]; - uint8_t r; - uint32_t addr; - if((addr = selector_address(selector)) == -1) - throw TRAP(FAULT_GP, IDXTBL(selector)); - - desc[0] = read_word(addr); - desc[1] = read_word(addr + 2); - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - - if(SEGDESC(r)) - { - if(!CODE(r)) - throw TRAP(FAULT_GP, IDXTBL(selector)); - - if(CONF(r)) - { - if(DPL(r) > CPL) - throw TRAP(FAULT_GP, IDXTBL(selector)); - } - else - if((RPL(selector) > CPL) || (DPL(r) != CPL)) - throw TRAP(FAULT_GP, IDXTBL(selector)); - - if(!PRES(r)) - throw TRAP(FAULT_NP, IDXTBL(selector)); // this order is important - - if(offset > LIMIT(desc)) - throw TRAP(FAULT_GP, 0); - - SET_ACC(desc); - write_word(addr + 4, desc[2]); - m_sregs[CS] = IDXTBL(selector) | CPL; - m_limit[CS] = LIMIT(desc); - m_base[CS] = BASE(desc); - m_rights[CS] = RIGHTS(desc); - m_ip = offset; - } - else - { // systemdescriptor - uint16_t gatesel = GATESEL(desc); - - if(!gate) - throw TRAP(FAULT_GP, IDXTBL(selector)); // tss cs must be segment - if(DPL(r) < PMAX(CPL,RPL(selector))) - throw TRAP(FAULT_GP, IDXTBL(selector)); - if(!PRES(r)) - throw TRAP(FAULT_NP, IDXTBL(selector)); - - switch (GATE(r)) - { - case CALLGATE: - { - uint16_t gatedesc[3]; - if((addr = selector_address(gatesel)) == -1) - throw TRAP(FAULT_GP, IDXTBL(gatesel)); - - gatedesc[0] = read_word(addr); - gatedesc[1] = read_word(addr + 2); - gatedesc[2] = read_word(addr + 4); - r = RIGHTS(gatedesc); - - if(!CODE(r) || !SEGDESC(r)) - throw TRAP(FAULT_GP, IDXTBL(gatesel)); - if(DPL(r) > CPL) - throw TRAP(FAULT_GP, IDXTBL(gatesel)); - if(!PRES(r)) - throw TRAP(FAULT_NP, IDXTBL(gatesel)); - - if(GATEOFF(desc) > LIMIT(gatedesc)) - throw TRAP(FAULT_GP,0); - - if (!CONF(r) && (DPL(r) < CPL)) - { - // inner call - uint16_t tss_ss, tss_sp, oldss, oldsp; - uint32_t oldstk; - int i; - if(gate == NT_JMP) - throw TRAP(FAULT_GP, IDXTBL(gatesel)); // can't jmp to inner - - tss_ss = read_word(m_tr.base+TSS_SS0*2+(DPL(r)*4)); - tss_sp = read_word(m_tr.base+TSS_SP0*2+(DPL(r)*4)); - - oldss = m_sregs[SS]; - oldsp = m_regs.w[SP]; - oldstk = m_base[SS] + oldsp; - data_descriptor(SS, tss_ss, DPL(r), TRAP(FAULT_TS,IDXTBL(tss_ss)), tss_sp-8-(GATECNT(desc)*2), 8+(GATECNT(desc)*2)); - m_regs.w[SP] = tss_sp; - PUSH(oldss); - PUSH(oldsp); - for(i = GATECNT(desc)-1; i >= 0; i--) - PUSH(read_word(oldstk+(i*2))); - } - else - check_permission(SS, m_regs.w[SP]-4, 4, I8086_READ); - - SET_ACC(gatedesc); - write_word(addr+4, gatedesc[2]); - m_sregs[CS]=IDXTBL(gatesel) | DPL(r); - m_limit[CS]=LIMIT(gatedesc); - m_base[CS]=BASE(gatedesc); - m_rights[CS]=RIGHTS(gatedesc); - m_ip=GATEOFF(desc); - break; - } - - case TASKGATE: - selector = gatesel; - if((addr = selector_address(selector)) == -1) - throw TRAP(FAULT_GP, IDXTBL(selector)); - - desc[2] = read_word(addr+4); - r = RIGHTS(desc); - if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) - throw TRAP(FAULT_GP,IDXTBL(selector)); - - case TSSDESCIDLE: - switch_task(selector, gate); - load_flags(CompressFlags(), CPL); - break; - - default: - throw TRAP(FAULT_GP,IDXTBL(selector)); - } - } - } - else - { - m_ip = offset; - m_sregs[CS]=selector; - m_base[CS]=selector<<4; - m_rights[CS]=0x9b; - m_limit[CS]=0xffff; - } -} - -void i80286_cpu_device::interrupt_descriptor(int number, int hwint, int error) -{ - uint16_t desc[3], gatesel, flags = CompressFlags(); - uint8_t r; - hwint = hwint ? 1 : 0; - - if(number == -1) - { - number = standard_irq_callback(0); - - m_irq_state = CLEAR_LINE; - m_pending_irq &= ~INT_IRQ; - hwint = 1; - } - - if(!PM) - { - PUSH(flags & ~0xf000); - m_TF = m_IF = 0; - - uint16_t dest_off = read_word(number * 4 + 0); - uint16_t dest_seg = read_word(number * 4 + 2); - - PUSH(m_sregs[CS]); - PUSH(m_ip); - code_descriptor(dest_seg, dest_off, 0); - return; - } - - if((number << 3) >= m_idtr.limit) - throw TRAP(FAULT_GP, (number * 8 + 2 + hwint)); - - desc[0] = read_word(m_idtr.base + (number << 3)); - desc[1] = read_word(m_idtr.base + (number << 3) + 2); - desc[2] = read_word(m_idtr.base + (number << 3) + 4); - - r = RIGHTS(desc); - if(!hwint && (DPL(r) < CPL)) - throw TRAP(FAULT_GP, (number * 8 + 2 + hwint)); - if(!PRES(r)) - throw TRAP(FAULT_NP, (number * 8 + 2 + hwint)); - gatesel = GATESEL(desc); - - switch (GATE(r)) - { - case TASKGATE: - try - { - switch_task(gatesel, NT_CALL); - } - catch (uint32_t e) - { - throw e + hwint; - } - if((hwint == 1) && (error != -1)) - PUSH(error); - load_flags(CompressFlags(), CPL); // new flags - break; - - case INTGATE: - case TRAPGATE: - { - uint16_t gatedesc[3]; - uint32_t addr; - - if((addr = selector_address(gatesel)) == -1) - throw TRAP(FAULT_GP, (IDXTBL(gatesel) + hwint)); - - gatedesc[0] = read_word(addr); - gatedesc[1] = read_word(addr + 2); - gatedesc[2] = read_word(addr + 4); - r = RIGHTS(gatedesc); - if(!CODE(r) || !SEGDESC(r)) - throw TRAP(FAULT_GP, (IDXTBL(gatesel) + hwint)); - if(DPL(r) > CPL) - throw TRAP(FAULT_GP, (IDXTBL(gatesel) + hwint)); - if(!PRES(r)) - throw TRAP(FAULT_NP, (IDXTBL(gatesel) + hwint)); - if(GATEOFF(desc) > LIMIT(gatedesc)) - throw TRAP(FAULT_GP, hwint); - - if(!CONF(r) && (DPL(r) < CPL)) - { - // inner call - uint16_t tss_ss, tss_sp, oldss, oldsp; - tss_ss = read_word(m_tr.base + TSS_SS0 * 2 + (DPL(r) * 4)); - tss_sp = read_word(m_tr.base + TSS_SP0 * 2 + (DPL(r) * 4)); - - oldss = m_sregs[SS]; - oldsp = m_regs.w[SP]; - data_descriptor(SS, tss_ss, DPL(r), TRAP(FAULT_TS, (IDXTBL(tss_ss) + hwint)), tss_sp - ((error != -1) ? 12 : 10), (error != -1) ? 12 : 10); - m_regs.w[SP] = tss_sp; - PUSH(oldss); - PUSH(oldsp); - } - else - check_permission(SS, m_regs.w[SP] - ((error != -1) ? 8 : 6), (error != -1) ? 8 : 6, I8086_READ); - - SET_ACC(gatedesc); - write_word(addr + 4, gatedesc[2]); - PUSH(flags); - PUSH(m_sregs[CS]); - PUSH(m_ip); - if((hwint == 1) && (error != -1)) - PUSH(error); - m_sregs[CS] = IDXTBL(gatesel) | DPL(r); - m_limit[CS] = LIMIT(gatedesc); - m_base[CS] = BASE(gatedesc); - m_rights[CS] = RIGHTS(gatedesc); - m_ip = GATEOFF(desc); - m_TF = 0; - m_NT = 0; - if(GATE(RIGHTS(desc)) == INTGATE) - m_IF = 0; - break; - } - default: - throw TRAP(FAULT_GP, (number * 8 + 2 + hwint)); - } -} - -uint8_t i80286_cpu_device::read_port_byte(uint16_t port) -{ - if(PM && (CPL > m_IOPL)) - throw TRAP(FAULT_GP, 0); - if(m_io != NULL) { - return m_io->read_io8((uint32_t)port); - } - return 0xff; - //return m_io->read_byte(port); -} - -uint16_t i80286_cpu_device::read_port_word(uint16_t port) -{ - if(PM && (CPL > m_IOPL)) - throw TRAP(FAULT_GP, 0); - if(m_io != NULL) { - return m_io->read_io16((uint32_t)port); - } - //return m_io->read_byte_unaligned(port); - return 0xff; -} - -void i80286_cpu_device::write_port_byte(uint16_t port, uint8_t data) -{ - if(PM && (CPL > m_IOPL)) - throw TRAP(FAULT_GP, 0); - if(m_io != NULL) { - m_io->write_io8((uint32_t)port, (uint32_t)data); - } -} - -void i80286_cpu_device::write_port_word(uint16_t port, uint16_t data) -{ - if(PM && (CPL > m_IOPL)) - throw TRAP(FAULT_GP, 0); - //m_io->write_word_unaligned(port, data); - if(m_io != NULL) { - m_io->write_io16((uint32_t)port, (uint32_t)data); - } -} - -uint8_t i80286_cpu_device::fetch_op() -{ - uint8_t data = 0xff; - if(m_ip > m_limit[CS]) - throw TRAP(FAULT_GP, 0); - - //data = m_direct_opcodes->read_byte( pc() & m_amask, m_fetch_xor ); - if(m_program != NULL) data = m_program->read_data8(pc() & m_amask); - m_ip++; - return data; -} - -uint8_t i80286_cpu_device::fetch() -{ - uint8_t data = 0xff; - if(m_ip > m_limit[CS]) - throw TRAP(FAULT_GP, 0); - - //data = m_direct_opcodes->read_byte( pc() & m_amask, m_fetch_xor ); - if(m_program != NULL) data = m_program->read_data8(pc() & m_amask); - m_ip++; - return data; -} - -uint32_t i80286_cpu_device::calc_addr(int seg, uint16_t offset, int size, int op, bool override) -{ - seg = (m_seg_prefix && (seg==DS || seg==SS) && override) ? m_prefix_seg : seg; - if(op != I8086_NONE) - check_permission(seg, offset, size, op); - - return (m_base[seg] + offset) & (op != I8086_NONE ? m_amask : 0xffffff); -} - -void i80286_cpu_device::set_extra_clock(int icount) -{ - m_extra_cycles += icount; -} - -int i80286_cpu_device::get_extra_clock() -{ - return m_extra_cycles; -} - -uint32_t i80286_cpu_device::get_pc() -{ - return prev_pc(); -} - -uint32_t i80286_cpu_device::get_next_pc() -{ - return pc(); -} - -void i80286_cpu_device::debugger_hook() -{ - if(d_debugger != NULL) { - bool now_debugging = d_debugger->now_debugging; - if(now_debugging) { - d_debugger->check_break_points(pc); - if(d_debugger->now_suspended) { - emu->mute_sound(); - cpustate->debugger->now_waiting = true; - while(d_debugger->now_debugging && d_debugger->now_suspended) { - emu->sleep(10); - } - cpustate->debugger->now_waiting = false; - } - if(d_debugger->now_debugging) { - d_program = d_io = d_debugger; - } else { - now_debugging = false; - } - try - { - if (PM && ((m_pc - base[CS]) > limit[CS])) - throw TRAP(FAULT_GP, sregs[CS] & ~3); - m_prev_ip = m_ip; - execute_opcode(); // call instruction - } - catch (UINT32 e) - { - trap(e); - } - - if(now_debugging) { - if(!d_debugger->now_going) { - d_debugger->now_suspended = true; - } - d_program = d_program_stored; - d_io = d_io_stored; - } - } else { - exec_opcode(); - } - } else { - exec_opcode(); - } -} - -void i80286_cpu_device:: exec_opcode() -{ - uint8_t op = fetch_op(); - try { - switch(op) - { - case 0x07: // i_pop_es - pop_seg(ES); - CLK(POP_SEG); - break; - - case 0x0f: - { - unsigned next = fetch_op(); - uint16_t desc[3], tmp, msw, sel; - uint8_t r; - uint32_t addr; - - switch (next) - { - case 0: - if(!PM) - throw TRAP(FAULT_UD, (uint16_t)-1); - m_modrm = fetch(); - switch (m_modrm & 0x38) - { - case 0: /* sldt */ - PutRMWord(m_ldtr.sel); - break; - - case 8: /* str */ - PutRMWord(m_tr.sel); - break; - - case 0x10: /* lldt */ - if(CPL != 0) - throw TRAP(FAULT_GP, 0); - sel = GetRMWord(); - if(TBL(sel)) - throw TRAP(FAULT_GP, IDXTBL(sel)); - if(IDXTBL(sel)) - { - if(IDX(sel) >= m_gdtr.limit) - throw TRAP(FAULT_GP, IDXTBL(sel)); - addr = m_gdtr.base + IDX(sel); - desc[0] = read_word(addr); - desc[1] = read_word(addr + 2); - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - if(SEGDESC(r) || (GATE(r) != LDTDESC)) - throw TRAP(FAULT_GP, IDXTBL(sel)); - if(!PRES(r)) - throw TRAP(FAULT_NP, IDXTBL(sel)); - } - else - { - desc[0] = 0; - desc[1] = 0; - desc[2] = 0; - } - m_ldtr.sel = sel; - m_ldtr.limit = LIMIT(desc); - m_ldtr.base = BASE(desc); - m_ldtr.rights = RIGHTS(desc); - break; - - case 0x18: /* ltr */ - if(CPL != 0) - throw TRAP(FAULT_GP, 0); - sel = GetRMWord(); - if((addr = selector_address(sel)) == -1) - throw TRAP(FAULT_GP, IDXTBL(sel)); - desc[0] = read_word(addr); - desc[1] = read_word(addr + 2); - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - if(SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) - throw TRAP(FAULT_GP, IDXTBL(sel)); - if(!PRES(r)) - throw TRAP(FAULT_NP, IDXTBL(sel)); - desc[2] |= 0x200; // mark busy - write_word(addr + 4, desc[2]); - m_tr.sel = sel; - m_tr.limit = LIMIT(desc); - m_tr.base = BASE(desc); - m_tr.rights = RIGHTS(desc); - break; - - case 0x20: /* verr */ - tmp = GetRMWord(); - if((addr = selector_address(tmp)) == -1) - m_ZeroVal = 1; - else - { - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - m_ZeroVal = verify(tmp, I8086_READ, RIGHTS(desc), 0); - m_ZeroVal = m_ZeroVal || (CODE(r) && CONF(r) ? 0 : (DPL(r) < PMAX(RPL(tmp),CPL))); - } - break; - - case 0x28: /* verw */ - tmp = GetRMWord(); - if((addr = selector_address(tmp)) == -1) - m_ZeroVal = 1; - else - { - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - m_ZeroVal = verify(tmp, I8086_WRITE, RIGHTS(desc), 0); - m_ZeroVal = m_ZeroVal || (DPL(r) < PMAX(RPL(tmp),CPL)); - } - break; - - default: - throw TRAP(FAULT_UD, (uint16_t)-1); - } - break; - case 1: - { - uint32_t ea; - m_modrm = fetch(); - if((m_modrm >= 0xc0) && (m_modrm < 0xe0)) - throw TRAP(FAULT_UD, (uint16_t)-1); - switch (m_modrm & 0x38) - { - case 0: /* sgdt */ - ea = get_ea(6, I8086_WRITE); - write_word(ea, m_gdtr.limit); - write_word(ea + 2, m_gdtr.base & 0xffff); - write_word(ea + 4, 0xff00 | m_gdtr.base >> 16); - break; - case 8: /* sidt */ - ea = get_ea(6, I8086_WRITE); - write_word(ea, m_idtr.limit); - write_word(ea + 2, m_idtr.base & 0xffff); - write_word(ea + 4, 0xff00 | m_idtr.base >> 16); - break; - case 0x10: /* lgdt */ - if(PM && (CPL != 0)) - throw TRAP(FAULT_GP, 0); - ea = get_ea(6, I8086_READ); - m_gdtr.limit = read_word(ea); - m_gdtr.base = read_word(ea + 2) | (read_byte(ea + 4) << 16); - break; - case 0x18: /* lidt */ - if(PM && (CPL != 0)) - throw TRAP(FAULT_GP, 0); - ea = get_ea(6, I8086_READ); - m_idtr.limit = read_word(ea); - m_idtr.base = read_word(ea + 2) | (read_byte(ea + 4) << 16); - break; - case 0x20: /* smsw */ - PutRMWord(m_msw); - break; - case 0x30: /* lmsw */ - if(PM && (CPL != 0)) - throw TRAP(FAULT_GP, 0); - msw = GetRMWord(); - m_msw = (m_msw & 1) | msw; - break; - default: - throw TRAP(FAULT_UD, (uint16_t)-1); - } - break; - } - case 2: /* LAR */ - if(!PM) - throw TRAP(FAULT_UD, (uint16_t)-1); - m_modrm = fetch_op(); - tmp = GetRMWord(); - if((addr = selector_address(tmp)) == -1) - m_ZeroVal = 1; - else - { - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - if(!SEGDESC(r) && ((GATE(r) > TRAPGATE) || !GATE(r))) - m_ZeroVal = 1; - else if(DPL(r) >= PMAX(RPL(tmp),CPL) || (SEGDESC(r) && CODE(r) && CONF(r))) - { - m_ZeroVal = 0; - // rights are expected to be in upper byte - RegWord(r << 8); - } - else - m_ZeroVal = 1; - } - break; - case 3: /* LSL */ - if(!PM) - throw TRAP(FAULT_UD, (uint16_t)-1); - m_modrm = fetch_op(); - tmp = GetRMWord(); - if((addr = selector_address(tmp)) == -1) - m_ZeroVal = 1; - else - { - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - if(!SEGDESC(r) && ((GATE(r) >= CALLGATE) || !GATE(r))) - m_ZeroVal = 1; // not valid for gates - else if(DPL(r) >= PMAX(RPL(tmp),CPL) || (SEGDESC(r) && CODE(r) && CONF(r))) - { - m_ZeroVal = 0; - RegWord(read_word(addr)); - } - else - m_ZeroVal = 1; - } - break; - case 5: /* loadall */ - if(PM && (CPL != 0)) - throw TRAP(FAULT_GP, 0); - m_msw = (m_msw & 1) | read_word(0x806); - m_tr.sel = read_word(0x816); - ExpandFlags(read_word(0x818)); - m_ip = read_word(0x81a); - m_ldtr.sel = read_word(0x81c); - m_sregs[DS] = read_word(0x81e); - m_sregs[SS] = read_word(0x820); - m_sregs[CS] = read_word(0x822); - m_sregs[ES] = read_word(0x824); - m_regs.w[DI] = read_word(0x826); - m_regs.w[SI] = read_word(0x828); - m_regs.w[BP] = read_word(0x82a); - m_regs.w[SP] = read_word(0x82c); - m_regs.w[BX] = read_word(0x82e); - m_regs.w[DX] = read_word(0x830); - m_regs.w[CX] = read_word(0x832); - m_regs.w[AX] = read_word(0x834); - // loadall uses base-rights-limit order -#define LOADDESC(addr, sreg) { desc[1] = read_word(addr); desc[2] = read_word(addr+2); desc[0] = read_word(addr+4); \ - m_base[sreg] = BASE(desc); m_rights[sreg] = RIGHTS(desc); \ - m_limit[sreg] = LIMIT(desc); } - LOADDESC(0x836, ES); - LOADDESC(0x83C, CS); - LOADDESC(0x842, SS); - LOADDESC(0x848, DS); -#undef LOADDESC - // void cast supresses warning -#define LOADDESC(addr, reg, r) { desc[1] = read_word(addr); desc[2] = read_word(addr + 2); desc[0] = read_word(addr + 4); \ - reg.base = BASE(desc); (void)(r); reg.limit = LIMIT(desc); } - LOADDESC(0x84e, m_gdtr, 1); - LOADDESC(0x854, m_ldtr, m_ldtr.rights = RIGHTS(desc)); - LOADDESC(0x85a, m_idtr, 1); - LOADDESC(0x860, m_tr, m_tr.rights = RIGHTS(desc)); -#undef LOADDESC - break; - - case 6: /* clts */ - if(PM && (CPL != 0)) - throw TRAP(FAULT_GP, 0); - m_msw &= ~8; - break; - default: - throw TRAP(FAULT_UD, (uint16_t)-1); - } - break; - } - - case 0x17: // i_pop_ss - pop_seg(SS); - CLK(POP_SEG); - m_no_interrupt = 1; - break; - - case 0x1f: // i_pop_ds - pop_seg(DS); - CLK(POP_SEG); - break; - - case 0x54: // i_push_sp - PUSH(m_regs.w[SP]); - CLK(PUSH_R16); - break; - - case 0x60: // i_pusha - { - check_permission(SS, m_regs.w[SP]-16, 16, I8086_WRITE); - uint32_t tmp = m_regs.w[SP]; - PUSH(m_regs.w[AX]); - PUSH(m_regs.w[CX]); - PUSH(m_regs.w[DX]); - PUSH(m_regs.w[BX]); - PUSH(tmp); - PUSH(m_regs.w[BP]); - PUSH(m_regs.w[SI]); - PUSH(m_regs.w[DI]); - CLK(PUSHA); - } - break; - - case 0x61: // i_popa - check_permission(SS, m_regs.w[SP], 16, I8086_READ); - m_regs.w[DI] = POP(); - m_regs.w[SI] = POP(); - m_regs.w[BP] = POP(); - POP(); - m_regs.w[BX] = POP(); - m_regs.w[DX] = POP(); - m_regs.w[CX] = POP(); - m_regs.w[AX] = POP(); - CLK(POPA); - break; - - case 0x62: // i_bound - { - uint32_t low,high,tmp; - m_modrm = fetch(); - low = GetRMWord(); - high = GetnextRMWord(); - tmp = RegWord(); - if (tmphigh) - interrupt(5); - CLK(BOUND); - logerror("%06x: bound %04x high %04x low %04x tmp\n", pc(), high, low, tmp); - } - break; - - case 0x63: // arpl - { - uint16_t tmp, source; - if (!PM) throw TRAP(FAULT_UD,(uint16_t)-1); - - m_modrm=fetch_op(); - tmp=GetRMWord(); - source=RegWord(); - - if (RPL(tmp)> 15 != 0) && (((int32_t)m_dst) >> 15 != -1); - RegWord(m_dst); - CLKM(IMUL_RRI16, IMUL_RMI16); - } - break; - - case 0x6a: // i_push_d8 - PUSH( (uint16_t)((int16_t)((int8_t)fetch())) ); - CLK(PUSH_IMM); - break; - - case 0x6b: // i_imul_d8 - { - uint32_t src2; - DEF_r16w(); - src2= (uint16_t)((int16_t)((int8_t)fetch())); - m_dst = (int32_t)((int16_t)m_src)*(int32_t)((int16_t)src2); - m_CarryVal = m_OverVal = (((int32_t)m_dst) >> 15 != 0) && (((int32_t)m_dst) >> 15 != -1); - RegWord(m_dst); - CLKM(IMUL_RRI8, IMUL_RMI8); - } - break; - - case 0x6c: // i_insb - i_insb(); - break; - - case 0x6d: // i_insw - i_insw(); - break; - - case 0x6e: // i_outsb - i_outsb(); - break; - - case 0x6f: // i_outsw - i_outsw(); - break; - - case 0x8c: // i_mov_wsreg - m_modrm = fetch(); - if((m_modrm & 0x38) > 0x18) - { - logerror("%06x: Mov Sreg - Invalid register\n", pc()); - throw TRAP(FAULT_UD, (uint16_t)-1); - } - PutRMWord(m_sregs[(m_modrm & 0x38) >> 3]); - CLKM(MOV_RS,MOV_MS); - break; - - case 0x8e: // i_mov_sregw - m_modrm = fetch(); - m_src = GetRMWord(); - CLKM(MOV_SR,MOV_SM); - switch (m_modrm & 0x38) - { - case 0x00: /* mov es,ew */ - data_descriptor(ES, m_src); - break; - case 0x10: /* mov ss,ew */ - data_descriptor(SS, m_src); - m_no_interrupt = 1; - break; - case 0x18: /* mov ds,ew */ - data_descriptor(DS, m_src); - break; - default: - logerror("%06x: Mov Sreg - Invalid register\n", pc()); - throw TRAP(FAULT_UD, (uint16_t)-1); - } - break; - - case 0x8f: // i_popw - { - m_modrm = fetch(); - uint16_t tmp = read_word(calc_addr(SS, m_regs.w[SP], 2, I8086_READ, false)); - PutRMWord( tmp ); - m_regs.w[SP] += 2; - CLKM(POP_R16,POP_M16); - break; - } - - case 0x9a: // i_call_far - { - uint16_t cs = m_sregs[CS]; - uint16_t tmp = fetch_word(); - uint16_t tmp2 = fetch_word(); - uint16_t ip = m_ip; - code_descriptor(tmp2, tmp, NT_CALL); - if(call_pseudo_bios(((tmp2 << 4) + tmp) & m_amask)) { - CLK(CALL_FAR); - return; - } - PUSH(cs); - PUSH(ip); - CLK(CALL_FAR); - } - break; - - case 0x9b: // i_wait - if((m_msw & 0x0a) == 0x0a) - throw TRAP(FAULT_NM, (uint16_t)-1); - if (m_test_state != 0) { - m_icount = 0; - m_ip--; // pc? - } else { - CLK(WAIT); - } - break; - - case 0x9c: // pushf - { - uint16_t flags = CompressFlags(); - if(!PM) - flags &= ~0xf000; - PUSH(flags); - CLK(PUSHF); - break; - } - - case 0x9d: // popf - { - uint16_t flags; - flags = POP(); - CLK(POPF); - load_flags(flags, CPL); - break; - } - - case 0xc0: // i_rotshft_bd8 - { - uint8_t c; - m_modrm = fetch(); - m_src = GetRMByte(); - m_dst = m_src; - c = fetch() & 0x1f; - CLKM(ROT_REG_BASE,ROT_M8_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x30: - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x38: SHRA_BYTE(c); break; - } - } - } - break; - - case 0xc1: // i_rotshft_wd8 - { - uint8_t c; - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - c = fetch() & 0x1f; - CLKM(ROT_REG_BASE,ROT_M16_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x30: - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x38: SHRA_WORD(c); break; - } - } - } - break; - - case 0xc4: // i_les_dw - { - m_modrm = fetch(); - if(m_modrm >= 0xc0) - throw TRAP(FAULT_UD, (uint16_t)-1); - uint16_t tmp = GetRMWord(); - data_descriptor(ES, GetnextRMWord()); - RegWord(tmp); - CLK(LOAD_PTR); - break; - } - - case 0xc5: // i_lds_dw - { - m_modrm = fetch(); - if(m_modrm >= 0xc0) - throw TRAP(FAULT_UD, (uint16_t)-1); - uint16_t tmp = GetRMWord(); - data_descriptor(DS, GetnextRMWord()); - RegWord(tmp); - CLK(LOAD_PTR); - break; - } - - case 0xc8: // i_enter - { - uint16_t nb = fetch(); - uint32_t level; - - nb |= fetch() << 8; - level = fetch(); - CLK(!level ? ENTER0 : (level == 1) ? ENTER1 : ENTER_BASE); - if(level > 1) - m_icount -= level * m_timing[ENTER_COUNT]; - PUSH(m_regs.w[BP]); - m_regs.w[BP] = m_regs.w[SP]; - m_regs.w[SP] -= nb; - for (int i=1; i0); PutbackRMByte(m_dst); break; - case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x30: - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x38: SHRA_BYTE(c); break; - } - } - } - break; - - case 0xd3: // i_rotshft_wcl - { - uint8_t c; - - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - c = m_regs.b[CL] & 0x1f; - CLKM(ROT_REG_BASE,ROT_M16_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x30: - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x38: SHRA_WORD(c); break; - } - } - } - break; - - case 0xd8: // i_esc - case 0xd9: - case 0xda: - case 0xdb: - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: - if((m_msw & 8) || (m_msw & 4)) - throw TRAP(FAULT_NM, (uint16_t)-1); - m_modrm = fetch(); - GetRMByte(); - CLK(NOP); - if((m_modrm == 0xe0) && (op == 0xdf)) - m_regs.w[AX] = 0xffff; // FPU not present - break; - - case 0xea: // i_jmp_far - { - uint16_t tmp = fetch_word(); - uint16_t tmp1 = fetch_word(); - code_descriptor(tmp1, tmp, NT_JMP); - CLK(JMP_FAR); - break; - } - - case 0xf0: // i_lock - if(PM && (CPL > m_IOPL)) - throw TRAP(FAULT_GP, 0); - logerror("%06x: Warning - BUSLOCK\n", pc()); - m_no_interrupt = 1; - CLK(NOP); - break; - - case 0xf4: // i_hlt - if(PM && CPL) - throw TRAP(FAULT_GP, 0); - m_icount = 0; - m_halt = true; - break; - - case 0xfa: // i_cli - if(PM && (CPL > m_IOPL)) - throw TRAP(FAULT_GP, 0); - m_IF = 0; - CLK(FLAG_OPS); - break; - - case 0xfb: // i_sti - if(PM && (CPL > m_IOPL)) - throw TRAP(FAULT_GP, 0); - m_IF = 1; - CLK(FLAG_OPS); - break; - - case 0xff: // i_ffpre - { - uint32_t tmp, tmp1; - m_modrm = fetch(); - tmp = GetRMWord(); - switch ( m_modrm & 0x38 ) - { - case 0x00: /* INC */ - tmp1 = tmp+1; - m_OverVal = (tmp==0x7fff); - set_AF(tmp1,tmp,1); - set_SZPF_Word(tmp1); - PutbackRMWord(tmp1); - CLKM(INCDEC_R16,INCDEC_M16); - break; - case 0x08: /* DEC */ - tmp1 = tmp-1; - m_OverVal = (tmp==0x8000); - set_AF(tmp1,tmp,1); - set_SZPF_Word(tmp1); - PutbackRMWord(tmp1); - CLKM(INCDEC_R16,INCDEC_M16); - break; - case 0x10: /* CALL */ - if(call_pseudo_bios((m_base[m_CS] + (uint16_t)tmp) & m_amask)) { - CLK(CALL_R16,CALL_M16); - //m_ip = m_ip + tmp; - return; - } - PUSH(m_ip); - m_ip = tmp; - CLKM(CALL_R16,CALL_M16); - break; - case 0x18: /* CALL FAR */ - { - uint16_t ip = m_ip; - tmp1 = m_sregs[CS]; - code_descriptor(GetnextRMWord(), tmp, NT_CALL); - if(call_pseudo_bios(((m_sregs[CS] << 4) + tmp1) & m_amask) { // OK? - CLK(CALL_M32); - //m_ip = m_ip + tmp; - return; - } - PUSH(tmp1); - PUSH(ip); - CLK(CALL_M32); - break; - } - case 0x20: /* JMP */ - m_ip = tmp; - CLKM(JMP_R16,JMP_M16); - break; - case 0x28: /* JMP FAR */ - code_descriptor(GetnextRMWord(), tmp, NT_JMP); - CLK(JMP_M32); - break; - case 0x30: - PUSH(tmp); - CLKM(PUSH_R16,PUSH_M16); - break; - default: - logerror("%06x: FF Pre with unimplemented mod\n", pc()); - throw TRAP(FAULT_UD,(uint16_t)-1); - } - } - break; - - case 0xf2: // i_repne - case 0xf3: - { - bool pass = false; - uint8_t next = repx_op(); - uint16_t c = m_regs.w[CX]; - - switch (next) - { - case 0x6c: CLK(OVERRIDE); if (c) do { i_insb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6d: CLK(OVERRIDE); if (c) do { i_insw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6e: CLK(OVERRIDE); if (c) do { i_outsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0x6f: CLK(OVERRIDE); if (c) do { i_outsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - default: - // Decrement IP and pass on - m_ip -= 1 + (m_seg_prefix_next ? 1 : 0); - pass = true; - } - if(!pass) - { - if(c) - m_ip = m_prev_ip; - break; - } - } - - default: - if(!common_op(op)) - { - m_icount -= 10; // UD fault timing? - logerror("%06x: Invalid Opcode %02x\n", pc(), op); - m_ip = m_prev_ip; - throw TRAP(FAULT_UD, (uint16_t)-1); - } - break; - } - catch(uint32_t e) - { - trap(e); - } -} - -void i80286_cpu_device::execute_run(int icount) -{ - if (m_halt || m_busreq) - { -//#ifdef SINGLE_MODE_DMA - if (d_dma != NULL) { - d_dma->do_dma(); - } -//#endif - if (icount == -1) { - int passed_icount = max(1, m_extra_cycles); - // this is main cpu, cpustate->icount is not used - /*cpustate->icount = */m_extra_cycles = 0; - return passed_icount; - } else { - cpustate->icount += icount; - int base_icount = m_icount; - - /* adjust for any interrupts that came in */ - m_icount -= m_extra_cycles; - m_extra_cycles = 0; - - /* if busreq is raised, spin cpu while remained clock */ - if (m_icount > 0) { - m_icount = 0; - } - return base_icount - m_icount; - } - } - - if (icount == -1) { - m_icount = 1; - } else { - m_icount += icount; - } - int base_icount = m_icount; - - /* adjust for any interrupts that came in */ - m_icount -= m_extra_cycles; - m_extra_cycles = 0; - - while(m_icount > 0 && !m_busreq) - { -// try - { - if ( m_seg_prefix_next ) - { - m_seg_prefix = true; - m_seg_prefix_next = false; - } - else - { - m_prev_ip = m_ip; - m_seg_prefix = false; - - /* Dispatch IRQ */ - if ( m_pending_irq && m_no_interrupt == 0 ) - { - if ( m_pending_irq & NMI_IRQ ) - { - interrupt_descriptor(NMI, 1, -1); - m_pending_irq &= ~NMI_IRQ; - m_halt = false; - m_shutdown = false; - //m_out_shutdown_func(false); - write_signals(&out_shutdown, 0); - } - else if ( m_IF ) - { - interrupt_descriptor(-1, 1, -1); - m_halt = false; - } - } - - if(m_halt || m_shutdown) - { - m_icount = 0; - return; - } - - /* No interrupt allowed between last instruction and this one */ - if ( m_no_interrupt ) - { - m_no_interrupt--; - } - - /* trap should allow one instruction to be executed */ - if ( m_fire_trap ) - { - if ( m_fire_trap >= 2 ) - { - interrupt(1); - m_fire_trap = 0; - } - else - { - m_fire_trap++; - } - } - } - - /* debugger_instruction_hook( this, pc() & m_amask ); */ - debugger_hook(); - //exec_opcode(); - } -// catch(uint32_t e) -// { -// trap(e); -// } -//#ifdef SINGLE_MODE_DMA - if (d_dma != NULL) { - d_dma->do_dma(); - } -//#endif - } - /* if busreq is raised, spin cpu while remained clock */ - if (m_icount > 0 && m_busreq) { - m_icount = 0; - } - return base_icount - m_icount; -} - - -void i80286_cpu_device::load_flags(uint16_t flags, int cpl) -{ - uint16_t oldflags = CompressFlags(); - flags &= ~0x8000; - if(PM && cpl) - { - uint16_t mask = 0x3000; - if(cpl > m_IOPL) - mask |= 0x200; - flags &= ~mask; - flags |= (oldflags & mask); - } - else if(!PM) - (flags &= ~0xf000); - ExpandFlags(flags); - - if(m_TF) - m_fire_trap = 1; -} - -uint16_t i80286_cpu_device::far_return(int iret, int bytes) -{ - uint16_t sel, off, flags = 0; - int spaddr; - - if(PM && m_NT && iret) - { - switch_task(read_word(m_tr.base + TSS_BACK * 2), NT_IRET); - return CompressFlags(); - } - - // must be restartable - if(PM) - check_permission(SS, m_regs.w[SP], (iret ? 6 : 4), I8086_READ); - - spaddr = (m_base[SS] + m_regs.w[SP]) & m_amask; - off = read_word(spaddr); - sel = read_word(spaddr + 2); - if(iret) - flags = read_word(spaddr + 4); - - if(PM) - { - uint16_t desc[3], newsp, newss; - int addr, r; - - if((addr = selector_address(sel)) == -1) - throw TRAP(FAULT_GP, IDXTBL(sel)); - - if(RPL(sel) < CPL) - throw TRAP(FAULT_GP, IDXTBL(sel)); - desc[0] = read_word(addr); - desc[1] = read_word(addr + 2); - desc[2] = read_word(addr + 4); - r = RIGHTS(desc); - - if(!CODE(r) || !SEGDESC(r)) - throw TRAP(FAULT_GP, IDXTBL(sel)); - if(CONF(r)) - { - if(DPL(r) > RPL(sel)) - throw TRAP(FAULT_GP, IDXTBL(sel)); - } - else if(DPL(r) != RPL(sel)) - throw TRAP(FAULT_GP, IDXTBL(sel)); - - if(!PRES(r)) - throw TRAP(FAULT_NP, IDXTBL(sel)); - if(off > LIMIT(desc)) - throw TRAP(FAULT_GP, 0); - if(CPL < RPL(sel)) - { - check_permission(SS, m_regs.w[SP] + (iret ? 6 : 4) + bytes, 4, I8086_READ); - newsp = read_word(spaddr + ((iret ? 6 : 4) + bytes)); - newss = read_word(spaddr + ((iret ? 8 : 6) + bytes)); - data_descriptor(SS, newss, RPL(sel), TRAP(FAULT_GP, IDXTBL(newss))); - m_regs.w[SP] = newsp + bytes; - } - else - m_regs.w[SP] += (iret ? 6 : 4) + bytes; - SET_ACC(desc); - write_word(addr + 4, desc[2]); - m_sregs[CS] = sel; - m_limit[CS] = LIMIT(desc); - m_base[CS] = BASE(desc); - m_rights[CS] = RIGHTS(desc); - m_ip = off; - - // docs say check rpl but windows doesn't like it - r = m_rights[DS]; - if(verify(m_sregs[DS], I8086_READ, r, 0) || (CODE(r) && CONF(r) ? 0 : (DPL(r) < CPL))) - data_descriptor(DS, 0); - r = m_rights[ES]; - if(verify(m_sregs[ES], I8086_READ, r, 0) || (CODE(r) && CONF(r) ? 0 : (DPL(r) < CPL))) - data_descriptor(ES, 0); - } - else - { - m_regs.w[SP] += (iret ? 6 : 4) + bytes; - m_sregs[CS] = sel; - m_base[CS] = sel << 4; - m_rights[CS] = 0x9b; - m_limit[CS] = 0xffff; - m_ip = off; - } - - return flags; -} - -void i80286_cpu_device::check_permission(uint8_t check_seg, uint32_t offset, uint16_t size, int operation) -{ - int trap; - uint8_t rights; - if(PM) - { - rights = m_rights[check_seg]; - trap = verify(m_sregs[check_seg], operation, rights, m_valid[check_seg]); - if((CODE(rights) || !EXPDOWN(rights)) && ((offset+size-1) > m_limit[check_seg])) { - trap = FAULT_GP; - } - if(!CODE(rights) && EXPDOWN(rights) && ((offset <= m_limit[check_seg]) || ((offset + size - 1) > 0xffff))) { - trap = FAULT_GP; - } - if((trap == FAULT_GP) && (check_seg == SS)) { - trap = FAULT_SS; - } - if(trap) { - throw TRAP(trap, 0); - } - } -} - -int i80286_cpu_device::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len) -{ - - std::ostringstream ostbuf; - extern int i386_dasm_one(std::ostream &stream, uint64_t eip, const uint8_t *oprom, int mode); - - cpu_state *cpustate = (cpu_state *)opaque; - UINT64 eip = pc - base[CS]; - UINT8 ops[16]; - for(int i = 0; i < 16; i++) { - int wait; - ops[i] = d_mem->read_data8w(pc + i, &wait); - } - const uint8_t *oprom = ops; - i386_dasm_one(ostbuf, eip, oprom, 1); - ostbuf.str().copy((char *)buffer, buffer_len); -} - -bool i80286_cpu_device::call_pseudo_bios(uint32_t pc) -{ - // blank - return false; // Not hit -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i286.h b/source/src/vm/libcpu_newdev/libcpu_i286/i286.h deleted file mode 100644 index 66553e991..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i286.h +++ /dev/null @@ -1,168 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -#ifndef I286_H_ -#define I286_H_ - -#include "i86.h" -#define INPUT_LINE_A20 1 - -extern const device_type I80286; - -enum -{ // same order as I8086 registers - I286_PC = STATE_GENPC, - - I286_IP = 1, - I286_AX, - I286_CX, - I286_DX, - I286_BX, - I286_SP, - I286_BP, - I286_SI, - I286_DI, - I286_FLAGS, - - I286_ES, - I286_CS, - I286_SS, - I286_DS, - - I286_VECTOR, - I286_HALT, - - I286_ES_BASE, - I286_ES_LIMIT, - I286_ES_FLAGS, - I286_CS_BASE, - I286_CS_LIMIT, - I286_CS_FLAGS, - I286_SS_BASE, - I286_SS_LIMIT, - I286_SS_FLAGS, - I286_DS_BASE, - I286_DS_LIMIT, - I286_DS_FLAGS, - - I286_MSW, - - I286_GDTR_BASE, - I286_GDTR_LIMIT, - I286_IDTR_BASE, - I286_IDTR_LIMIT, - I286_TR, - I286_TR_BASE, - I286_TR_LIMIT, - I286_TR_FLAGS, - I286_LDTR, - I286_LDTR_BASE, - I286_LDTR_LIMIT, - I286_LDTR_FLAGS -}; - -class i80286_cpu_device : public i8086_common_cpu_device -{ -public: - // construction/destruction - i80286_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // device_memory_interface overrides - - typedef delegate a20_cb; - -protected: - virtual void execute_run() override; - virtual void device_reset() override; - virtual void device_start() override; - - // device_state_interface overrides - virtual void state_import(const device_state_entry &entry) override; - virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - - virtual uint32_t execute_input_lines() const override { return 1; } - virtual void execute_set_input(int inputnum, int state) override; - bool memory_translate(address_spacenum spacenum, int intention, offs_t &address) override; - - virtual void interrupt(int int_num, int trap = 1) override { if(trap) throw TRAP(int_num, (uint16_t)-1); else interrupt_descriptor(int_num, 0, 0); } - virtual uint8_t read_port_byte(uint16_t port) override; - virtual uint16_t read_port_word(uint16_t port) override; - virtual void write_port_byte(uint16_t port, uint8_t data) override; - virtual void write_port_word(uint16_t port, uint16_t data) override; - - // Executing instructions - virtual uint8_t fetch_op() override; - virtual uint8_t fetch() override; - virtual uint32_t calc_addr(int seg, uint16_t offset, int size, int op, bool override = true) override; - -private: - void check_permission(uint8_t check_seg, uint32_t offset, uint16_t size, int operation); - void code_descriptor(uint16_t selector, uint16_t offset, int gate); - void data_descriptor(int reg, uint16_t selector); - void data_descriptor(int reg, uint16_t selector, int cpl, uint32_t trap, uint16_t offset = 0, int size = 0); - uint16_t far_return(int iret, int bytes); - void interrupt_descriptor(int number, int hwint, int error); - void load_flags(uint16_t flags, int cpl); - void pop_seg(int reg); - uint32_t selector_address(uint16_t sel); - void switch_task(uint16_t ntask, int type); - void trap(uint32_t error); - int verify(uint16_t selector, int operation, uint8_t rights, bool valid); - uint32_t pc() { return m_pc = m_base[CS] + m_ip; } - - outputs_t out_a20; - outputs_t out_shutdown; - int m_trap_level; - uint16_t m_msw; - uint32_t m_base[4]; - uint16_t m_limit[4]; - uint8_t m_rights[4]; - bool m_valid[4]; - - uint32_t m_amask; - bool m_shutdown; - - struct { - uint32_t base; - uint16_t limit; - } m_gdtr, m_idtr; - struct { - uint16_t sel; - uint32_t base; - uint16_t limit; - uint8_t rights; - } m_ldtr, m_tr; - - uint32_t TRAP(uint16_t fault, uint16_t code) { return ((((uint32_t)fault&0xffff)<<16)|(code&0xffff)); } - - address_space_config m_program_config; - address_space_config m_opcodes_config; - address_space_config m_io_config; - static const uint8_t m_i80286_timing[200]; - - enum { - FAULT_DE = 0, - FAULT_DB, - NMI, - FAULT_BP, - FAULT_OF, - FAULT_BR, - FAULT_UD, - FAULT_NM, - FAULT_DF, - FAULT_MP, - FAULT_TS, - FAULT_NP, - FAULT_SS, - FAULT_GP - }; - - -}; - -#define MCFG_80286_A20(_class, _a20_cb) \ - i80286_cpu_device::static_set_a20_callback(*device, i80286_cpu_device::a20_cb(&_class::_a20_cb, (_class *)owner)); - -#define MCFG_80286_SHUTDOWN(_devcb) \ - devcb = &i80286_cpu_device::static_set_shutdown_callback(*device, DEVCB_##_devcb); - -#endif /* I286_H_ */ diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i86.cpp b/source/src/vm/libcpu_newdev/libcpu_i286/i86.cpp deleted file mode 100644 index 8efd582a4..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i86.cpp +++ /dev/null @@ -1,2455 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -/**************************************************************************** - - NEC V20/V30/V33 emulator modified back to a 8086/80186 emulator - - (Re)Written June-September 2000 by Bryan McPhail (mish@tendril.co.uk) based - on code by Oliver Bergmann (Raul_Bloodworth@hotmail.com) who based code - on the i286 emulator by Fabrice Frances which had initial work based on - David Hedley's pcemu(!). - -****************************************************************************/ - -#include "../../device.h" -#include "../../fmr50/bios.h" -#include "debugger.h" -#include "./i86.h" -#include "./i86inline.h" - -#define I8086_NMI_INT_VECTOR 2 - -const uint8_t i8086_cpu_device::m_i8086_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 */ -}; - -/***************************************************************************/ -/* cpu state */ -/***************************************************************************/ - -/***************************************************************************/ - -i8088_cpu_device::i8088_cpu_device(VM_TEMPLATE* parent_vm, EMU* parent_emu) : i8086_cpu_device(parent_vm, parent_emu) -{ - memcpy(m_timing, m_i8086_timing, sizeof(m_i8086_timing)); - m_amask = 0x000fffff; -} - -i8088_cpu_device::~i8088_cpu_device() -{ -} - - -i8086_cpu_device::i8086_cpu_device(VM_TEMPLATE* parent_vm, EMU* parent_emu) : i8086_common_cpu_device(parent_vm, parent_emu) -{ - memcpy(m_timing, m_i8086_timing, sizeof(m_i8086_timing)); - m_extra_cycles = 0; - m_busreq = false; - m_test = 0; - m_amask = 0x000fffff; -} - -i8086_cpu_device::~i8086_cpu_device() -{ -} - - -uint8_t i8086_cpu_device::fetch_op() -{ - uint8_t data; - if(d_program == NULL) return 0xff; - data = d_program->read_data8(pc()); - m_ip++; - return data; -} - -uint8_t i8086_cpu_device::fetch() -{ - uint8_t data; - if(d_program == NULL) return 0xff; - data = d_program->read_data8(pc()); - m_ip++; - return data; -} - -void i8086_cpu_device::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, m_extra_icount); - // this is main cpu, icount is not used - /*icount = */ - m_extra_icount = 0; - return passed_icount; - } else { - m_icount += clock; - int first_icount = m_icount; - - /* adjust for any interrupts that came in */ - m_icount -= m_extra_icount; - m_extra_icount = 0; - - /* if busreq is raised, spin cpu while remained clock */ - if(m_icount > 0) { - m_icount = 0; - } - return first_icount - m_icount; - } - } - if(clock == -1) { - /* run only one opcode */ - m_icount = -m_extra_icount; - m_extra_icount = 0; -#ifdef USE_DEBUGGER - execute_run(); - //execute_run_debugger(); -#else - execute_run(); -#endif - return -m_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(m_icount > 0 && !busreq) { -#ifdef USE_DEBUGGER - execute_run(); - //execute_run_debugger(); -#else - execute_run(); -#endif - } - /* if busreq is raised, spin cpu while remained clock */ - if(m_icount > 0 && busreq) { - m_icount = 0; - } - return first_icount - m_icount; - } -} - -void i8086_cpu_device::debugger_instruction_hook() -{ - -} - -void i8086_cpu_device::execute_run() -{ -// while(m_icount > 0 ) -// { - if ( m_seg_prefix_next ) - { - m_seg_prefix = true; - m_seg_prefix_next = false; - } - else - { - m_prev_ip = m_ip; - m_seg_prefix = false; - - /* Dispatch IRQ */ - if ( m_pending_irq && (m_no_interrupt == 0) ) - { - if ( m_pending_irq & NMI_IRQ ) - { - interrupt(I8086_NMI_INT_VECTOR); - m_pending_irq &= ~NMI_IRQ; - } - else if ( m_IF ) - { - /* the actual vector is retrieved after pushing flags */ - /* and clearing the IF */ - interrupt(-1); - } - } - - /* Trap should allow one instruction to be executed. - CPUID.ASM (by Bob Smith, 1985) suggests that in situations where m_no_interrupt is 1, - (directly after POP SS / MOV_SREG), single step IRQs don't fire. - */ - if (m_fire_trap ) - { - if ( (m_fire_trap >= 2) && (m_no_interrupt == 0) ) - { - m_fire_trap = 0; // reset trap flag upon entry - interrupt(1); - } - else - { - m_fire_trap++; - } - } - - /* No interrupt allowed between last instruction and this one */ - if ( m_no_interrupt ) - { - m_no_interrupt--; - } - - } - - if (!m_seg_prefix) - { -// debugger_instruction_hook( this, pc() ); - } - - uint8_t op = fetch_op(); - - switch(op) - { - case 0x0f: - m_sregs[CS] = POP(); - CLK(POP_SEG); - break; - - case 0xd2: // i_rotshft_bcl - { - uint8_t c; - - m_modrm = fetch(); - m_src = GetRMByte(); - m_dst = m_src; - c = m_regs.b[CL]; - CLKM(ROT_REG_BASE,ROT_M8_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break; - case 0x30: - case 0x20: SHL_BYTE(c); break; - case 0x28: SHR_BYTE(c); break; - case 0x38: SHRA_BYTE(c); break; - } - } - } - break; - - case 0xd3: // i_rotshft_wcl - { - uint8_t c; - - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - c = m_regs.b[CL]; - CLKM(ROT_REG_BASE,ROT_M16_BASE); - m_icount -= m_timing[ROT_REG_BIT] * c; - if (c) - { - switch ( m_modrm & 0x38 ) - { - case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break; - case 0x30: - case 0x20: SHL_WORD(c); break; - case 0x28: SHR_WORD(c); break; - case 0x38: SHRA_WORD(c); break; - } - } - } - break; - - default: - if(!common_op(op)) - { - m_icount -= 10; - logerror("%06x: Invalid Opcode %02x\n", pc(), op); - break; - } - break; - } -// } -#ifdef SINGLE_MODE_DMA - if(d_dma) { - d_dma->do_dma(); - } -#endif - m_icount -= m_extra_icount; - m_extra_icount = 0; -} - -i8086_common_cpu_device::i8086_common_cpu_device(VM_TEMPLATE* prev_vm, EMU* prev_emu) - : DEVICE(prev_vm, prev_emu) - , m_ip(0) - , m_TF(0) - , m_int_vector(0) - , m_pending_irq(0) - , m_nmi_state(0) - , m_irq_state(0) - , m_test_state(1) - , m_pc(0) - , m_busreq(false) - , m_extra_cycles(0) - , m_lock(false) - , m_lock_handler(*this) -{ - static const BREGS reg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH }; - - /* Set up parity lookup table. */ - for (uint16_t i = 0;i < 256; i++) - { - uint16_t c = 0; - for (uint16_t j = i; j > 0; j >>= 1) - { - if (j & 1) c++; - } - m_parity_table[i] = !(c & 1); - } - - for (uint16_t i = 0; i < 256; i++) - { - m_Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3]; - m_Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ; - } - - for (uint16_t i = 0xc0; i < 0x100; i++) - { - m_Mod_RM.RM.w[i] = (WREGS)( i & 7 ); - m_Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7]; - } - - memset(&m_regs, 0x00, sizeof(m_regs)); - memset(m_sregs, 0x00, sizeof(m_sregs)); - - d_program = NULL; - d_dma = NULL; - d_io = NULL; - d_bios = NULL; - - d_debugger = NULL; - d_mem_stored = NULL; - d_io_stored = NULL; -} - -bool i8086_common_cpu_device::call_pseudo_bios(uint32_t PC) -{ - if(d_bios == NULL) return false; - bool stat; - stat = d_bios->bios_call_i86(PC, &(m_regs.w[0]), sregs, &m_ZeroVal, &m_CarryVal); - return stat; -} - -bool i8086_common_cpu_device::call_pseudo_bios_int(int intnum) -{ - if(d_bios == NULL) return false; - bool stat; - stat = d_bios->bios_int_i86(intnum, n_regs, n_sregs, &m_ZeroVal, &m_CarryVal); - return stat; -} - -void i8086_common_cpu_device::reset() -{ - m_ZeroVal = 1; - m_ParityVal = 1; - m_regs.w[AX] = 0; - m_regs.w[CX] = 0; - m_regs.w[DX] = 0; - m_regs.w[BX] = 0; - m_regs.w[SP] = 0; - m_regs.w[BP] = 0; - m_regs.w[SI] = 0; - m_regs.w[DI] = 0; - m_sregs[ES] = 0; - m_sregs[CS] = 0xffff; - m_sregs[SS] = 0; - m_sregs[DS] = 0; - m_ip = 0; - m_prev_ip = 0; - m_SignVal = 0; - m_AuxVal = 0; - m_OverVal = 0; - m_CarryVal = 0; - m_TF = 0; - m_IF = 0; - m_DF = 0; - m_IOPL = 3; // 8086 IOPL always 3 - m_NT = 1; // 8086 NT always 1 - m_MF = 1; // 8086 MF always 1, 80286 always 0 - m_int_vector = 0; - m_pending_irq = 0; - m_nmi_state = 0; - m_irq_state = 0; - m_no_interrupt = 0; - m_fire_trap = 0; - m_prefix_seg = 0; - m_seg_prefix = false; - m_seg_prefix_next = false; - m_ea = 0; - m_eo = 0; - m_e16 = 0; - m_modrm = 0; - m_dst = 0; - m_src = 0; - m_halt = false; - m_lock = false; -} - - - -void i8086_common_cpu_device::interrupt(int int_num, int trap) -{ - PUSH( CompressFlags() ); - m_TF = m_IF = 0; - - if (int_num == -1) { - int_num = standard_irq_callback(0); - - m_irq_state = CLEAR_LINE; - m_pending_irq &= ~INT_IRQ; - } - - PUSH(m_sregs[CS]); - PUSH(m_ip); - - if(call_pseudo_bios_int(int_num)) { - // i_iret - m_ip = POP(); - m_sregs[CS] = POP(); - i_popf(); - CLK(IRET); - return; - } - uint16_t dest_off = read_word( int_num * 4 + 0 ); - uint16_t dest_seg = read_word( int_num * 4 + 2 ); - m_ip = dest_off; - m_sregs[CS] = dest_seg; -} - - -void i8086_common_cpu_device::execute_set_input( int inptnum, int state ) -{ - if (inptnum == INPUT_LINE_NMI) - { - if ( m_nmi_state == state ) - { - return; - } - m_nmi_state = state; - if (state != CLEAR_LINE) - { - m_pending_irq |= NMI_IRQ; - } - } - else if (inptnum == INPUT_LINE_TEST) - { - m_test_state = state; - } - else - { - m_irq_state = state; - if (state == CLEAR_LINE) - { - m_pending_irq &= ~INT_IRQ; - } - else - { - m_pending_irq |= INT_IRQ; - } - } -} - -offs_t i8086_common_cpu_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) -{ - extern int i386_dasm_one(std::ostream &stream, offs_t eip, const uint8_t *oprom, int mode); - return i386_dasm_one(stream, pc, oprom, 1); -} - -uint8_t i8086_common_cpu_device::read_port_byte(uint16_t port) -{ - return d_io->read_io8(port); -} - -uint16_t i8086_common_cpu_device::read_port_word(uint16_t port) -{ - return d_io->read_io16(port); -} - -void i8086_common_cpu_device::write_port_byte(uint16_t port, uint8_t data) -{ - d_io->write_io8(port, data); -} - -void i8086_common_cpu_device::write_port_word(uint16_t port, uint16_t data) -{ - d_io->write_io16(port, data); -} - - -uint32_t i8086_common_cpu_device::calc_addr(int seg, uint16_t offset, int size, int op, bool override) -{ - if ( m_seg_prefix && (seg==DS || seg==SS) && override ) - { - return (m_sregs[m_prefix_seg] << 4) + offset; - } - else - { - return (m_sregs[seg] << 4) + offset; - } -} - -bool i8086_common_cpu_device::common_op(uint8_t op) -{ - switch(op) - { - case 0x00: // i_add_br8 - DEF_br8(); - set_CFB(ADDB()); - PutbackRMByte(m_dst); - CLKM(ALU_RR8,ALU_MR8); - break; - - case 0x01: // i_add_wr16 - DEF_wr16(); - set_CFW(ADDX()); - PutbackRMWord(m_dst); - CLKM(ALU_RR16,ALU_MR16); - break; - - case 0x02: // i_add_r8b - DEF_r8b(); - set_CFB(ADDB()); - RegByte(m_dst); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x03: // i_add_r16w - DEF_r16w(); - set_CFW(ADDX()); - RegWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x04: // i_add_ald8 - DEF_ald8(); - set_CFB(ADDB()); - m_regs.b[AL] = m_dst; - CLK(ALU_RI8); - break; - - case 0x05: // i_add_axd16 - DEF_axd16(); - set_CFW(ADDX()); - m_regs.w[AX] = m_dst; - CLK(ALU_RI16); - break; - - case 0x06: // i_push_es - PUSH(m_sregs[ES]); - CLK(PUSH_SEG); - break; - - case 0x07: // i_pop_es - m_sregs[ES] = POP(); - CLK(POP_SEG); - break; - - case 0x08: // i_or_br8 - DEF_br8(); - ORB(); - PutbackRMByte(m_dst); - CLKM(ALU_RR8,ALU_MR8); - break; - - case 0x09: // i_or_wr16 - DEF_wr16(); - ORW(); - PutbackRMWord(m_dst); - CLKM(ALU_RR16,ALU_MR16); - break; - - case 0x0a: // i_or_r8b - DEF_r8b(); - ORB(); - RegByte(m_dst); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x0b: // i_or_r16w - DEF_r16w(); - ORW(); - RegWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x0c: // i_or_ald8 - DEF_ald8(); - ORB(); - m_regs.b[AL] = m_dst; - CLK(ALU_RI8); - break; - - case 0x0d: // i_or_axd16 - DEF_axd16(); - ORW(); - m_regs.w[AX] = m_dst; - CLK(ALU_RI16); - break; - - case 0x0e: // i_push_cs - PUSH(m_sregs[CS]); - CLK(PUSH_SEG); - break; - - case 0x10: // i_adc_br8 - { - DEF_br8(); - m_src += CF ? 1 : 0; - uint32_t tmpcf = ADDB(); - PutbackRMByte(m_dst); - set_CFB(tmpcf); - CLKM(ALU_RR8,ALU_MR8); - break; - } - case 0x11: // i_adc_wr16 - { - DEF_wr16(); - m_src += CF ? 1 : 0; - uint32_t tmpcf = ADDX(); - PutbackRMWord(m_dst); - set_CFW(tmpcf); - CLKM(ALU_RR16,ALU_MR16); - break; - } - - case 0x12: // i_adc_r8b - DEF_r8b(); - m_src += CF ? 1 : 0; - set_CFB(ADDB()); - RegByte(m_dst); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x13: // i_adc_r16w - DEF_r16w(); - m_src += CF ? 1 : 0; - set_CFW(ADDX()); - RegWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x14: // i_adc_ald8 - DEF_ald8(); - m_src += CF ? 1 : 0; - set_CFB(ADDB()); - m_regs.b[AL] = m_dst; - CLK(ALU_RI8); - break; - - case 0x15: // i_adc_axd16 - DEF_axd16(); - m_src += CF ? 1 : 0; - set_CFW(ADDX()); - m_regs.w[AX] = m_dst; - CLK(ALU_RI16); - break; - - case 0x16: // i_push_ss - PUSH(m_sregs[SS]); - CLK(PUSH_SEG); - break; - - case 0x17: // i_pop_ss - m_sregs[SS] = POP(); - CLK(POP_SEG); - m_no_interrupt = 1; - break; - - case 0x18: // i_sbb_br8 - { - uint32_t tmpcf; - DEF_br8(); - m_src += CF ? 1 : 0; - tmpcf = SUBB(); - PutbackRMByte(m_dst); - set_CFB(tmpcf); - CLKM(ALU_RR8,ALU_MR8); - break; - } - - case 0x19: // i_sbb_wr16 - { - uint32_t tmpcf; - DEF_wr16(); - m_src += CF ? 1 : 0; - tmpcf = SUBX(); - PutbackRMWord(m_dst); - set_CFW(tmpcf); - CLKM(ALU_RR16,ALU_MR16); - break; - } - - case 0x1a: // i_sbb_r8b - DEF_r8b(); - m_src += CF ? 1 : 0; - set_CFB(SUBB()); - RegByte(m_dst); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x1b: // i_sbb_r16w - DEF_r16w(); - m_src += CF ? 1 : 0; - set_CFW(SUBX()); - RegWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x1c: // i_sbb_ald8 - DEF_ald8(); - m_src += CF ? 1 : 0; - set_CFB(SUBB()); - m_regs.b[AL] = m_dst; - CLK(ALU_RI8); - break; - - case 0x1d: // i_sbb_axd16 - DEF_axd16(); - m_src += CF ? 1 : 0; - set_CFW(SUBX()); - m_regs.w[AX] = m_dst; - CLK(ALU_RI16); - break; - - case 0x1e: // i_push_ds - PUSH(m_sregs[DS]); - CLK(PUSH_SEG); - break; - - case 0x1f: // i_pop_ds - m_sregs[DS] = POP(); - CLK(POP_SEG); - break; - - - case 0x20: // i_and_br8 - DEF_br8(); - ANDB(); - PutbackRMByte(m_dst); - CLKM(ALU_RR8,ALU_MR8); - break; - - case 0x21: // i_and_wr16 - DEF_wr16(); - ANDX(); - PutbackRMWord(m_dst); - CLKM(ALU_RR16,ALU_MR16); - break; - - case 0x22: // i_and_r8b - DEF_r8b(); - ANDB(); - RegByte(m_dst); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x23: // i_and_r16w - DEF_r16w(); - ANDX(); - RegWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x24: // i_and_ald8 - DEF_ald8(); - ANDB(); - m_regs.b[AL] = m_dst; - CLK(ALU_RI8); - break; - - case 0x25: // i_and_axd16 - DEF_axd16(); - ANDX(); - m_regs.w[AX] = m_dst; - CLK(ALU_RI16); - break; - - case 0x26: // i_es - m_seg_prefix_next = true; - m_prefix_seg = ES; - CLK(OVERRIDE); - break; - - case 0x27: // i_daa - ADJ4(6,0x60); - CLK(DAA); - break; - - - case 0x28: // i_sub_br8 - DEF_br8(); - set_CFB(SUBB()); - PutbackRMByte(m_dst); - CLKM(ALU_RR8,ALU_MR8); - break; - - case 0x29: // i_sub_wr16 - DEF_wr16(); - set_CFW(SUBX()); - PutbackRMWord(m_dst); - CLKM(ALU_RR16,ALU_MR16); - break; - - case 0x2a: // i_sub_r8b - DEF_r8b(); - set_CFB(SUBB()); - RegByte(m_dst); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x2b: // i_sub_r16w - DEF_r16w(); - set_CFW(SUBX()); - RegWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x2c: // i_sub_ald8 - DEF_ald8(); - set_CFB(SUBB()); - m_regs.b[AL] = m_dst; - CLK(ALU_RI8); - break; - - case 0x2d: // i_sub_axd16 - DEF_axd16(); - set_CFW(SUBX()); - m_regs.w[AX] = m_dst; - CLK(ALU_RI16); - break; - - case 0x2e: // i_cs - m_seg_prefix_next = true; - m_prefix_seg = CS; - CLK(OVERRIDE); - break; - - case 0x2f: // i_das - ADJ4(-6,-0x60); - CLK(DAS); - break; - - - case 0x30: // i_xor_br8 - DEF_br8(); - XORB(); - PutbackRMByte(m_dst); - CLKM(ALU_RR8,ALU_MR8); - break; - - case 0x31: // i_xor_wr16 - DEF_wr16(); - XORW(); - PutbackRMWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x32: // i_xor_r8b - DEF_r8b(); - XORB(); - RegByte(m_dst); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x33: // i_xor_r16w - DEF_r16w(); - XORW(); - RegWord(m_dst); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x34: // i_xor_ald8 - DEF_ald8(); - XORB(); - m_regs.b[AL] = m_dst; - CLK(ALU_RI8); - break; - - case 0x35: // i_xor_axd16 - DEF_axd16(); - XORW(); - m_regs.w[AX] = m_dst; - CLK(ALU_RI16); - break; - - case 0x36: // i_ss - m_seg_prefix_next = true; - m_prefix_seg = SS; - CLK(OVERRIDE); - break; - - case 0x37: // i_aaa - ADJB(6, (m_regs.b[AL] > 0xf9) ? 2 : 1); - CLK(AAA); - break; - - - case 0x38: // i_cmp_br8 - DEF_br8(); - set_CFB(SUBB()); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x39: // i_cmp_wr16 - DEF_wr16(); - set_CFW(SUBX()); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x3a: // i_cmp_r8b - DEF_r8b(); - set_CFB(SUBB()); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x3b: // i_cmp_r16w - DEF_r16w(); - set_CFW(SUBX()); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x3c: // i_cmp_ald8 - DEF_ald8(); - set_CFB(SUBB()); - CLK(ALU_RI8); - break; - - case 0x3d: // i_cmp_axd16 - DEF_axd16(); - set_CFW(SUBX()); - CLK(ALU_RI16); - break; - - case 0x3e: // i_ds - m_seg_prefix_next = true; - m_prefix_seg = DS; - CLK(OVERRIDE); - break; - - case 0x3f: // i_aas - ADJB(-6, (m_regs.b[AL] < 6) ? -2 : -1); - CLK(AAS); - break; - - - case 0x40: // i_inc_ax - IncWordReg(AX); - CLK(INCDEC_R16); - break; - - case 0x41: // i_inc_cx - IncWordReg(CX); - CLK(INCDEC_R16); - break; - - case 0x42: // i_inc_dx - IncWordReg(DX); - CLK(INCDEC_R16); - break; - - case 0x43: // i_inc_bx - IncWordReg(BX); - CLK(INCDEC_R16); - break; - - case 0x44: // i_inc_sp - IncWordReg(SP); - CLK(INCDEC_R16); - break; - - case 0x45: // i_inc_bp - IncWordReg(BP); - CLK(INCDEC_R16); - break; - - case 0x46: // i_inc_si - IncWordReg(SI); - CLK(INCDEC_R16); - break; - - case 0x47: // i_inc_di - IncWordReg(DI); - CLK(INCDEC_R16); - break; - - - case 0x48: // i_dec_ax - DecWordReg(AX); - CLK(INCDEC_R16); - break; - - case 0x49: // i_dec_cx - DecWordReg(CX); - CLK(INCDEC_R16); - break; - - case 0x4a: // i_dec_dx - DecWordReg(DX); - CLK(INCDEC_R16); - break; - - case 0x4b: // i_dec_bx - DecWordReg(BX); - CLK(INCDEC_R16); - break; - - case 0x4c: // i_dec_sp - DecWordReg(SP); - CLK(INCDEC_R16); - break; - - case 0x4d: // i_dec_bp - DecWordReg(BP); - CLK(INCDEC_R16); - break; - - case 0x4e: // i_dec_si - DecWordReg(SI); - CLK(INCDEC_R16); - break; - - case 0x4f: // i_dec_di - DecWordReg(DI); - CLK(INCDEC_R16); - break; - - - case 0x50: // i_push_ax - PUSH(m_regs.w[AX]); - CLK(PUSH_R16); - break; - - case 0x51: // i_push_cx - PUSH(m_regs.w[CX]); - CLK(PUSH_R16); - break; - - case 0x52: // i_push_dx - PUSH(m_regs.w[DX]); - CLK(PUSH_R16); - break; - - case 0x53: // i_push_bx - PUSH(m_regs.w[BX]); - CLK(PUSH_R16); - break; - - case 0x54: // i_push_sp - PUSH(m_regs.w[SP]-2); - CLK(PUSH_R16); - break; - - case 0x55: // i_push_bp - PUSH(m_regs.w[BP]); - CLK(PUSH_R16); - break; - - case 0x56: // i_push_si - PUSH(m_regs.w[SI]); - CLK(PUSH_R16); - break; - - case 0x57: // i_push_di - PUSH(m_regs.w[DI]); - CLK(PUSH_R16); - break; - - - case 0x58: // i_pop_ax - m_regs.w[AX] = POP(); - CLK(POP_R16); - break; - - case 0x59: // i_pop_cx - m_regs.w[CX] = POP(); - CLK(POP_R16); - break; - - case 0x5a: // i_pop_dx - m_regs.w[DX] = POP(); - CLK(POP_R16); - break; - - case 0x5b: // i_pop_bx - m_regs.w[BX] = POP(); - CLK(POP_R16); - break; - - case 0x5c: // i_pop_sp - m_regs.w[SP] = POP(); - CLK(POP_R16); - break; - - case 0x5d: // i_pop_bp - m_regs.w[BP] = POP(); - CLK(POP_R16); - break; - - case 0x5e: // i_pop_si - m_regs.w[SI] = POP(); - CLK(POP_R16); - break; - - case 0x5f: // i_pop_di - m_regs.w[DI] = POP(); - CLK(POP_R16); - break; - -// 8086 'invalid opcodes', as documented at http://www.os2museum.com/wp/?p=2147 and tested on real hardware -// - 0x60 - 0x6f are aliases to 0x70 - 0x7f. -// - 0xc0, 0xc1, 0xc8, 0xc9 are also aliases where the CPU ignores BIT 1 (*). -// - 0xf1 is an alias to 0xf0. -// -// Instructions are used in the boot sector for some versions of -// MS-DOS (e.g. the DEC Rainbow-100 version of DOS 2.x) - case 0x60: - case 0x70: // i_jo - JMP( OF); - break; - - case 0x61: - case 0x71: // i_jno - JMP(!OF); - break; - - case 0x62: - case 0x72: // i_jc - JMP( CF); - break; - - case 0x63: - case 0x73: // i_jnc - JMP(!CF); - break; - - case 0x64: - case 0x74: // i_jz - JMP( ZF); - break; - - case 0x65: - case 0x75: // i_jnz - JMP(!ZF); - break; - - case 0x66: - case 0x76: // i_jce - JMP(CF || ZF); - break; - - case 0x67: - case 0x77: // i_jnce - JMP(!(CF || ZF)); - break; - - case 0x68: - case 0x78: // i_js - JMP( SF); - break; - - case 0x69: - case 0x79: // i_jns - JMP(!SF); - break; - - case 0x6a: - case 0x7a: // i_jp - JMP( PF); - break; - - case 0x6b: - case 0x7b: // i_jnp - JMP(!PF); - break; - - case 0x6c: - case 0x7c: // i_jl - JMP((SF!=OF)&&(!ZF)); - break; - - case 0x6d: - case 0x7d: // i_jnl - JMP(SF==OF); - break; - - case 0x6e: - case 0x7e: // i_jle - JMP((ZF)||(SF!=OF)); - break; - - case 0x6f: - case 0x7f: // i_jnle - JMP((SF==OF)&&(!ZF)); - break; - - - case 0x80: // i_80pre - { - uint32_t tmpcf; - m_modrm = fetch(); - m_dst = GetRMByte(); - m_src = fetch(); - if (m_modrm >=0xc0 ) { CLK(ALU_RI8); } - else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI8_RO); } - else { CLK(ALU_MI8); } - switch (m_modrm & 0x38) - { - case 0x00: set_CFB(ADDB()); PutbackRMByte(m_dst); break; - case 0x08: ORB(); PutbackRMByte(m_dst); break; - case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break; - case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break; - case 0x20: ANDB(); PutbackRMByte(m_dst); break; - case 0x28: set_CFB(SUBB()); PutbackRMByte(m_dst); break; - case 0x30: XORB(); PutbackRMByte(m_dst); break; - case 0x38: set_CFB(SUBB()); break; /* CMP */ - } - break; - } - - - case 0x81: // i_81pre - { - uint32_t tmpcf; - m_modrm = fetch(); - m_dst = GetRMWord(); - m_src = fetch_word(); - if (m_modrm >=0xc0 ) { CLK(ALU_RI16); } - else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI16_RO); } - else { CLK(ALU_MI16); } - switch (m_modrm & 0x38) - { - case 0x00: set_CFW(ADDX()); PutbackRMWord(m_dst); break; - case 0x08: ORW(); PutbackRMWord(m_dst); break; - case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break; - case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break; - case 0x20: ANDX(); PutbackRMWord(m_dst); break; - case 0x28: set_CFW(SUBX()); PutbackRMWord(m_dst); break; - case 0x30: XORW(); PutbackRMWord(m_dst); break; - case 0x38: set_CFW(SUBX()); break; /* CMP */ - } - break; - } - - - case 0x82: // i_82pre - { - uint32_t tmpcf; - m_modrm = fetch(); - m_dst = GetRMByte(); - m_src = (int8_t)fetch(); - if (m_modrm >=0xc0 ) { CLK(ALU_RI8); } - else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI8_RO); } - else { CLK(ALU_MI8); } - switch (m_modrm & 0x38) - { - case 0x00: set_CFB(ADDB()); PutbackRMByte(m_dst); break; - case 0x08: ORB(); PutbackRMByte(m_dst); break; - case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break; - case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break; - case 0x20: ANDB(); PutbackRMByte(m_dst); break; - case 0x28: set_CFB(SUBB()); PutbackRMByte(m_dst); break; - case 0x30: XORB(); PutbackRMByte(m_dst); break; - case 0x38: set_CFB(SUBB()); break; /* CMP */ - } - break; - } - - - case 0x83: // i_83pre - { - uint32_t tmpcf; - m_modrm = fetch(); - m_dst = GetRMWord(); - m_src = (uint16_t)((int16_t)((int8_t)fetch())); - if (m_modrm >=0xc0 ) { CLK(ALU_R16I8); } - else if ((m_modrm & 0x38)==0x38) { CLK(ALU_M16I8_RO); } - else { CLK(ALU_M16I8); } - switch (m_modrm & 0x38) - { - case 0x00: set_CFW(ADDX()); PutbackRMWord(m_dst); break; - case 0x08: ORW(); PutbackRMWord(m_dst); break; - case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break; - case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break; - case 0x20: ANDX(); PutbackRMWord(m_dst); break; - case 0x28: set_CFW(SUBX()); PutbackRMWord(m_dst); break; - case 0x30: XORW(); PutbackRMWord(m_dst); break; - case 0x38: set_CFW(SUBX()); break; /* CMP */ - } - break; - } - - - case 0x84: // i_test_br8 - DEF_br8(); - ANDB(); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x85: // i_test_wr16 - DEF_wr16(); - ANDX(); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x86: // i_xchg_br8 - DEF_br8(); - RegByte(m_dst); - PutbackRMByte(m_src); - CLKM(XCHG_RR8,XCHG_RM8); - break; - - case 0x87: // i_xchg_wr16 - DEF_wr16(); - RegWord(m_dst); - PutbackRMWord(m_src); - CLKM(XCHG_RR16,XCHG_RM16); - break; - - - case 0x88: // i_mov_br8 - m_modrm = fetch(); - m_src = RegByte(); - PutRMByte(m_src); - CLKM(ALU_RR8,ALU_MR8); - break; - - case 0x89: // i_mov_wr16 - m_modrm = fetch(); - m_src = RegWord(); - PutRMWord(m_src); - CLKM(ALU_RR16,ALU_MR16); - break; - - case 0x8a: // i_mov_r8b - m_modrm = fetch(); - m_src = GetRMByte(); - RegByte(m_src); - CLKM(ALU_RR8,ALU_RM8); - break; - - case 0x8b: // i_mov_r16w - m_modrm = fetch(); - m_src = GetRMWord(); - RegWord(m_src); - CLKM(ALU_RR16,ALU_RM16); - break; - - case 0x8c: // i_mov_wsreg - m_modrm = fetch(); - PutRMWord(m_sregs[(m_modrm & 0x18) >> 3]); // confirmed on hw: modrm bit 5 ignored - CLKM(MOV_RS,MOV_MS); - break; - - case 0x8d: // i_lea - m_modrm = fetch(); - get_ea(0, I8086_NONE); - RegWord(m_eo); - CLK(LEA); - break; - - case 0x8e: // i_mov_sregw - m_modrm = fetch(); - m_src = GetRMWord(); - m_sregs[(m_modrm & 0x18) >> 3] = m_src; // confirmed on hw: modrm bit 5 ignored - CLKM(MOV_SR,MOV_SM); - m_no_interrupt = 1; // Disable IRQ after load segment register. - break; - - case 0x8f: // i_popw - m_modrm = fetch(); - PutRMWord( POP() ); - CLKM(POP_R16,POP_M16); - break; - - case 0x90: // i_nop - CLK(NOP); - break; - - case 0x91: // i_xchg_axcx - XchgAXReg(CX); - CLK(XCHG_AR16); - break; - - case 0x92: // i_xchg_axdx - XchgAXReg(DX); - CLK(XCHG_AR16); - break; - - case 0x93: // i_xchg_axbx - XchgAXReg(BX); - CLK(XCHG_AR16); - break; - - case 0x94: // i_xchg_axsp - XchgAXReg(SP); - CLK(XCHG_AR16); - break; - - case 0x95: // i_xchg_axbp - XchgAXReg(BP); - CLK(XCHG_AR16); - break; - - case 0x96: // i_xchg_axsi - XchgAXReg(SI); - CLK(XCHG_AR16); - break; - - case 0x97: // i_xchg_axdi - XchgAXReg(DI); - CLK(XCHG_AR16); - break; - - - case 0x98: // i_cbw - m_regs.b[AH] = (m_regs.b[AL] & 0x80) ? 0xff : 0; - CLK(CBW); - break; - - case 0x99: // i_cwd - m_regs.w[DX] = (m_regs.b[AH] & 0x80) ? 0xffff : 0; - CLK(CWD); - break; - - case 0x9a: // i_call_far - { - uint16_t tmp = fetch_word(); - uint16_t tmp2 = fetch_word(); - PUSH(m_sregs[CS]); - PUSH(m_ip); - m_ip = tmp; - m_sregs[CS] = tmp2; - if(call_pseudo_bios(((m_sregs[CS] << 4) + tmp) & m_amask)) { - m_ip = POP(); - m_sregs[CS] = POP(); - CLK(RET_FAR); - } - CLK(CALL_FAR); - } - break; - - case 0x9b: // i_wait - // Wait for assertion of /TEST - if (m_test_state == 0) - { - m_icount = 0; - m_ip--; - } - else - CLK(WAIT); - break; - - case 0x9c: // i_pushf - PUSH( CompressFlags() ); - CLK(PUSHF); - break; - - case 0x9d: // i_popf - i_popf(); - break; - - case 0x9e: // i_sahf - { - uint32_t tmp = (CompressFlags() & 0xff00) | (m_regs.b[AH] & 0xd5); - ExpandFlags(tmp); - CLK(SAHF); - } - break; - - case 0x9f: // i_lahf - m_regs.b[AH] = CompressFlags(); - CLK(LAHF); - break; - - - case 0xa0: // i_mov_aldisp - { - uint32_t addr = fetch_word(); - m_regs.b[AL] = GetMemB(DS, addr); - CLK(MOV_AM8); - } - break; - - case 0xa1: // i_mov_axdisp - { - uint32_t addr = fetch_word(); - m_regs.w[AX] = GetMemW(DS, addr); - CLK(MOV_AM16); - } - break; - - case 0xa2: // i_mov_dispal - { - uint32_t addr = fetch_word(); - PutMemB(DS, addr, m_regs.b[AL]); - CLK(MOV_MA8); - } - break; - - case 0xa3: // i_mov_dispax - { - uint32_t addr = fetch_word(); - PutMemW(DS, addr, m_regs.w[AX]); - CLK(MOV_MA16); - } - break; - - case 0xa4: // i_movsb - i_movsb(); - break; - - case 0xa5: // i_movsw - i_movsw(); - break; - - case 0xa6: // i_cmpsb - i_cmpsb(); - break; - - case 0xa7: // i_cmpsw - i_cmpsw(); - break; - - - case 0xa8: // i_test_ald8 - DEF_ald8(); - ANDB(); - CLK(ALU_RI8); - break; - - case 0xa9: // i_test_axd16 - DEF_axd16(); - ANDX(); - CLK(ALU_RI16); - break; - - case 0xaa: // i_stosb - i_stosb(); - break; - - case 0xab: // i_stosw - i_stosw(); - break; - - case 0xac: // i_lodsb - i_lodsb(); - break; - - case 0xad: // i_lodsw - i_lodsw(); - break; - - case 0xae: // i_scasb - i_scasb(); - break; - - case 0xaf: // i_scasw - i_scasw(); - break; - - - case 0xb0: // i_mov_ald8 - m_regs.b[AL] = fetch(); - CLK(MOV_RI8); - break; - - case 0xb1: // i_mov_cld8 - m_regs.b[CL] = fetch(); - CLK(MOV_RI8); - break; - - case 0xb2: // i_mov_dld8 - m_regs.b[DL] = fetch(); - CLK(MOV_RI8); - break; - - case 0xb3: // i_mov_bld8 - m_regs.b[BL] = fetch(); - CLK(MOV_RI8); - break; - - case 0xb4: // i_mov_ahd8 - m_regs.b[AH] = fetch(); - CLK(MOV_RI8); - break; - - case 0xb5: // i_mov_chd8 - m_regs.b[CH] = fetch(); - CLK(MOV_RI8); - break; - - case 0xb6: // i_mov_dhd8 - m_regs.b[DH] = fetch(); - CLK(MOV_RI8); - break; - - case 0xb7: // i_mov_bhd8 - m_regs.b[BH] = fetch(); - CLK(MOV_RI8); - break; - - - case 0xb8: // i_mov_axd16 - m_regs.b[AL] = fetch(); - m_regs.b[AH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xb9: // i_mov_cxd16 - m_regs.b[CL] = fetch(); - m_regs.b[CH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xba: // i_mov_dxd16 - m_regs.b[DL] = fetch(); - m_regs.b[DH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xbb: // i_mov_bxd16 - m_regs.b[BL] = fetch(); - m_regs.b[BH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xbc: // i_mov_spd16 - m_regs.b[SPL] = fetch(); - m_regs.b[SPH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xbd: // i_mov_bpd16 - m_regs.b[BPL] = fetch(); - m_regs.b[BPH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xbe: // i_mov_sid16 - m_regs.b[SIL] = fetch(); - m_regs.b[SIH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xbf: // i_mov_did16 - m_regs.b[DIL] = fetch(); - m_regs.b[DIH] = fetch(); - CLK(MOV_RI16); - break; - - case 0xc0: // 0xc0 is 0xc2 - see (*) - case 0xc2: // i_ret_d16 - { - uint32_t count = fetch_word(); - m_ip = POP(); - m_regs.w[SP] += count; - CLK(RET_NEAR_IMM); - } - break; - - case 0xc1: // 0xc1 is 0xc3 - see (*) - case 0xc3: // i_ret - m_ip = POP(); - CLK(RET_NEAR); - break; - - case 0xc4: // i_les_dw - m_modrm = fetch(); - RegWord( GetRMWord() ); - m_sregs[ES] = GetnextRMWord(); - CLK(LOAD_PTR); - break; - - case 0xc5: // i_lds_dw - m_modrm = fetch(); - RegWord( GetRMWord() ); - m_sregs[DS] = GetnextRMWord(); - CLK(LOAD_PTR); - break; - - case 0xc6: // i_mov_bd8 - m_modrm = fetch(); - PutImmRMByte(); - CLKM(MOV_RI8,MOV_MI8); - break; - - case 0xc7: // i_mov_wd16 - m_modrm = fetch(); - PutImmRMWord(); - CLKM(MOV_RI16,MOV_MI16); - break; - - case 0xc8: // 0xc8 = 0xca - see (*) - case 0xca: // i_retf_d16 - { - uint32_t count = fetch_word(); - m_ip = POP(); - m_sregs[CS] = POP(); - m_regs.w[SP] += count; - CLK(RET_FAR_IMM); - } - break; - - case 0xc9: // 0xc9 = 0xcb - see (*) - case 0xcb: // i_retf - m_ip = POP(); - m_sregs[CS] = POP(); - CLK(RET_FAR); - break; - - case 0xcc: // i_int3 - interrupt(3, 0); - CLK(INT3); - break; - - case 0xcd: // i_int - { - int int_num = fetch(); - interrupt(int_num, 0); - CLK(INT_IMM); - } - break; - - case 0xce: // i_into - if (OF) - { - interrupt(4, 0); - CLK(INTO_T); - } - else - CLK(INTO_NT); - break; - - case 0xcf: // i_iret - m_ip = POP(); - m_sregs[CS] = POP(); - i_popf(); - CLK(IRET); - break; - - case 0xd0: // i_rotshft_b - m_modrm = fetch(); - m_src = GetRMByte(); - m_dst = m_src; - CLKM(ROT_REG_1,ROT_M8_1); - switch ( m_modrm & 0x38 ) - { - case 0x00: ROL_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break; - case 0x08: ROR_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break; - case 0x10: ROLC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break; - case 0x18: RORC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break; - case 0x30: - case 0x20: SHL_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break; - case 0x28: SHR_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break; - case 0x38: SHRA_BYTE(1); m_OverVal = 0; break; - } - break; - - case 0xd1: // i_rotshft_w - m_modrm = fetch(); - m_src = GetRMWord(); - m_dst = m_src; - CLKM(ROT_REG_1,ROT_M8_1); - switch ( m_modrm & 0x38 ) - { - case 0x00: ROL_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break; - case 0x08: ROR_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break; - case 0x10: ROLC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break; - case 0x18: RORC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break; - case 0x30: - case 0x20: SHL_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000; break; - case 0x28: SHR_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000; break; - case 0x38: SHRA_WORD(1); m_OverVal = 0; break; - } - break; - - case 0xd4: // i_aam - { - uint8_t base = fetch(); - if(!base) - { - interrupt(0); - break; - } - m_regs.b[AH] = m_regs.b[AL] / base; - m_regs.b[AL] %= base; - set_SZPF_Word(m_regs.w[AX]); - CLK(AAM); - break; - } - - case 0xd5: // i_aad - { - uint8_t base = fetch(); - m_regs.b[AL] = m_regs.b[AH] * base + m_regs.b[AL]; - m_regs.b[AH] = 0; - set_SZPF_Byte(m_regs.b[AL]); - CLK(AAD); - break; - } - - case 0xd6: // i_salc - m_regs.b[AL] = (CF ? 0xff : 0); - CLK(ALU_RR8); // is sbb al,al - break; - - case 0xd7: // i_trans - m_regs.b[AL] = GetMemB( DS, m_regs.w[BX] + m_regs.b[AL] ); - CLK(XLAT); - break; - - case 0xd8: // i_esc - case 0xd9: - case 0xda: - case 0xdb: - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: - m_modrm = fetch(); - GetRMByte(); - CLK(NOP); - logerror("%06x: Unimplemented floating point escape %02x%02x\n", pc(), op, m_modrm); - break; - - - case 0xe0: // i_loopne - { - int8_t disp = (int8_t)fetch(); - - m_regs.w[CX]--; - if (!ZF && m_regs.w[CX]) - { - m_ip = m_ip + disp; - CLK(LOOP_T); - } - else - CLK(LOOP_NT); - } - break; - - case 0xe1: // i_loope - { - int8_t disp = (int8_t)fetch(); - - m_regs.w[CX]--; - if (ZF && m_regs.w[CX]) - { - m_ip = m_ip + disp; - CLK(LOOPE_T); - } - else - CLK(LOOPE_NT); - } - break; - - case 0xe2: // i_loop - { - int8_t disp = (int8_t)fetch(); - - m_regs.w[CX]--; - if (m_regs.w[CX]) - { - m_ip = m_ip + disp; - CLK(LOOP_T); - } - else - CLK(LOOP_NT); - } - break; - - case 0xe3: // i_jcxz - { - int8_t disp = (int8_t)fetch(); - - if (m_regs.w[CX] == 0) - { - m_ip = m_ip + disp; - CLK(JCXZ_T); - } - else - CLK(JCXZ_NT); - } - break; - - case 0xe4: // i_inal - if (m_lock) m_lock_handler(1); - m_regs.b[AL] = read_port_byte( fetch() ); - if (m_lock) { m_lock_handler(0); m_lock = false; } - CLK(IN_IMM8); - break; - - case 0xe5: // i_inax - { - uint8_t port = fetch(); - - m_regs.w[AX] = read_port_word(port); - CLK(IN_IMM16); - } - break; - - case 0xe6: // i_outal - write_port_byte( fetch(), m_regs.b[AL]); - CLK(OUT_IMM8); - break; - - case 0xe7: // i_outax - { - uint8_t port = fetch(); - - write_port_word(port, m_regs.w[AX]); - CLK(OUT_IMM16); - } - break; - - - case 0xe8: // i_call_d16 - { - int16_t tmp = (int16_t)fetch_word(); - PUSH(m_ip); - if(call_pseudo_bios((m_pc + tmp) & m_amask)) { - CLK(CALL_NEAR); - POP(m_ip); - CLK(RET_NEAR); - return true; - } - m_ip = m_ip + tmp; - CLK(CALL_NEAR); - } - break; - - case 0xe9: // i_jmp_d16 - { - int16_t offset = (int16_t)fetch_word(); - m_ip += offset; - CLK(JMP_NEAR); - } - break; - - case 0xea: // i_jmp_far - { - uint16_t tmp = fetch_word(); - uint16_t tmp1 = fetch_word(); - - m_sregs[CS] = tmp1; - m_ip = tmp; - CLK(JMP_FAR); - } - break; - - case 0xeb: // i_jmp_d8 - { - int tmp = (int)((int8_t)fetch()); - - CLK(JMP_SHORT); - if (tmp==-2 && m_no_interrupt==0 && (m_pending_irq==0) && m_icount>0) - { - m_icount%=12; /* cycle skip */ - } - m_ip = (uint16_t)(m_ip+tmp); - } - break; - - case 0xec: // i_inaldx - m_regs.b[AL] = read_port_byte(m_regs.w[DX]); - CLK(IN_DX8); - break; - - case 0xed: // i_inaxdx - { - uint32_t port = m_regs.w[DX]; - - m_regs.w[AX] = read_port_word(port); - CLK(IN_DX16); - } - break; - - case 0xee: // i_outdxal - write_port_byte(m_regs.w[DX], m_regs.b[AL]); - CLK(OUT_DX8); - break; - - case 0xef: // i_outdxax - { - uint32_t port = m_regs.w[DX]; - - write_port_word(port, m_regs.w[AX]); - CLK(OUT_DX16); - } - break; - - - case 0xf0: // i_lock - case 0xf1: // 0xf1 is 0xf0; verified on real CPU - logerror("%06x: Warning - BUSLOCK\n", pc()); - m_lock = true; - m_no_interrupt = 1; - CLK(NOP); - break; - - case 0xf2: // i_repne - { - bool invalid = false; - uint8_t next = repx_op(); - uint16_t c = m_regs.w[CX]; - - switch (next) - { - case 0xa4: CLK(OVERRIDE); if (c) do { i_movsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xa5: CLK(OVERRIDE); if (c) do { i_movsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xa6: CLK(OVERRIDE); if (c) do { i_cmpsb(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xa7: CLK(OVERRIDE); if (c) do { i_cmpsw(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xaa: CLK(OVERRIDE); if (c) do { i_stosb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xab: CLK(OVERRIDE); if (c) do { i_stosw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xac: CLK(OVERRIDE); if (c) do { i_lodsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xad: CLK(OVERRIDE); if (c) do { i_lodsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xae: CLK(OVERRIDE); if (c) do { i_scasb(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xaf: CLK(OVERRIDE); if (c) do { i_scasw(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - default: - logerror("%06x: REPNE invalid\n", pc()); - // Decrement IP so the normal instruction will be executed next - m_ip--; - invalid = true; - break; - } - if(c && !invalid) - { - if(!(ZF && ((next & 6) == 6))) - m_ip = m_prev_ip; - } - } - break; - - case 0xf3: // i_repe - { - bool invalid = false; - uint8_t next = repx_op(); - uint16_t c = m_regs.w[CX]; - - switch (next) - { - case 0xa4: CLK(OVERRIDE); if (c) do { i_movsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xa5: CLK(OVERRIDE); if (c) do { i_movsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xa6: CLK(OVERRIDE); if (c) do { i_cmpsb(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xa7: CLK(OVERRIDE); if (c) do { i_cmpsw(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xaa: CLK(OVERRIDE); if (c) do { i_stosb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xab: CLK(OVERRIDE); if (c) do { i_stosw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xac: CLK(OVERRIDE); if (c) do { i_lodsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xad: CLK(OVERRIDE); if (c) do { i_lodsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xae: CLK(OVERRIDE); if (c) do { i_scasb(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - case 0xaf: CLK(OVERRIDE); if (c) do { i_scasw(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break; - default: - logerror("%06x: REPE invalid\n", pc()); - // Decrement IP so the normal instruction will be executed next - m_ip--; - invalid = true; - break; - } - if(c && !invalid) - { - if(!(!ZF && ((next & 6) == 6))) - m_ip = m_prev_ip; - } - } - break; - - case 0xf4: // i_hlt - //logerror("%s: %06x: HALT\n", tag(), pc()); - m_icount = 0; - m_halt = true; - break; - - case 0xf5: // i_cmc - m_CarryVal = !m_CarryVal; - CLK(FLAG_OPS); - break; - - case 0xf6: // i_f6pre - { - uint32_t tmp; - uint32_t uresult,uresult2; - int32_t result,result2; - - m_modrm = fetch(); - tmp = GetRMByte(); - switch ( m_modrm & 0x38 ) - { - case 0x00: /* TEST */ - case 0x08: /* TEST (alias) */ - tmp &= fetch(); - m_CarryVal = m_OverVal = 0; - set_SZPF_Byte(tmp); - CLKM(ALU_RI8,ALU_MI8_RO); - break; - case 0x10: /* NOT */ - PutbackRMByte(~tmp); - CLKM(NEGNOT_R8,NEGNOT_M8); - break; - case 0x18: /* NEG */ - m_CarryVal = (tmp!=0) ? 1 : 0; - tmp = (~tmp)+1; - set_SZPF_Byte(tmp); - PutbackRMByte(tmp&0xff); - CLKM(NEGNOT_R8,NEGNOT_M8); - break; - case 0x20: /* MUL */ - uresult = m_regs.b[AL] * tmp; - m_regs.w[AX] = (uint16_t)uresult; - m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0; - set_ZF(m_regs.w[AX]); - CLKM(MUL_R8,MUL_M8); - break; - case 0x28: /* IMUL */ - result = (int16_t)((int8_t)m_regs.b[AL])*(int16_t)((int8_t)tmp); - m_regs.w[AX] = (uint16_t)result; - m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0; - set_ZF(m_regs.w[AX]); - CLKM(IMUL_R8,IMUL_M8); - break; - case 0x30: /* DIV */ - if (tmp) - { - uresult = m_regs.w[AX]; - uresult2 = uresult % tmp; - if ((uresult /= tmp) > 0xff) - { - interrupt(0); - } - else - { - m_regs.b[AL] = uresult; - m_regs.b[AH] = uresult2; - } - } - else - { - interrupt(0); - } - CLKM(DIV_R8,DIV_M8); - break; - case 0x38: /* IDIV */ - if (tmp) - { - result = (int16_t)m_regs.w[AX]; - result2 = result % (int16_t)((int8_t)tmp); - if ((result /= (int16_t)((int8_t)tmp)) > 0xff) - { - interrupt(0); - } - else - { - m_regs.b[AL] = result; - m_regs.b[AH] = result2; - } - } - else - { - interrupt(0); - } - CLKM(IDIV_R8,IDIV_M8); - break; - } - } - break; - - - case 0xf7: // i_f7pre - { - uint32_t tmp,tmp2; - uint32_t uresult,uresult2; - int32_t result,result2; - - m_modrm = fetch(); - tmp = GetRMWord(); - switch ( m_modrm & 0x38 ) - { - case 0x00: /* TEST */ - case 0x08: /* TEST (alias) */ - tmp2 = fetch_word(); - tmp &= tmp2; - m_CarryVal = m_OverVal = 0; - set_SZPF_Word(tmp); - CLKM(ALU_RI16,ALU_MI16_RO); - break; - case 0x10: /* NOT */ - PutbackRMWord(~tmp); - CLKM(NEGNOT_R16,NEGNOT_M16); - break; - case 0x18: /* NEG */ - m_CarryVal = (tmp!=0) ? 1 : 0; - tmp = (~tmp) + 1; - set_SZPF_Word(tmp); - PutbackRMWord(tmp); - CLKM(NEGNOT_R16,NEGNOT_M16); - break; - case 0x20: /* MUL */ - uresult = m_regs.w[AX]*tmp; - m_regs.w[AX] = uresult & 0xffff; - m_regs.w[DX] = ((uint32_t)uresult)>>16; - m_CarryVal = m_OverVal = (m_regs.w[DX] != 0) ? 1 : 0; - set_ZF(m_regs.w[AX] | m_regs.w[DX]); - CLKM(MUL_R16,MUL_M16); - break; - case 0x28: /* IMUL */ - result = (int32_t)((int16_t)m_regs.w[AX]) * (int32_t)((int16_t)tmp); - m_regs.w[AX] = result & 0xffff; - m_regs.w[DX] = result >> 16; - m_CarryVal = m_OverVal = (m_regs.w[DX] != 0) ? 1 : 0; - set_ZF(m_regs.w[AX] | m_regs.w[DX]); - CLKM(IMUL_R16,IMUL_M16); - break; - case 0x30: /* DIV */ - if (tmp) - { - uresult = (((uint32_t)m_regs.w[DX]) << 16) | m_regs.w[AX]; - uresult2 = uresult % tmp; - if ((uresult /= tmp) > 0xffff) - { - interrupt(0); - } - else - { - m_regs.w[AX] = uresult; - m_regs.w[DX] = uresult2; - } - } - else - { - interrupt(0); - } - CLKM(DIV_R16,DIV_M16); - break; - case 0x38: /* IDIV */ - if (tmp) - { - result = ((uint32_t)m_regs.w[DX] << 16) + m_regs.w[AX]; - result2 = result % (int32_t)((int16_t)tmp); - if ((result /= (int32_t)((int16_t)tmp)) > 0xffff) - { - interrupt(0); - } - else - { - m_regs.w[AX] = result; - m_regs.w[DX] = result2; - } - } - else - { - interrupt(0); - } - CLKM(IDIV_R16,IDIV_M16); - break; - } - } - break; - - - case 0xf8: // i_clc - m_CarryVal = 0; - CLK(FLAG_OPS); - break; - - case 0xf9: // i_stc - m_CarryVal = 1; - CLK(FLAG_OPS); - break; - - case 0xfa: // i_cli - m_IF = 0; - CLK(FLAG_OPS); - break; - - case 0xfb: // i_sti - m_IF = 1; - CLK(FLAG_OPS); - break; - - case 0xfc: // i_cld - m_DF = 0; - CLK(FLAG_OPS); - break; - - case 0xfd: // i_std - m_DF = 1; - CLK(FLAG_OPS); - break; - - case 0xfe: // i_fepre - { - uint32_t tmp, tmp1; - m_modrm = fetch(); - tmp = GetRMByte(); - switch ( m_modrm & 0x38 ) - { - case 0x00: /* INC */ - tmp1 = tmp+1; - m_OverVal = (tmp==0x7f); - set_AF(tmp1,tmp,1); - set_SZPF_Byte(tmp1); - PutbackRMByte(tmp1); - CLKM(INCDEC_R8,INCDEC_M8); - break; - case 0x08: /* DEC */ - tmp1 = tmp-1; - m_OverVal = (tmp==0x80); - set_AF(tmp1,tmp,1); - set_SZPF_Byte(tmp1); - PutbackRMByte(tmp1); - CLKM(INCDEC_R8,INCDEC_M8); - break; - default: - logerror("%06x: FE Pre with unimplemented mod\n", pc()); - break; - } - } - break; - - case 0xff: // i_ffpre - { - uint32_t tmp, tmp1; - m_modrm = fetch(); - tmp = GetRMWord(); - switch ( m_modrm & 0x38 ) - { - case 0x00: /* INC */ - tmp1 = tmp+1; - m_OverVal = (tmp==0x7fff); - set_AF(tmp1,tmp,1); - set_SZPF_Word(tmp1); - PutbackRMWord(tmp1); - CLKM(INCDEC_R16,INCDEC_M16); - break; - case 0x08: /* DEC */ - tmp1 = tmp-1; - m_OverVal = (tmp==0x8000); - set_AF(tmp1,tmp,1); - set_SZPF_Word(tmp1); - PutbackRMWord(tmp1); - CLKM(INCDEC_R16,INCDEC_M16); - break; - case 0x10: /* CALL */ - PUSH(m_ip); - m_ip = tmp; - if(call_pseudo_bios(m_ip & m_amask)) { - CLK(CALL_R16,CALL_M16); - m_ip = POP(); - CLK(RET_NEAR); - return true; - } - CLKM(CALL_R16,CALL_M16); - break; - case 0x18: /* CALL FAR */ - tmp1 = m_sregs[CS]; - m_sregs[CS] = GetnextRMWord(); - PUSH(tmp1); - PUSH(m_ip); - m_ip = tmp; - if(call_pseudo_bios(((m_sregs[CS] << 4) + tmp1) & m_amask)) { - CLK(CALL_M32); - m_ip = POP(); - m_sregs[CS] = POP(); - CLK(RET_FAR); - return true; - } - CLK(CALL_M32); - break; - case 0x20: /* JMP */ - m_ip = tmp; - CLKM(JMP_R16,JMP_M16); - break; - case 0x28: /* JMP FAR */ - m_ip = tmp; - m_sregs[CS] = GetnextRMWord(); - CLK(JMP_M32); - break; - case 0x30: - PUSH(tmp); - CLKM(PUSH_R16,PUSH_M16); - break; - default: - logerror("%06x: FF Pre with unimplemented mod\n", pc()); - break; - } - } - break; - default: - return false; - } - return true; -} - diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i86.h b/source/src/vm/libcpu_newdev/libcpu_i286/i86.h deleted file mode 100644 index bfbffe800..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i86.h +++ /dev/null @@ -1,452 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -#ifndef __I8086_H__ -#define __I8086_H__ - - -///////////////////////////////////////////////////////////////// - -extern const device_type I8086; -extern const device_type I8088; - -#define INPUT_LINE_INT0 INPUT_LINE_IRQ0 -#define INPUT_LINE_TEST 20 - -class DEVICE; -class BIOS; -class DEBUGGER; - - -#define MCFG_I8086_LOCK_HANDLER(_write) \ - devcb = &i8086_common_cpu_device::set_lock_handler(*device, DEVCB_##_write); - - -enum -{ - I8086_PC = STATE_GENPC, - I8086_IP = 1, I8086_AX, I8086_CX, I8086_DX, I8086_BX, I8086_SP, I8086_BP, I8086_SI, I8086_DI, - I8086_FLAGS, I8086_ES, I8086_CS, I8086_SS, I8086_DS, - I8086_VECTOR, I8086_HALT -}; - - -class i8086_common_cpu_device : public DEVICE -{ -public: - // construction/destruction - i8086_common_cpu_device(VM_TEMPLATE* prev_vm, EMU* prev_emu); - ~i8086_common_cpu_device(); - - virtual void initialize(); - virtual void reset(); - - void *get_debugger() - { - return d_debugger; - } - uint32_t get_debug_prog_addr_mask() - { - return m_amask; - } - uint32_t get_debug_data_addr_mask() - { - return m_amask; - } - 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); - - void save_state(FILEIO* state_fio); - bool load_state(FILEIO* state_fio); - - // unique function - void set_context_mem(DEVICE* device) - { - d_program = 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 - void set_extra_clock(int clock) - { - m_extra_icount += clock; - } - int get_extra_clock() - { - return m_extra_icount; - } - -protected: - enum - { - EXCEPTION, IRET, /* EXCEPTION, iret */ - INT3, INT_IMM, INTO_NT, INTO_T, /* intS */ - OVERRIDE, /* SEGMENT OVERRIDES */ - FLAG_OPS, LAHF, SAHF, /* FLAG OPERATIONS */ - AAA, AAS, AAM, AAD, /* ARITHMETIC ADJUSTS */ - DAA, DAS, /* DECIMAL ADJUSTS */ - CBW, CWD, /* SIGN EXTENSION */ - HLT, LOAD_PTR, LEA, NOP, WAIT, XLAT, /* MISC */ - - JMP_SHORT, JMP_NEAR, JMP_FAR, /* DIRECT jmpS */ - JMP_R16, JMP_M16, JMP_M32, /* INDIRECT jmpS */ - CALL_NEAR, CALL_FAR, /* DIRECT callS */ - CALL_R16, CALL_M16, CALL_M32, /* INDIRECT callS */ - RET_NEAR, RET_FAR, RET_NEAR_IMM, RET_FAR_IMM, /* RETURNS */ - JCC_NT, JCC_T, JCXZ_NT, JCXZ_T, /* CONDITIONAL jmpS */ - LOOP_NT, LOOP_T, LOOPE_NT, LOOPE_T, /* LOOPS */ - - IN_IMM8, IN_IMM16, IN_DX8, IN_DX16, /* PORT READS */ - OUT_IMM8, OUT_IMM16, OUT_DX8, OUT_DX16, /* PORT WRITES */ - - MOV_RR8, MOV_RM8, MOV_MR8, /* MOVE, 8-BIT */ - MOV_RI8, MOV_MI8, /* MOVE, 8-BIT IMMEDIATE */ - MOV_RR16, MOV_RM16, MOV_MR16, /* MOVE, 16-BIT */ - MOV_RI16, MOV_MI16, /* MOVE, 16-BIT IMMEDIATE */ - MOV_AM8, MOV_AM16, MOV_MA8, MOV_MA16, /* MOVE, al/ax MEMORY */ - MOV_SR, MOV_SM, MOV_RS, MOV_MS, /* MOVE, SEGMENT REGISTERS */ - XCHG_RR8, XCHG_RM8, /* EXCHANGE, 8-BIT */ - XCHG_RR16, XCHG_RM16, XCHG_AR16, /* EXCHANGE, 16-BIT */ - - PUSH_R16, PUSH_M16, PUSH_SEG, PUSHF, /* PUSHES */ - POP_R16, POP_M16, POP_SEG, POPF, /* POPS */ - - ALU_RR8, ALU_RM8, ALU_MR8, /* alu OPS, 8-BIT */ - ALU_RI8, ALU_MI8, ALU_MI8_RO, /* alu OPS, 8-BIT IMMEDIATE */ - ALU_RR16, ALU_RM16, ALU_MR16, /* alu OPS, 16-BIT */ - ALU_RI16, ALU_MI16, ALU_MI16_RO, /* alu OPS, 16-BIT IMMEDIATE */ - ALU_R16I8, ALU_M16I8, ALU_M16I8_RO, /* alu OPS, 16-BIT W/8-BIT IMMEDIATE */ - MUL_R8, MUL_R16, MUL_M8, MUL_M16, /* mul */ - IMUL_R8, IMUL_R16, IMUL_M8, IMUL_M16, /* imul */ - DIV_R8, DIV_R16, DIV_M8, DIV_M16, /* div */ - IDIV_R8, IDIV_R16, IDIV_M8, IDIV_M16, /* idiv */ - INCDEC_R8, INCDEC_R16, INCDEC_M8, INCDEC_M16, /* inc/dec */ - NEGNOT_R8, NEGNOT_R16, NEGNOT_M8, NEGNOT_M16, /* neg/not */ - - ROT_REG_1, ROT_REG_BASE, ROT_REG_BIT, /* REG SHIFT/ROTATE */ - ROT_M8_1, ROT_M8_BASE, ROT_M8_BIT, /* M8 SHIFT/ROTATE */ - ROT_M16_1, ROT_M16_BASE, ROT_M16_BIT, /* M16 SHIFT/ROTATE */ - - CMPS8, REP_CMPS8_BASE, REP_CMPS8_COUNT, /* cmps 8-BIT */ - CMPS16, REP_CMPS16_BASE, REP_CMPS16_COUNT, /* cmps 16-BIT */ - SCAS8, REP_SCAS8_BASE, REP_SCAS8_COUNT, /* scas 8-BIT */ - SCAS16, REP_SCAS16_BASE, REP_SCAS16_COUNT, /* scas 16-BIT */ - LODS8, REP_LODS8_BASE, REP_LODS8_COUNT, /* lods 8-BIT */ - LODS16, REP_LODS16_BASE, REP_LODS16_COUNT, /* lods 16-BIT */ - STOS8, REP_STOS8_BASE, REP_STOS8_COUNT, /* stos 8-BIT */ - STOS16, REP_STOS16_BASE, REP_STOS16_COUNT, /* stos 16-BIT */ - MOVS8, REP_MOVS8_BASE, REP_MOVS8_COUNT, /* movs 8-BIT */ - MOVS16, REP_MOVS16_BASE, REP_MOVS16_COUNT, /* movs 16-BIT */ - - INS8, REP_INS8_BASE, REP_INS8_COUNT, /* (80186) ins 8-BIT */ - INS16, REP_INS16_BASE, REP_INS16_COUNT, /* (80186) ins 16-BIT */ - OUTS8, REP_OUTS8_BASE, REP_OUTS8_COUNT, /* (80186) outs 8-BIT */ - OUTS16, REP_OUTS16_BASE, REP_OUTS16_COUNT, /* (80186) outs 16-BIT */ - PUSH_IMM, PUSHA, POPA, /* (80186) push IMMEDIATE, pusha/popa */ - IMUL_RRI8, IMUL_RMI8, /* (80186) imul IMMEDIATE 8-BIT */ - IMUL_RRI16, IMUL_RMI16, /* (80186) imul IMMEDIATE 16-BIT */ - ENTER0, ENTER1, ENTER_BASE, ENTER_COUNT, LEAVE, /* (80186) enter/leave */ - BOUND /* (80186) bound */ - }; - - enum SREGS { ES=0, CS, SS, DS }; - enum WREGS { AX=0, CX, DX, BX, SP, BP, SI, DI }; - - // device_execute_interface overrides - virtual uint32_t execute_min_cycles() const override { return 1; } - virtual uint32_t execute_max_cycles() const override { return 50; } - virtual void execute_set_input(int inputnum, int state) override; - - // device_disasm_interface overrides - virtual uint32_t disasm_min_opcode_bytes() const override { return 1; } - virtual uint32_t disasm_max_opcode_bytes() const override { return 8; } - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; - - // device_state_interface overrides - //virtual void state_import(const device_state_entry &entry) override; - //virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; - - virtual void interrupt(int int_num, int trap = 1); - virtual bool common_op(uint8_t op); - - // Accessing memory and io - inline uint8_t read_byte(uint32_t addr); - inline uint16_t read_word(uint32_t addr); - inline void write_byte(uint32_t addr, uint8_t data); - inline void write_word(uint32_t addr, uint16_t data); - virtual uint8_t read_port_byte(uint16_t port); - virtual uint16_t read_port_word(uint16_t port); - virtual void write_port_byte(uint16_t port, uint8_t data); - virtual void write_port_word(uint16_t port, uint16_t data); - - // Executing instructions - virtual uint8_t fetch_op() = 0; - virtual uint8_t fetch() = 0; - inline uint16_t fetch_word(); - inline uint8_t repx_op(); - - // Cycles passed while executing instructions - inline void CLK(uint8_t op); - inline void CLKM(uint8_t op_reg, uint8_t op_mem); - - // Memory handling while executing instructions - virtual uint32_t calc_addr(int seg, uint16_t offset, int size, int op, bool override = true); - inline uint32_t get_ea(int size, int op); - inline void PutbackRMByte(uint8_t data); - inline void PutbackRMWord(uint16_t data); - inline void RegByte(uint8_t data); - inline void RegWord(uint16_t data); - inline uint8_t RegByte(); - inline uint16_t RegWord(); - inline uint16_t GetRMWord(); - inline uint16_t GetnextRMWord(); - inline uint8_t GetRMByte(); - inline void PutMemB(int seg, uint16_t offset, uint8_t data); - inline void PutMemW(int seg, uint16_t offset, uint16_t data); - inline uint8_t GetMemB(int seg, uint16_t offset); - inline uint16_t GetMemW(int seg, uint16_t offset); - inline void PutImmRMWord(); - inline void PutRMWord(uint16_t val); - inline void PutRMByte(uint8_t val); - inline void PutImmRMByte(); - inline void DEF_br8(); - inline void DEF_wr16(); - inline void DEF_r8b(); - inline void DEF_r16w(); - inline void DEF_ald8(); - inline void DEF_axd16(); - - // Flags - inline void set_CFB(uint32_t x); - inline void set_CFW(uint32_t x); - inline void set_AF(uint32_t x,uint32_t y,uint32_t z); - inline void set_SF(uint32_t x); - inline void set_ZF(uint32_t x); - inline void set_PF(uint32_t x); - inline void set_SZPF_Byte(uint32_t x); - inline void set_SZPF_Word(uint32_t x); - inline void set_OFW_Add(uint32_t x,uint32_t y,uint32_t z); - inline void set_OFB_Add(uint32_t x,uint32_t y,uint32_t z); - inline void set_OFW_Sub(uint32_t x,uint32_t y,uint32_t z); - inline void set_OFB_Sub(uint32_t x,uint32_t y,uint32_t z); - inline uint16_t CompressFlags() const; - inline void ExpandFlags(uint16_t f); - - // rep instructions - inline void i_insb(); - inline void i_insw(); - inline void i_outsb(); - inline void i_outsw(); - inline void i_movsb(); - inline void i_movsw(); - inline void i_cmpsb(); - inline void i_cmpsw(); - inline void i_stosb(); - inline void i_stosw(); - inline void i_lodsb(); - inline void i_lodsw(); - inline void i_scasb(); - inline void i_scasw(); - inline void i_popf(); - - // sub implementations - inline uint32_t ADDB(); - inline uint32_t ADDX(); - inline uint32_t SUBB(); - inline uint32_t SUBX(); - inline void ORB(); - inline void ORW(); - inline void ANDB(); - inline void ANDX(); - inline void XORB(); - inline void XORW(); - inline void ROL_BYTE(); - inline void ROL_WORD(); - inline void ROR_BYTE(); - inline void ROR_WORD(); - inline void ROLC_BYTE(); - inline void ROLC_WORD(); - inline void RORC_BYTE(); - inline void RORC_WORD(); - inline void SHL_BYTE(uint8_t c); - inline void SHL_WORD(uint8_t c); - inline void SHR_BYTE(uint8_t c); - inline void SHR_WORD(uint8_t c); - inline void SHRA_BYTE(uint8_t c); - inline void SHRA_WORD(uint8_t c); - inline void XchgAXReg(uint8_t reg); - inline void IncWordReg(uint8_t reg); - inline void DecWordReg(uint8_t reg); - inline void PUSH(uint16_t data); - inline uint16_t POP(); - inline void JMP(bool cond); - inline void ADJ4(int8_t param1, int8_t param2); - inline void ADJB(int8_t param1, int8_t param2); - -protected: - - union - { /* eight general registers */ - uint16_t w[8]; /* viewed as 16 bits registers */ - uint8_t b[16]; /* or as 8 bit registers */ - } m_regs; - - enum BREGS { - AL = NATIVE_ENDIAN_VALUE_LE_BE(0x0, 0x1), - AH = NATIVE_ENDIAN_VALUE_LE_BE(0x1, 0x0), - CL = NATIVE_ENDIAN_VALUE_LE_BE(0x2, 0x3), - CH = NATIVE_ENDIAN_VALUE_LE_BE(0x3, 0x2), - DL = NATIVE_ENDIAN_VALUE_LE_BE(0x4, 0x5), - DH = NATIVE_ENDIAN_VALUE_LE_BE(0x5, 0x4), - BL = NATIVE_ENDIAN_VALUE_LE_BE(0x6, 0x7), - BH = NATIVE_ENDIAN_VALUE_LE_BE(0x7, 0x6), - SPL = NATIVE_ENDIAN_VALUE_LE_BE(0x8, 0x9), - SPH = NATIVE_ENDIAN_VALUE_LE_BE(0x9, 0x8), - BPL = NATIVE_ENDIAN_VALUE_LE_BE(0xa, 0xb), - BPH = NATIVE_ENDIAN_VALUE_LE_BE(0xb, 0xa), - SIL = NATIVE_ENDIAN_VALUE_LE_BE(0xc, 0xd), - SIH = NATIVE_ENDIAN_VALUE_LE_BE(0xd, 0xc), - DIL = NATIVE_ENDIAN_VALUE_LE_BE(0xe, 0xf), - DIH = NATIVE_ENDIAN_VALUE_LE_BE(0xf, 0xe) - }; - - enum { - I8086_READ, - I8086_WRITE, - I8086_FETCH, - I8086_NONE - }; - - uint16_t m_sregs[4]; - - uint16_t m_ip; - uint16_t m_prev_ip; - uint32_t m_amask; - - int32_t m_SignVal; - int32_t m_AuxVal, m_OverVal, m_ZeroVal, m_CarryVal, m_ParityVal; /* 0 or non-0 valued flags */ - uint8_t m_TF, m_IF, m_DF; /* 0 or 1 valued flags */ - uint8_t m_IOPL, m_NT, m_MF; - uint32_t m_int_vector; - uint32_t m_pending_irq; - uint32_t m_nmi_state; - uint32_t m_irq_state; - uint8_t m_no_interrupt; - uint8_t m_fire_trap; - uint8_t m_test_state; - int m_extra_cycles; - - DEVICE *d_program; - DEVICE *d_io; - DEVICE *d_dma; - BIOS *d_bios; - DEBUGGER *debugger; - DEVICE *d_mem_stored; - DEVICE *d_io_stored; - - int m_icount; - - uint32_t m_prefix_seg; /* the latest prefix segment */ - bool m_seg_prefix; /* prefix segment indicator */ - bool m_seg_prefix_next; /* prefix segment for next instruction */ - - uint32_t m_ea; - uint16_t m_eo; - uint16_t m_e16; - - // Used during execution of instructions - uint8_t m_modrm; - uint32_t m_dst; - uint32_t m_src; - uint32_t m_pc; - - // Lookup tables - uint8_t m_parity_table[256]; - struct { - struct { - int w[256]; - int b[256]; - } reg; - struct { - int w[256]; - int b[256]; - } RM; - } m_Mod_RM; - - uint8_t m_timing[200]; - bool m_halt; - - bool m_lock; - bool m_busreq; - - bool call_pseudo_bios(uint32_t PC); - bool call_pseudo_bios_int(int intnum); - -}; - -class i8086_cpu_device : public i8086_common_cpu_device -{ -public: - // construction/destruction - i8086_cpu_device(VM_TEMPLATE* prev_vm, EMU* prev_emu); - ~i8086_cpu_device(); - - // device_memory_interface overrides - uint32_t get_pc() - { - return prev_pc(); - } - uint32_t get_next_pc() - { - return pc(); - } - -protected: - virtual void execute_run() override; - virtual uint32_t execute_input_lines() const override { return 1; } - virtual uint8_t fetch_op() override; - virtual uint8_t fetch() override; - uint32_t pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; } - uint32_t prev_pc() { return (m_sregs[CS] << 4) + m_prev_ip; } - - static const uint8_t m_i8086_timing[200]; -}; - -class i8088_cpu_device : public i8086_cpu_device -{ -public: - // construction/destruction - i8088_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -}; - - -#endif /* __I8086_H__ */ diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i86.txt b/source/src/vm/libcpu_newdev/libcpu_i286/i86.txt deleted file mode 100644 index fb27b8526..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i86.txt +++ /dev/null @@ -1,114 +0,0 @@ -intel 8086 and compatibles --------------------------- - -this info is here, -to list and give some remarks on all 8086 compatible processors - -excellent info in Hamarsoft's 86BUGS list -(also distributed in ralf browns interrupt list) - -8086/8088 ---------- -20 bit address bus, 16 bit data bus and registers -many 8080 assembler sources should be compilable/reusable - -8086 ----- -6 bytes prefetch queue - -8088 ----- -8086 with 8 bit data bus, -prefetch queue only 4 byte, and refilled when 1 byte empty - -early 8086/8088 revisions bug ------------------------------ -(copyright 1978 on package) -mov sreg, doesnot disable until next operation is executed - -8086/8088 ---------- -"mov cs, " causes unconditional jump! -0xd6 is salc (sbb al,al) as all other intel x86-16 and -32 cpus - -80C86/80C88 ------------ -"mov cs, " ignored - -80186/80188 ------------ -integrated pic, timer and dmac entirely incompatible with 8259, 825[3,4] and 82[3,5]7 -additional instructions -#BR/bound/int 5, #UD/illegal instruction/int 6, #NM/coprocessor unavailable/int 7 support -"mov cs, " ignored (likely causes int 6) -shift count anded with 0x1f - -80188 ------ -8bit data bus - -NEC series ----------- -80186 instruction set, additional nec instructions -although it is based on 80186 instruction set, some behaviours follow 8086 -8080 emulation mode -"mov cs, " ignored -shift count not anded (acts like 8086) -0xd6 is xlat alias - -NEC 70116 (V30) ---------------- -8086 pin compatible - -NEC 70108 (V20) ---------------- -8088 pinout - -NEC V30MX ---------- -on die ems hardware -24 bit address but for ems memory!? -no 8080 emulation mode - -NEC V40 -------- -pinout, integrated peripherals 8259,54,37 clones at nonpc compatible addresses - -NEC V50 -------- -pinout, integrated peripherals as v40 - -NEC V33? --------- -speed optimized V30? - -NEC V25/V35? ------------- - -NEC V25+/V35+? --------------- - -NEC V60/V70 ------------ -risc (misc/delux) like instruction set -v30? emulation mode (without 8080 emulation mode) - -80286 ------ -80186 with additional instructions but no peripherals -24 bit address bus, -protected mode selector/descriptor - -80386 and later ---------------- -not covered here - -8087/80287/80387/80387sx ------------------------- -mathematical coprocessors - -weitek, iit variants - -in 80486 coprocessor integrated -(except 80486sx and several clones) -80487: 80486 with other pinout diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/i86inline.h b/source/src/vm/libcpu_newdev/libcpu_i286/i86inline.h deleted file mode 100644 index 80d6fc18d..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/i86inline.h +++ /dev/null @@ -1,988 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -#include "i86.h" - -#define CF (m_CarryVal!=0) -#define SF (m_SignVal<0) -#define ZF (m_ZeroVal==0) -#define PF m_parity_table[(uint8_t)m_ParityVal] -#define AF (m_AuxVal!=0) -#define OF (m_OverVal!=0) - -/* The interrupt number of a pending external interrupt pending NMI is 2. */ -/* For INTR interrupts, the level is caught on the bus during an INTA cycle */ - -#define INT_IRQ 0x01 -#define NMI_IRQ 0x02 - -uint8_t i8086_common_cpu_device::read_byte(uint32_t addr) -{ - if(m_program == NULL) return 0xff; - //return m_program->read_byte(addr); - return m_program->read_data8(addr); -} - -uint16_t i8086_common_cpu_device::read_word(uint32_t addr) -{ - if(m_program == NULL) return 0xffff; - //return m_program->read_word_unaligned(addr); - return m_program->read_data16(addr); -} - -void i8086_common_cpu_device::write_byte(uint32_t addr, uint8_t data) -{ - if(m_program == NULL) return; - m_program->write_data8(addr, data); - //m_program->write_byte(addr, data); -} - - -void i8086_common_cpu_device::write_word(uint32_t addr, uint16_t data) -{ - if(m_program == NULL) return; - //m_program->write_word_unaligned(addr, data); - m_program->write_data16(addr, data); -} - -inline uint16_t i8086_common_cpu_device::fetch_word() -{ - uint16_t data = fetch(); - data |= ( fetch() << 8 ); - return data; -} - -inline uint8_t i8086_common_cpu_device::repx_op() -{ - uint8_t next = fetch_op(); - bool seg_prefix = false; - int seg = 0; - - switch (next) - { - case 0x26: - seg_prefix = true; - seg = ES; - break; - case 0x2e: - seg_prefix = true; - seg = CS; - break; - case 0x36: - seg_prefix = true; - seg = SS; - break; - case 0x3e: - seg_prefix = true; - seg = DS; - break; - } - - if ( seg_prefix ) - { - m_seg_prefix = true; - m_seg_prefix_next = true; - m_prefix_seg = seg; - next = fetch_op(); - CLK(OVERRIDE); - } - - return next; -} - - -inline void i8086_common_cpu_device::CLK(uint8_t op) -{ - m_icount -= m_timing[op]; -} - - -inline void i8086_common_cpu_device::CLKM(uint8_t op_reg, uint8_t op_mem) -{ - m_icount -= ( m_modrm >= 0xc0 ) ? m_timing[op_reg] : m_timing[op_mem]; -} - - -inline uint32_t i8086_common_cpu_device::get_ea(int size, int op) -{ - switch( m_modrm & 0xc7 ) - { - case 0x00: - m_icount -= 7; - m_eo = m_regs.w[BX] + m_regs.w[SI]; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x01: - m_icount -= 8; - m_eo = m_regs.w[BX] + m_regs.w[DI]; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x02: - m_icount -= 8; - m_eo = m_regs.w[BP] + m_regs.w[SI]; - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x03: - m_icount -= 7; - m_eo = m_regs.w[BP] + m_regs.w[DI]; - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x04: - m_icount -= 5; - m_eo = m_regs.w[SI]; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x05: - m_icount -= 5; - m_eo = m_regs.w[DI]; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x06: - m_icount -= 6; - m_eo = fetch_word(); - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x07: - m_icount -= 5; - m_eo = m_regs.w[BX]; - m_ea = calc_addr(DS, m_eo, size, op); - break; - - case 0x40: - m_icount -= 11; - m_eo = m_regs.w[BX] + m_regs.w[SI] + (int8_t)fetch(); - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x41: - m_icount -= 12; - m_eo = m_regs.w[BX] + m_regs.w[DI] + (int8_t)fetch(); - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x42: - m_icount -= 12; - m_eo = m_regs.w[BP] + m_regs.w[SI] + (int8_t)fetch(); - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x43: - m_icount -= 11; - m_eo = m_regs.w[BP] + m_regs.w[DI] + (int8_t)fetch(); - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x44: - m_icount -= 9; - m_eo = m_regs.w[SI] + (int8_t)fetch(); - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x45: - m_icount -= 9; - m_eo = m_regs.w[DI] + (int8_t)fetch(); - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x46: - m_icount -= 9; - m_eo = m_regs.w[BP] + (int8_t)fetch(); - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x47: - m_icount -= 9; - m_eo = m_regs.w[BX] + (int8_t)fetch(); - m_ea = calc_addr(DS, m_eo, size, op); - break; - - case 0x80: - m_icount -= 11; - m_e16 = fetch_word(); - m_eo = m_regs.w[BX] + m_regs.w[SI] + (int16_t)m_e16; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x81: - m_icount -= 12; - m_e16 = fetch_word(); - m_eo = m_regs.w[BX] + m_regs.w[DI] + (int16_t)m_e16; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x82: - m_icount -= 11; - m_e16 = fetch_word(); - m_eo = m_regs.w[BP] + m_regs.w[SI] + (int16_t)m_e16; - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x83: - m_icount -= 11; - m_e16 = fetch_word(); - m_eo = m_regs.w[BP] + m_regs.w[DI] + (int16_t)m_e16; - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x84: - m_icount -= 9; - m_e16 = fetch_word(); - m_eo = m_regs.w[SI] + (int16_t)m_e16; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x85: - m_icount -= 9; - m_e16 = fetch_word(); - m_eo = m_regs.w[DI] + (int16_t)m_e16; - m_ea = calc_addr(DS, m_eo, size, op); - break; - case 0x86: - m_icount -= 9; - m_e16 = fetch_word(); - m_eo = m_regs.w[BP] + (int16_t)m_e16; - m_ea = calc_addr(SS, m_eo, size, op); - break; - case 0x87: - m_icount -= 9; - m_e16 = fetch_word(); - m_eo = m_regs.w[BX] + (int16_t)m_e16; - m_ea = calc_addr(DS, m_eo, size, op); - break; - } - - return m_ea; -} - - -inline void i8086_common_cpu_device::PutbackRMByte(uint8_t data) -{ - if ( m_modrm >= 0xc0 ) - { - m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ] = data; - } - else - { - write_byte( m_ea, data ); - } -} - - -inline void i8086_common_cpu_device::PutbackRMWord(uint16_t data) -{ - if ( m_modrm >= 0xc0 ) - { - m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ] = data; - } - else - { - write_word( m_ea, data ); - } -} - -inline void i8086_common_cpu_device::PutImmRMWord() -{ - if ( m_modrm >= 0xc0 ) - { - m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ] = fetch_word(); - } - else - { - uint32_t addr = get_ea(2, I8086_WRITE); - write_word( addr, fetch_word() ); - } -} - -inline void i8086_common_cpu_device::PutRMWord(uint16_t val) -{ - if ( m_modrm >= 0xc0 ) - { - m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ] = val; - } - else - { - write_word( get_ea(2, I8086_WRITE), val ); - } -} - - -inline void i8086_common_cpu_device::PutRMByte(uint8_t val) -{ - if ( m_modrm >= 0xc0 ) - { - m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ] = val; - } - else - { - write_byte( get_ea(1, I8086_WRITE), val ); - } -} - - -inline void i8086_common_cpu_device::PutImmRMByte() -{ - if ( m_modrm >= 0xc0 ) - { - m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ] = fetch(); - } - else - { - uint32_t addr = get_ea(1, I8086_WRITE); - write_byte( addr, fetch() ); - } -} - - -inline void i8086_common_cpu_device::DEF_br8() -{ - m_modrm = fetch(); - m_src = RegByte(); - m_dst = GetRMByte(); -} - - -inline void i8086_common_cpu_device::DEF_wr16() -{ - m_modrm = fetch(); - m_src = RegWord(); - m_dst = GetRMWord(); -} - - -inline void i8086_common_cpu_device::DEF_r8b() -{ - m_modrm = fetch(); - m_dst = RegByte(); - m_src = GetRMByte(); -} - - -inline void i8086_common_cpu_device::DEF_r16w() -{ - m_modrm = fetch(); - m_dst = RegWord(); - m_src = GetRMWord(); -} - - -inline void i8086_common_cpu_device::DEF_ald8() -{ - m_src = fetch(); - m_dst = m_regs.b[AL]; -} - - -inline void i8086_common_cpu_device::DEF_axd16() -{ - m_src = fetch_word(); - m_dst = m_regs.w[AX]; -} - - - -inline void i8086_common_cpu_device::RegByte(uint8_t data) -{ - m_regs.b[ m_Mod_RM.reg.b[ m_modrm ] ] = data; -} - - -inline void i8086_common_cpu_device::RegWord(uint16_t data) -{ - m_regs.w[ m_Mod_RM.reg.w[ m_modrm ] ] = data; -} - - -inline uint8_t i8086_common_cpu_device::RegByte() -{ - return m_regs.b[ m_Mod_RM.reg.b[ m_modrm ] ]; -} - - -inline uint16_t i8086_common_cpu_device::RegWord() -{ - return m_regs.w[ m_Mod_RM.reg.w[ m_modrm ] ]; -} - - -inline uint16_t i8086_common_cpu_device::GetRMWord() -{ - if ( m_modrm >= 0xc0 ) - { - return m_regs.w[ m_Mod_RM.RM.w[ m_modrm ] ]; - } - else - { - return read_word( get_ea(2, I8086_READ) ); - } -} - - -inline uint16_t i8086_common_cpu_device::GetnextRMWord() -{ - uint32_t addr = ( m_ea & ~0xffff ) | ( ( m_ea + 2 ) & 0xffff ); - - return read_word( addr ); -} - - -inline uint8_t i8086_common_cpu_device::GetRMByte() -{ - if ( m_modrm >= 0xc0 ) - { - return m_regs.b[ m_Mod_RM.RM.b[ m_modrm ] ]; - } - else - { - return read_byte( get_ea(1, I8086_READ) ); - } -} - - -inline void i8086_common_cpu_device::PutMemB(int seg, uint16_t offset, uint8_t data) -{ - write_byte( calc_addr(seg, offset, 1, I8086_WRITE), data); -} - - -inline void i8086_common_cpu_device::PutMemW(int seg, uint16_t offset, uint16_t data) -{ - write_word( calc_addr( seg, offset, 2, I8086_WRITE), data); -} - - -inline uint8_t i8086_common_cpu_device::GetMemB(int seg, uint16_t offset) -{ - return read_byte( calc_addr(seg, offset, 1, I8086_READ) ); -} - - -inline uint16_t i8086_common_cpu_device::GetMemW(int seg, uint16_t offset) -{ - return read_word( calc_addr(seg, offset, 2, I8086_READ) ); -} - - -// Setting flags - -inline void i8086_common_cpu_device::set_CFB(uint32_t x) -{ - m_CarryVal = x & 0x100; -} - -inline void i8086_common_cpu_device::set_CFW(uint32_t x) -{ - m_CarryVal = x & 0x10000; -} - -inline void i8086_common_cpu_device::set_AF(uint32_t x,uint32_t y,uint32_t z) -{ - m_AuxVal = (x ^ (y ^ z)) & 0x10; -} - -inline void i8086_common_cpu_device::set_SF(uint32_t x) -{ - m_SignVal = x; -} - -inline void i8086_common_cpu_device::set_ZF(uint32_t x) -{ - m_ZeroVal = x; -} - -inline void i8086_common_cpu_device::set_PF(uint32_t x) -{ - m_ParityVal = x; -} - -inline void i8086_common_cpu_device::set_SZPF_Byte(uint32_t x) -{ - m_SignVal = m_ZeroVal = m_ParityVal = (int8_t)x; -} - -inline void i8086_common_cpu_device::set_SZPF_Word(uint32_t x) -{ - m_SignVal = m_ZeroVal = m_ParityVal = (int16_t)x; -} - -inline void i8086_common_cpu_device::set_OFW_Add(uint32_t x,uint32_t y,uint32_t z) -{ - m_OverVal = (x ^ y) & (x ^ z) & 0x8000; -} - -inline void i8086_common_cpu_device::set_OFB_Add(uint32_t x,uint32_t y,uint32_t z) -{ - m_OverVal = (x ^ y) & (x ^ z) & 0x80; -} - -inline void i8086_common_cpu_device::set_OFW_Sub(uint32_t x,uint32_t y,uint32_t z) -{ - m_OverVal = (z ^ y) & (z ^ x) & 0x8000; -} - -inline void i8086_common_cpu_device::set_OFB_Sub(uint32_t x,uint32_t y,uint32_t z) -{ - m_OverVal = (z ^ y) & (z ^ x) & 0x80; -} - - -inline uint16_t i8086_common_cpu_device::CompressFlags() const -{ - return (CF ? 1 : 0) - | (1 << 1) - | (PF ? 4 : 0) - | (AF ? 0x10 : 0) - | (ZF ? 0x40 : 0) - | (SF ? 0x80 : 0) - | (m_TF << 8) - | (m_IF << 9) - | (m_DF << 10) - | (OF << 11) - | (m_IOPL << 12) - | (m_NT << 14) - | (m_MF << 15); -} - -inline void i8086_common_cpu_device::ExpandFlags(uint16_t f) -{ - m_CarryVal = (f) & 1; - m_ParityVal = !((f) & 4); - m_AuxVal = (f) & 16; - m_ZeroVal = !((f) & 64); - m_SignVal = (f) & 128 ? -1 : 0; - m_TF = ((f) & 256) == 256; - m_IF = ((f) & 512) == 512; - m_DF = ((f) & 1024) == 1024; - m_OverVal = (f) & 2048; - m_IOPL = (f >> 12) & 3; - m_NT = ((f) & 0x4000) == 0x4000; - m_MF = ((f) & 0x8000) == 0x8000; -} - -inline void i8086_common_cpu_device::i_insb() -{ - uint32_t ea = calc_addr(ES, m_regs.w[DI], 1, I8086_WRITE); - write_byte(ea, read_port_byte(m_regs.w[DX])); - m_regs.w[DI] += -2 * m_DF + 1; - CLK(IN_IMM8); -} - -inline void i8086_common_cpu_device::i_insw() -{ - uint32_t ea = calc_addr(ES, m_regs.w[DI], 2, I8086_WRITE); - write_word(ea, read_port_word(m_regs.w[DX])); - m_regs.w[DI] += -4 * m_DF + 2; - CLK(IN_IMM16); -} - -inline void i8086_common_cpu_device::i_outsb() -{ - write_port_byte(m_regs.w[DX], GetMemB(DS, m_regs.w[SI])); - m_regs.w[SI] += -2 * m_DF + 1; - CLK(OUT_IMM8); -} - -inline void i8086_common_cpu_device::i_outsw() -{ - write_port_word(m_regs.w[DX], GetMemW(DS, m_regs.w[SI])); - m_regs.w[SI] += -4 * m_DF + 2; - CLK(OUT_IMM16); -} - -inline void i8086_common_cpu_device::i_movsb() -{ - uint8_t tmp = GetMemB( DS, m_regs.w[SI] ); - PutMemB( ES, m_regs.w[DI], tmp); - m_regs.w[DI] += -2 * m_DF + 1; - m_regs.w[SI] += -2 * m_DF + 1; - CLK(MOVS8); -} - -inline void i8086_common_cpu_device::i_movsw() -{ - uint16_t tmp = GetMemW( DS, m_regs.w[SI] ); - PutMemW( ES, m_regs.w[DI], tmp ); - m_regs.w[DI] += -4 * m_DF + 2; - m_regs.w[SI] += -4 * m_DF + 2; - CLK(MOVS16); -} - -inline void i8086_common_cpu_device::i_cmpsb() -{ - m_src = GetMemB( ES, m_regs.w[DI] ); - m_dst = GetMemB( DS, m_regs.w[SI] ); - set_CFB(SUBB()); - m_regs.w[DI] += -2 * m_DF + 1; - m_regs.w[SI] += -2 * m_DF + 1; - CLK(CMPS8); -} - -inline void i8086_common_cpu_device::i_cmpsw() -{ - m_src = GetMemW( ES, m_regs.w[DI] ); - m_dst = GetMemW( DS, m_regs.w[SI] ); - set_CFW(SUBX()); - m_regs.w[DI] += -4 * m_DF + 2; - m_regs.w[SI] += -4 * m_DF + 2; - CLK(CMPS16); -} - -inline void i8086_common_cpu_device::i_stosb() -{ - PutMemB( ES, m_regs.w[DI], m_regs.b[AL] ); - m_regs.w[DI] += -2 * m_DF + 1; - CLK(STOS8); -} - -inline void i8086_common_cpu_device::i_stosw() -{ - PutMemW( ES, m_regs.w[DI], m_regs.w[AX] ); - m_regs.w[DI] += -4 * m_DF + 2; - CLK(STOS16); -} - -inline void i8086_common_cpu_device::i_lodsb() -{ - m_regs.b[AL] = GetMemB( DS, m_regs.w[SI] ); - m_regs.w[SI] += -2 * m_DF + 1; - CLK(LODS8); -} - -inline void i8086_common_cpu_device::i_lodsw() -{ - m_regs.w[AX] = GetMemW( DS, m_regs.w[SI] ); - m_regs.w[SI] += -4 * m_DF + 2; - CLK(LODS16); -} - -inline void i8086_common_cpu_device::i_scasb() -{ - m_src = GetMemB( ES, m_regs.w[DI] ); - m_dst = m_regs.b[AL]; - set_CFB(SUBB()); - m_regs.w[DI] += -2 * m_DF + 1; - CLK(SCAS8); -} - -inline void i8086_common_cpu_device::i_scasw() -{ - m_src = GetMemW( ES, m_regs.w[DI] ); - m_dst = m_regs.w[AX]; - set_CFW(SUBX()); - m_regs.w[DI] += -4 * m_DF + 2; - CLK(SCAS16); -} - - -inline void i8086_common_cpu_device::i_popf() -{ - uint32_t tmp = POP(); - - ExpandFlags(tmp | 0xf000); - CLK(POPF); - if (m_TF) - { - m_fire_trap = 1; - } -} - - -inline uint32_t i8086_common_cpu_device::ADDB() -{ - uint32_t res = m_dst + m_src; - - set_OFB_Add(res,m_src,m_dst); - set_AF(res,m_src,m_dst); - set_SZPF_Byte(res); - m_dst = res & 0xff; - return res; -} - - -inline uint32_t i8086_common_cpu_device::ADDX() -{ - uint32_t res = m_dst + m_src; - - set_OFW_Add(res,m_src,m_dst); - set_AF(res,m_src,m_dst); - set_SZPF_Word(res); - m_dst = res & 0xffff; - return res; -} - - -inline uint32_t i8086_common_cpu_device::SUBB() -{ - uint32_t res = m_dst - m_src; - - set_OFB_Sub(res,m_src,m_dst); - set_AF(res,m_src,m_dst); - set_SZPF_Byte(res); - m_dst = res & 0xff; - return res; -} - - -inline uint32_t i8086_common_cpu_device::SUBX() -{ - uint32_t res = m_dst - m_src; - - set_OFW_Sub(res,m_src,m_dst); - set_AF(res,m_src,m_dst); - set_SZPF_Word(res); - m_dst = res & 0xffff; - return res; -} - - -inline void i8086_common_cpu_device::ORB() -{ - m_dst |= m_src; - m_CarryVal = m_OverVal = m_AuxVal = 0; - set_SZPF_Byte(m_dst); -} - - -inline void i8086_common_cpu_device::ORW() -{ - m_dst |= m_src; - m_CarryVal = m_OverVal = m_AuxVal = 0; - set_SZPF_Word(m_dst); -} - - -inline void i8086_common_cpu_device::ANDB() -{ - m_dst &= m_src; - m_CarryVal = m_OverVal = m_AuxVal = 0; - set_SZPF_Byte(m_dst); -} - - -inline void i8086_common_cpu_device::ANDX() -{ - m_dst &= m_src; - m_CarryVal = m_OverVal = m_AuxVal = 0; - set_SZPF_Word(m_dst); -} - - -inline void i8086_common_cpu_device::XORB() -{ - m_dst ^= m_src; - m_CarryVal = m_OverVal = m_AuxVal = 0; - set_SZPF_Byte(m_dst); -} - - -inline void i8086_common_cpu_device::XORW() -{ - m_dst ^= m_src; - m_CarryVal = m_OverVal = m_AuxVal = 0; - set_SZPF_Word(m_dst); -} - - -inline void i8086_common_cpu_device::ROL_BYTE() -{ - m_CarryVal = m_dst & 0x80; - m_dst = (m_dst << 1) | ( CF ? 1 : 0 ); -} - -inline void i8086_common_cpu_device::ROL_WORD() -{ - m_CarryVal = m_dst & 0x8000; - m_dst = (m_dst << 1) | ( CF ? 1 : 0 ); -} - -inline void i8086_common_cpu_device::ROR_BYTE() -{ - m_CarryVal = m_dst & 0x1; - m_dst = (m_dst >> 1) | (CF ? 0x80 : 0x00); -} - -inline void i8086_common_cpu_device::ROR_WORD() -{ - m_CarryVal = m_dst & 0x1; - m_dst = (m_dst >> 1) + (CF ? 0x8000 : 0x0000); -} - -inline void i8086_common_cpu_device::ROLC_BYTE() -{ - m_dst = (m_dst << 1) | ( CF ? 1 : 0 ); - set_CFB(m_dst); -} - -inline void i8086_common_cpu_device::ROLC_WORD() -{ - m_dst = (m_dst << 1) | ( CF ? 1 : 0 ); - set_CFW(m_dst); -} - -inline void i8086_common_cpu_device::RORC_BYTE() -{ - m_dst |= ( CF ? 0x100 : 0x00); - m_CarryVal = m_dst & 0x01; - m_dst >>= 1; -} - -inline void i8086_common_cpu_device::RORC_WORD() -{ - m_dst |= ( CF ? 0x10000 : 0); - m_CarryVal = m_dst & 0x01; - m_dst >>= 1; -} - -inline void i8086_common_cpu_device::SHL_BYTE(uint8_t c) -{ - while (c--) - m_dst <<= 1; - - set_CFB(m_dst); - set_SZPF_Byte(m_dst); - PutbackRMByte(m_dst); -} - -inline void i8086_common_cpu_device::SHL_WORD(uint8_t c) -{ - while (c--) - m_dst <<= 1; - - set_CFW(m_dst); - set_SZPF_Word(m_dst); - PutbackRMWord(m_dst); -} - -inline void i8086_common_cpu_device::SHR_BYTE(uint8_t c) -{ - while (c--) - { - m_CarryVal = m_dst & 0x01; - m_dst >>= 1; - } - - set_SZPF_Byte(m_dst); - PutbackRMByte(m_dst); -} - -inline void i8086_common_cpu_device::SHR_WORD(uint8_t c) -{ - while (c--) - { - m_CarryVal = m_dst & 0x01; - m_dst >>= 1; - } - - set_SZPF_Word(m_dst); - PutbackRMWord(m_dst); -} - -inline void i8086_common_cpu_device::SHRA_BYTE(uint8_t c) -{ - while (c--) - { - m_CarryVal = m_dst & 0x01; - m_dst = ((int8_t) m_dst) >> 1; - } - - set_SZPF_Byte(m_dst); - PutbackRMByte(m_dst); -} - -inline void i8086_common_cpu_device::SHRA_WORD(uint8_t c) -{ - while (c--) - { - m_CarryVal = m_dst & 0x01; - m_dst = ((int16_t) m_dst) >> 1; - } - - set_SZPF_Word(m_dst); - PutbackRMWord(m_dst); -} - - -inline void i8086_common_cpu_device::XchgAXReg(uint8_t reg) -{ - uint16_t tmp = m_regs.w[reg]; - - m_regs.w[reg] = m_regs.w[AX]; - m_regs.w[AX] = tmp; -} - - -inline void i8086_common_cpu_device::IncWordReg(uint8_t reg) -{ - uint32_t tmp = m_regs.w[reg]; - uint32_t tmp1 = tmp+1; - - m_OverVal = (tmp == 0x7fff); - set_AF(tmp1,tmp,1); - set_SZPF_Word(tmp1); - m_regs.w[reg] = tmp1; -} - - -inline void i8086_common_cpu_device::DecWordReg(uint8_t reg) -{ - uint32_t tmp = m_regs.w[reg]; - uint32_t tmp1 = tmp-1; - - m_OverVal = (tmp == 0x8000); - set_AF(tmp1,tmp,1); - set_SZPF_Word(tmp1); - m_regs.w[reg] = tmp1; -} - - -inline void i8086_common_cpu_device::PUSH(uint16_t data) -{ - write_word(calc_addr(SS, m_regs.w[SP] - 2, 2, I8086_WRITE, false), data); - m_regs.w[SP] -= 2; -} - - -inline uint16_t i8086_common_cpu_device::POP() -{ - uint16_t data = read_word(calc_addr(SS, m_regs.w[SP], 2, I8086_READ, false)); - - m_regs.w[SP] += 2; - return data; -} - - -inline void i8086_common_cpu_device::JMP(bool cond) -{ - int rel = (int)((int8_t)fetch()); - - if (cond) - { - m_ip += rel; - CLK(JCC_T); - } - else - CLK(JCC_NT); -} - - -inline void i8086_common_cpu_device::ADJ4(int8_t param1,int8_t param2) -{ - if (AF || ((m_regs.b[AL] & 0xf) > 9)) - { - uint16_t tmp; - tmp = m_regs.b[AL] + param1; - m_regs.b[AL] = tmp; - m_AuxVal = 1; - m_CarryVal |= tmp & 0x100; - } - if (CF || (m_regs.b[AL]>0x9f)) - { - m_regs.b[AL] += param2; - m_CarryVal = 1; - } - set_SZPF_Byte(m_regs.b[AL]); -} - - -inline void i8086_common_cpu_device::ADJB(int8_t param1, int8_t param2) -{ - if (AF || ((m_regs.b[AL] & 0xf) > 9)) - { - m_regs.b[AL] += param1; - m_regs.b[AH] += param2; - m_AuxVal = 1; - m_CarryVal = 1; - } - else - { - m_AuxVal = 0; - m_CarryVal = 0; - } - m_regs.b[AL] &= 0x0F; -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i286/readme_takeda.txt b/source/src/vm/libcpu_newdev/libcpu_i286/readme_takeda.txt deleted file mode 100644 index 5b7c50b3b..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i286/readme_takeda.txt +++ /dev/null @@ -1,2 +0,0 @@ -Based on MAME 0.149. -Add NEC V30 instructions based on MAME 0.128. diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/CMakeLists.txt b/source/src/vm/libcpu_newdev/libcpu_i386/CMakeLists.txt deleted file mode 100644 index 65db1de44..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -cmake_minimum_required (VERSION 2.6) - -message("* vm/libcpu_newdev/libcpu_i386") - -add_library(cpu_newdev_i386 - ) - diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/cycles.h b/source/src/vm/libcpu_newdev/libcpu_i386/cycles.h deleted file mode 100644 index a538411cb..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/cycles.h +++ /dev/null @@ -1,337 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett - -#pragma once - -#ifndef __LIB_I386_CYCLES_H__ -#define __LIB_I386_CYCLES_H__ - -const X86_CYCLE_TABLE x86_cycle_table[] = -{ - // opcode rm/pmode - // i386 i486 pentium mediagx - { CYCLES_MOV_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_MOV_REG_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_MOV_MEM_REG, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_MOV_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_MOV_IMM_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_MOV_ACC_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_MOV_MEM_ACC, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_MOV_REG_SREG, { { 2, 18 }, { 3, 3 }, { 2, 2 }, { 1, 6 } } }, - { CYCLES_MOV_MEM_SREG, { { 5, 19 }, { 9, 9 }, { 3, 3 }, { 1, 6 } } }, - { CYCLES_MOV_SREG_REG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } }, - { CYCLES_MOV_SREG_MEM, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } }, - { CYCLES_MOVSX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_MOVSX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_MOVZX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_MOVZX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_PUSH_RM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 3, 3 } } }, - { CYCLES_PUSH_REG_SHORT, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_PUSH_SREG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_PUSH_IMM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_PUSHA, { { 18, 18 }, { 11, 11 }, { 5, 5 }, { 11, 11 } } }, - { CYCLES_POP_RM, { { 5, 5 }, { 4, 4 }, { 3, 3 }, { 4, 4 } } }, - { CYCLES_POP_REG_SHORT, { { 4, 4 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_POP_SREG, { { 7, 21 }, { 3, 3 }, { 3, 3 }, { 1, 6 } } }, - { CYCLES_POPA, { { 24, 24 }, { 9, 9 }, { 5, 5 }, { 9, 9 } } }, - { CYCLES_XCHG_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_XCHG_REG_MEM, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_IN, { { 12, 26 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } }, - { CYCLES_IN_VAR, { { 13, 27 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } }, - { CYCLES_OUT, { { 10, 24 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } }, - { CYCLES_OUT_VAR, { { 11, 25 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } }, - { CYCLES_LEA, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_LDS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, - { CYCLES_LES, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, - { CYCLES_LFS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, - { CYCLES_LGS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } }, - { CYCLES_LSS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 10 } } }, - { CYCLES_CLC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_CLD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } }, - { CYCLES_CLI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } }, - { CYCLES_CLTS, { { 6, 6 }, { 7, 7 }, { 10, 10 }, { 7, 7 } } }, - { CYCLES_CMC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 } } }, - { CYCLES_LAHF, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } }, - { CYCLES_POPF, { { 5, 5 }, { 9, 9 }, { 6, 6 }, { 8, 8 } } }, - { CYCLES_PUSHF, { { 4, 4 }, { 4, 4 }, { 9, 9 }, { 2, 2 } } }, - { CYCLES_SAHF, { { 3, 3 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_STC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_STD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } }, - { CYCLES_STI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } }, - { CYCLES_ALU_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_ALU_REG_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_ALU_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_ALU_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_ALU_IMM_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_ALU_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_INC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_INC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_DEC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_DEC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_CMP_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_CMP_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_CMP_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_CMP_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_CMP_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_CMP_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_TEST_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_TEST_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_TEST_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_TEST_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_TEST_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_NEG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_NEG_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_AAA, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, - { CYCLES_AAS, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, - { CYCLES_DAA, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } }, - { CYCLES_DAS, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } }, - { CYCLES_MUL8_ACC_REG, { { 17, 17 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } }, - { CYCLES_MUL8_ACC_MEM, { { 20, 20 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } }, - { CYCLES_MUL16_ACC_REG, { { 25, 25 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } }, - { CYCLES_MUL16_ACC_MEM, { { 28, 28 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } }, - { CYCLES_MUL32_ACC_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, - { CYCLES_MUL32_ACC_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, - { CYCLES_IMUL8_ACC_REG, { { 17, 17 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } }, - { CYCLES_IMUL8_ACC_MEM, { { 20, 20 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } }, - { CYCLES_IMUL16_ACC_REG, { { 25, 25 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } }, - { CYCLES_IMUL16_ACC_MEM, { { 28, 28 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } }, - { CYCLES_IMUL32_ACC_REG, { { 41, 41 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } }, - { CYCLES_IMUL32_ACC_MEM, { { 44, 44 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } }, - { CYCLES_IMUL8_REG_REG, { { 17, 17 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } }, - { CYCLES_IMUL8_REG_MEM, { { 20, 20 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } }, - { CYCLES_IMUL16_REG_REG, { { 25, 25 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } }, - { CYCLES_IMUL16_REG_MEM, { { 28, 28 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } }, - { CYCLES_IMUL32_REG_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, - { CYCLES_IMUL32_REG_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } }, - { CYCLES_IMUL16_REG_IMM_REG,{ { 26, 26 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } }, - { CYCLES_IMUL16_MEM_IMM_REG,{ { 27, 27 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } }, - { CYCLES_IMUL32_REG_IMM_REG,{ { 42, 42 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } }, - { CYCLES_IMUL32_MEM_IMM_REG,{ { 43, 43 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } }, - { CYCLES_DIV8_ACC_REG, { { 14, 14 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } }, - { CYCLES_DIV8_ACC_MEM, { { 17, 17 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } }, - { CYCLES_DIV16_ACC_REG, { { 22, 22 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } }, - { CYCLES_DIV16_ACC_MEM, { { 25, 25 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } }, - { CYCLES_DIV32_ACC_REG, { { 38, 38 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } }, - { CYCLES_DIV32_ACC_MEM, { { 41, 41 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } }, - { CYCLES_IDIV8_ACC_REG, { { 19, 19 }, { 19, 19 }, { 22, 22 }, { 20, 20 } } }, - { CYCLES_IDIV8_ACC_MEM, { { 22, 22 }, { 20, 20 }, { 22, 22 }, { 20, 20 } } }, - { CYCLES_IDIV16_ACC_REG, { { 27, 27 }, { 27, 27 }, { 30, 30 }, { 29, 29 } } }, - { CYCLES_IDIV16_ACC_MEM, { { 30, 30 }, { 28, 28 }, { 30, 30 }, { 29, 29 } } }, - { CYCLES_IDIV32_ACC_REG, { { 43, 43 }, { 43, 43 }, { 46, 46 }, { 45, 45 } } }, - { CYCLES_IDIV32_ACC_MEM, { { 46, 46 }, { 44, 44 }, { 46, 46 }, { 45, 45 } } }, - { CYCLES_AAD, { { 19, 19 }, { 14, 14 }, { 10, 10 }, { 7, 7 } } }, - { CYCLES_AAM, { { 17, 17 }, { 15, 15 }, { 18, 18 }, { 19, 19 } } }, - { CYCLES_CBW, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, - { CYCLES_CWD, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } }, - { CYCLES_ROTATE_REG, { { 3, 3 }, { 3, 3 }, { 1, 1 }, { 2, 2 } } }, - { CYCLES_ROTATE_MEM, { { 7, 7 }, { 4, 4 }, { 3, 3 }, { 2, 2 } } }, - { CYCLES_ROTATE_CARRY_REG, { { 9, 9 }, { 8, 8 }, { 7, 7 }, { 8, 8 } } }, - { CYCLES_ROTATE_CARRY_MEM, { { 10, 10 }, { 9, 9 }, { 8, 8 }, { 8, 8 } } }, - { CYCLES_SHLD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } }, - { CYCLES_SHLD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } }, - { CYCLES_SHRD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } }, - { CYCLES_SHRD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } }, - { CYCLES_NOT_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_NOT_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_CMPS, { { 10, 10 }, { 8, 8 }, { 5, 5 }, { 6, 6 } } }, - { CYCLES_INS, { { 15, 29 }, { 17, 30 }, { 9, 22 }, { 11, 11 } } }, - { CYCLES_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, - { CYCLES_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 6, 6 } } }, - { CYCLES_OUTS, { { 14, 28 }, { 17, 30 }, { 13, 25 }, { 15, 15 } } }, - { CYCLES_SCAS, { { 8, 8 }, { 6, 6 }, { 4, 4 }, { 2, 2 } } }, - { CYCLES_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } }, - { CYCLES_XLAT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } }, - { CYCLES_REP_CMPS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 11, 11 } } }, - { CYCLES_REP_INS_BASE, { { 14, 8 }, { 0, 0 }, { 0, 0 }, { 17, 17 } } }, - { CYCLES_REP_LODS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } }, - { CYCLES_REP_MOVS_BASE, { { 8, 8 }, { 0, 0 }, { 0, 0 }, { 12, 12 } } }, - { CYCLES_REP_OUTS_BASE, { { 12, 6 }, { 0, 0 }, { 0, 0 }, { 24, 24 } } }, - { CYCLES_REP_SCAS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } }, - { CYCLES_REP_STOS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } }, - { CYCLES_REP_CMPS, { { 5, 5 }, { 8, 8 }, { 5, 5 }, { 4, 4 } } }, - { CYCLES_REP_INS, { { 14, 8 }, { 17, 30 }, { 9, 22 }, { 4, 4 } } }, - { CYCLES_REP_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 2, 2 } } }, - { CYCLES_REP_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 2, 2 } } }, - { CYCLES_REP_OUTS, { { 12, 6 }, { 17, 30 }, { 13, 25 }, { 4, 4 } } }, - { CYCLES_REP_SCAS, { { 5, 5 }, { 6, 6 }, { 4, 4 }, { 3, 3 } } }, - { CYCLES_REP_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } }, - { CYCLES_BSF_BASE, { { 11, 11 }, { 6, 6 }, { 6, 6 }, { 4, 4 } } }, - { CYCLES_BSF, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_BSR_BASE, { { 9, 9 }, { 6, 6 }, { 7, 7 }, { 4, 4 } } }, - { CYCLES_BSR, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_BT_IMM_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } }, - { CYCLES_BT_IMM_MEM, { { 6, 6 }, { 6, 6 }, { 4, 4 }, { 1, 1 } } }, - { CYCLES_BT_REG_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } }, - { CYCLES_BT_REG_MEM, { { 12, 12 }, { 12, 12 }, { 9, 9 }, { 7, 7 } } }, - { CYCLES_BTC_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, - { CYCLES_BTC_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } }, - { CYCLES_BTC_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, - { CYCLES_BTC_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } }, - { CYCLES_BTR_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, - { CYCLES_BTR_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } }, - { CYCLES_BTR_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, - { CYCLES_BTR_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } }, - { CYCLES_BTS_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, - { CYCLES_BTS_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } }, - { CYCLES_BTS_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } }, - { CYCLES_BTS_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } }, - { CYCLES_CALL, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 3, 3 } } }, - { CYCLES_CALL_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, - { CYCLES_CALL_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 4, 4 } } }, - { CYCLES_CALL_INTERSEG, { { 17, 34 }, { 18, 20 }, { 4, 13 }, { 9, 14 } } }, - { CYCLES_CALL_REG_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } }, - { CYCLES_CALL_MEM_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } }, - { CYCLES_JMP_SHORT, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_JMP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_JMP_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_JMP_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, - { CYCLES_JMP_INTERSEG, { { 12, 27 }, { 17, 19 }, { 3, 3 }, { 8, 12 } } }, - { CYCLES_JMP_REG_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 10 } } }, - { CYCLES_JMP_MEM_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 13 } } }, - { CYCLES_RET, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, - { CYCLES_RET_IMM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } }, - { CYCLES_RET_INTERSEG, { { 18, 32 }, { 13, 13 }, { 4, 4 }, { 10, 13 } } }, - { CYCLES_RET_IMM_INTERSEG, { { 18, 32 }, { 14, 14 }, { 4, 4 }, { 10, 13 } } }, - { CYCLES_JCC_DISP8, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_JCC_FULL_DISP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_JCC_DISP8_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_JCC_FULL_DISP_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_JCXZ, { { 9, 9 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } }, - { CYCLES_JCXZ_NOBRANCH, { { 5, 5 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } }, - { CYCLES_LOOP, { { 11, 11 }, { 6, 6 }, { 5, 5 }, { 2, 2 } } }, - { CYCLES_LOOPZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } }, - { CYCLES_LOOPNZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } }, - { CYCLES_SETCC_REG, { { 4, 4 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_SETCC_MEM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_ENTER, { { 10, 10 }, { 14, 14 }, { 11, 11 }, { 13, 13 } } }, - { CYCLES_LEAVE, { { 4, 4 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_INT, { { 37, 37 }, { 30, 30 }, { 16, 16 }, { 19, 19 } } }, - { CYCLES_INT3, { { 33, 33 }, { 26, 26 }, { 13, 13 }, { 19, 19 } } }, - { CYCLES_INTO_OF1, { { 35, 35 }, { 28, 28 }, { 13, 13 }, { 19, 19 } } }, - { CYCLES_INTO_OF0, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } }, - { CYCLES_BOUND_IN_RANGE, { { 10, 10 }, { 7, 7 }, { 8, 8 }, { 7, 7 } } }, - { CYCLES_BOUND_OUT_RANGE, { { 44, 44 }, { 7, 7 }, { 8, 8 }, { 8, 8 } } }, - { CYCLES_IRET, { { 22, 22 }, { 15, 15 }, { 8, 8 }, { 13, 13 } } }, - { CYCLES_HLT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 10, 10 } } }, - { CYCLES_MOV_REG_CR0, { { 11, 11 }, { 16, 16 }, { 16, 16 }, { 20, 18 } } }, - { CYCLES_MOV_REG_CR2, { { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } }, - { CYCLES_MOV_REG_CR3, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 6 } } }, - { CYCLES_MOV_CR_REG, { { 6, 6 }, { 4, 4 }, { 4, 4 }, { 6, 6 } } }, - { CYCLES_MOV_REG_DR0_3, { { 22, 22 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } }, - { CYCLES_MOV_REG_DR6_7, { { 16, 16 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } }, - { CYCLES_MOV_DR6_7_REG, { { 14, 14 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } }, - { CYCLES_MOV_DR0_3_REG, { { 22, 22 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } }, - { CYCLES_MOV_REG_TR6_7, { { 12, 12 }, { 4, 4 }, { 4, 4 }, { 11, 11 } } }, - { CYCLES_MOV_TR6_7_REG, { { 12, 12 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } }, - { CYCLES_NOP, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_WAIT, { { 7, 7 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_ARPL_REG, { { 0, 20 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } }, - { CYCLES_ARPL_MEM, { { 0, 21 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } }, - { CYCLES_LAR_REG, { { 0, 15 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } }, - { CYCLES_LAR_MEM, { { 0, 16 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } }, - { CYCLES_LGDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } }, - { CYCLES_LIDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } }, - { CYCLES_LLDT_REG, { { 0, 20 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } }, - { CYCLES_LLDT_MEM, { { 0, 24 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } }, - { CYCLES_LMSW_REG, { { 11, 11 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } }, - { CYCLES_LMSW_MEM, { { 14, 14 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } }, - { CYCLES_LSL_REG, { { 0, 21 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } }, - { CYCLES_LSL_MEM, { { 0, 22 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } }, - { CYCLES_LTR_REG, { { 0, 23 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } }, - { CYCLES_LTR_MEM, { { 0, 27 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } }, - { CYCLES_SGDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } }, - { CYCLES_SIDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } }, - { CYCLES_SLDT_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 1 } } }, - { CYCLES_SLDT_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 1 } } }, - { CYCLES_SMSW_REG, { { 2, 2 }, { 2, 2 }, { 4, 4 }, { 4, 4 } } }, - { CYCLES_SMSW_MEM, { { 2, 2 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } }, - { CYCLES_STR_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 3 } } }, - { CYCLES_STR_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 3 } } }, - { CYCLES_VERR_REG, { { 0, 10 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, - { CYCLES_VERR_MEM, { { 0, 11 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, - { CYCLES_VERW_REG, { { 0, 15 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, - { CYCLES_VERW_MEM, { { 0, 16 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } }, - { CYCLES_LOCK, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } }, - - // i486+ - { CYCLES_BSWAP, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 6, 6 } } }, - { CYCLES_CMPXCHG, { { 0, 0 }, { 6, 6 }, { 5, 5 }, { 6, 6 } } }, - { CYCLES_INVD, { { 0, 0 }, { 4, 4 }, { 15, 15 }, { 20, 20 } } }, - { CYCLES_XADD, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 2, 2 } } }, - - // Pentium+ - { CYCLES_CMPXCHG8B, { { 0, 0 }, { 0, 0 }, { 10, 10 }, { 6, 6 } } }, - { CYCLES_CPUID, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } }, - { CYCLES_CPUID_EAX1, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } }, - { CYCLES_RDTSC, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } }, - { CYCLES_RSM, { { 0, 0 }, { 0, 0 }, { 82, 82 }, { 57, 57 } } }, - { CYCLES_RDMSR, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } }, - - // FPU - { CYCLES_FABS, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FADD, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_FBLD, { { 0, 0 }, { 70, 70 }, { 48, 48 }, { 1, 1 } } }, - { CYCLES_FBSTP, { { 0, 0 }, {172,172 }, {148,148 }, { 1, 1 } } }, - { CYCLES_FCHS, { { 0, 0 }, { 6, 6 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FCLEX, { { 0, 0 }, { 7, 7 }, { 9, 9 }, { 1, 1 } } }, - { CYCLES_FCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } }, - { CYCLES_FCOS, { { 0, 0 }, {255,255 }, {124,124 }, { 1, 1 } } }, - { CYCLES_FDECSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FDISI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FDIV, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } }, - { CYCLES_FDIVR, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } }, - { CYCLES_FENI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FFREE, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FIADD, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } }, - { CYCLES_FICOM, { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 1, 1 } } }, - { CYCLES_FIDIV, { { 0, 0 }, { 85, 85 }, { 42, 42 }, { 1, 1 } } }, - { CYCLES_FILD, { { 0, 0 }, { 13, 13 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_FIMUL, { { 0, 0 }, { 23, 23 }, { 7, 7 }, { 1, 1 } } }, - { CYCLES_FINCSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FINIT, { { 0, 0 }, { 17, 17 }, { 16, 16 }, { 1, 1 } } }, - { CYCLES_FIST, { { 0, 0 }, { 29, 29 }, { 6, 6 }, { 1, 1 } } }, - { CYCLES_FISUB, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } }, - { CYCLES_FLD, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FLDZ, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_FLD1, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_FLDL2E, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, - { CYCLES_FLDL2T, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, - { CYCLES_FLDLG2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, - { CYCLES_FLDLN2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, - { CYCLES_FLDPI, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } }, - { CYCLES_FLDCW, { { 0, 0 }, { 4, 4 }, { 7, 7 }, { 1, 1 } } }, - { CYCLES_FLDENV, { { 0, 0 }, { 44, 44 }, { 37, 37 }, { 1, 1 } } }, - { CYCLES_FMUL, { { 0, 0 }, { 16, 16 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_FNOP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FPATAN, { { 0, 0 }, {218,218 }, {173,173 }, { 1, 1 } } }, - { CYCLES_FPREM, { { 0, 0 }, { 70, 70 }, { 16, 16 }, { 1, 1 } } }, - { CYCLES_FPREM1, { { 0, 0 }, { 72, 72 }, { 20, 20 }, { 1, 1 } } }, - { CYCLES_FPTAN, { { 0, 0 }, {200,200 }, {173,173 }, { 1, 1 } } }, - { CYCLES_FRNDINT, { { 0, 0 }, { 21, 21 }, { 9, 9 }, { 1, 1 } } }, - { CYCLES_FRSTOR, { { 0, 0 }, {131,131 }, { 75, 75 }, { 1, 1 } } }, - { CYCLES_FSAVE, { { 0, 0 }, {154,154 }, {127,127 }, { 1, 1 } } }, - { CYCLES_FSCALE, { { 0, 0 }, { 30, 30 }, { 20, 20 }, { 1, 1 } } }, - { CYCLES_FSETPM, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FSIN, { { 0, 0 }, {255,255 }, {126,126 }, { 1, 1 } } }, - { CYCLES_FSINCOS, { { 0, 0 }, {255,255 }, {137,137 }, { 1, 1 } } }, - { CYCLES_FSQRT, { { 0, 0 }, { 83, 83 }, { 70, 70 }, { 1, 1 } } }, - { CYCLES_FST, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FSTCW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_FSTENV, { { 0, 0 }, { 67, 67 }, { 48, 48 }, { 1, 1 } } }, - { CYCLES_FSTSW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } }, - { CYCLES_FSUB, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_FSUBR, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } }, - { CYCLES_FTST, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } }, - { CYCLES_FUCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } }, - { CYCLES_FXAM, { { 0, 0 }, { 8, 8 }, { 21, 21 }, { 1, 1 } } }, - { CYCLES_FXCH, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } }, - { CYCLES_FXTRACT, { { 0, 0 }, { 16, 16 }, { 13, 13 }, { 1, 1 } } }, - { CYCLES_FYL2X, { { 0, 0 }, {196,196 }, {111,111 }, { 1, 1 } } }, - { CYCLES_FYL2XPI, { { 0, 0 }, {171,171 }, {103,103 }, { 1, 1 } } }, - { CYCLES_CMPXCHG_REG_REG_T, { { 0, 0 }, { 6, 6 }, { 6, 6 }, { 6, 6 } } }, - { CYCLES_CMPXCHG_REG_REG_F, { { 0, 0 }, { 9, 9 }, { 9, 9 }, { 9, 9 } } }, - { CYCLES_CMPXCHG_REG_MEM_T, { { 0, 0 }, { 7, 7 }, { 7, 7 }, { 7, 7 } } }, - { CYCLES_CMPXCHG_REG_MEM_F, { { 0, 0 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } }, -}; - -#endif /* __CYCLES_H__ */ diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386.h b/source/src/vm/libcpu_newdev/libcpu_i386/i386.h deleted file mode 100644 index 64b65fc0f..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386.h +++ /dev/null @@ -1,32 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -#pragma once - -#ifndef __I386INTF_H__ -#define __I386INTF_H__ - -#define INPUT_LINE_A20 1 -#define INPUT_LINE_SMI 2 - -struct i386_interface -{ - devcb_write_line smiact; -}; - -// mingw has this defined for 32-bit compiles -#undef i386 - -DECLARE_LEGACY_CPU_DEVICE(I386, i386); -DECLARE_LEGACY_CPU_DEVICE(I386SX, i386SX); -DECLARE_LEGACY_CPU_DEVICE(I486, i486); -DECLARE_LEGACY_CPU_DEVICE(PENTIUM, pentium); -DECLARE_LEGACY_CPU_DEVICE(MEDIAGX, mediagx); -DECLARE_LEGACY_CPU_DEVICE(PENTIUM_PRO, pentium_pro); -DECLARE_LEGACY_CPU_DEVICE(PENTIUM_MMX, pentium_mmx); -DECLARE_LEGACY_CPU_DEVICE(PENTIUM2, pentium2); -DECLARE_LEGACY_CPU_DEVICE(PENTIUM3, pentium3); -DECLARE_LEGACY_CPU_DEVICE(PENTIUM4, pentium4); - - - -#endif /* __I386INTF_H__ */ diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386_base_ext.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386_base_ext.cpp deleted file mode 100644 index 47965678d..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386_base_ext.cpp +++ /dev/null @@ -1,267 +0,0 @@ -#include "./i386_opdef.h" - -int I386_OPS_BASE::i386_translate_address(int intention, offs_t *address, vtlb_entry *entry) -{ - UINT32 a = *address; - UINT32 pdbr = cpustate->cr[3] & 0xfffff000; - UINT32 directory = (a >> 22) & 0x3ff; - UINT32 table = (a >> 12) & 0x3ff; - vtlb_entry perm = 0; - int ret = FALSE; - bool user = (intention & TRANSLATE_USER_MASK) ? true : false; - bool write = (intention & TRANSLATE_WRITE) ? true : false; - bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false; - - if(!(cpustate->cr[0] & 0x80000000)) - { - if(entry) - *entry = 0x77; - return TRUE; - } - - UINT32 page_dir = cpustate->program->read_data32(pdbr + directory * 4); - if(page_dir & 1) - { - if ((page_dir & 0x80) && (cpustate->cr[4] & 0x10)) - { - a = (page_dir & 0xffc00000) | (a & 0x003fffff); - if(debug) - { - *address = a; - return TRUE; - } - perm = get_permissions(page_dir, WP); - if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED)))) - ret = FALSE; - else if(user && !(perm & VTLB_USER_READ_ALLOWED)) - ret = FALSE; - else - { - if(write) - perm |= VTLB_FLAG_DIRTY; - if(!(page_dir & 0x40) && write) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x60); - else if(!(page_dir & 0x20)) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20); - ret = TRUE; - } - } - else - { - UINT32 page_entry = cpustate->program->read_data32((page_dir & 0xfffff000) + (table * 4)); - if(!(page_entry & 1)) - ret = FALSE; - else - { - a = (page_entry & 0xfffff000) | (a & 0xfff); - if(debug) - { - *address = a; - return TRUE; - } - perm = get_permissions(page_entry, WP); - if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED)))) - ret = FALSE; - else if(user && !(perm & VTLB_USER_READ_ALLOWED)) - ret = FALSE; - else - { - if(write) - perm |= VTLB_FLAG_DIRTY; - if(!(page_dir & 0x20)) - cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20); - if(!(page_entry & 0x40) && write) - cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60); - else if(!(page_entry & 0x20)) - cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20); - ret = TRUE; - } - } - } - } - else - ret = FALSE; - if(entry) - *entry = perm; - if(ret) - *address = a; - return ret; -} - -/*********************************************************************************** - MSR ACCESS -***********************************************************************************/ - -// Pentium MSR handling -UINT64 I386_OPS_BASE::pentium_msr_read(UINT32 offset,UINT8 *valid_msr) -{ - switch(offset) - { - // Machine Check Exception (TODO) - case 0x00: - *valid_msr = 1; - popmessage("RDMSR: Reading P5_MC_ADDR"); - return 0; - case 0x01: - *valid_msr = 1; - popmessage("RDMSR: Reading P5_MC_TYPE"); - return 0; - // Time Stamp Counter - case 0x10: - *valid_msr = 1; - popmessage("RDMSR: Reading TSC"); - return cpustate->tsc; - // Event Counters (TODO) - case 0x11: // CESR - *valid_msr = 1; - popmessage("RDMSR: Reading CESR"); - return 0; - case 0x12: // CTR0 - *valid_msr = 1; - return cpustate->perfctr[0]; - case 0x13: // CTR1 - *valid_msr = 1; - return cpustate->perfctr[1]; - default: - if(!(offset & ~0xf)) // 2-f are test registers - { - *valid_msr = 1; - logerror("RDMSR: Reading test MSR %x", offset); - return 0; - } - logerror("RDMSR: invalid P5 MSR read %08x at %08x\n",offset,cpustate->pc-2); - *valid_msr = 0; - return 0; - } - return -1; -} - -void I386_OPS_BASE::pentium_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr) -{ - switch(offset) - { - // Machine Check Exception (TODO) - case 0x00: - popmessage("WRMSR: Writing P5_MC_ADDR"); - *valid_msr = 1; - break; - case 0x01: - popmessage("WRMSR: Writing P5_MC_TYPE"); - *valid_msr = 1; - break; - // Time Stamp Counter - case 0x10: - cpustate->tsc = data; - popmessage("WRMSR: Writing to TSC"); - *valid_msr = 1; - break; - // Event Counters (TODO) - case 0x11: // CESR - popmessage("WRMSR: Writing to CESR"); - *valid_msr = 1; - break; - case 0x12: // CTR0 - cpustate->perfctr[0] = data; - *valid_msr = 1; - break; - case 0x13: // CTR1 - cpustate->perfctr[1] = data; - *valid_msr = 1; - break; - default: - if(!(offset & ~0xf)) // 2-f are test registers - { - *valid_msr = 1; - logerror("WRMSR: Writing test MSR %x", offset); - break; - } - logerror("WRMSR: invalid MSR write %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2); - *valid_msr = 0; - break; - } -} - -// P6 (Pentium Pro, Pentium II, Pentium III) MSR handling -UINT64 I386_OPS_BASE::p6_msr_read(UINT32 offset,UINT8 *valid_msr) -{ - switch(offset) - { - // Machine Check Exception (TODO) - case 0x00: - *valid_msr = 1; - popmessage("RDMSR: Reading P5_MC_ADDR"); - return 0; - case 0x01: - *valid_msr = 1; - popmessage("RDMSR: Reading P5_MC_TYPE"); - return 0; - // Time Stamp Counter - case 0x10: - *valid_msr = 1; - popmessage("RDMSR: Reading TSC"); - return cpustate->tsc; - // Performance Counters (TODO) - case 0xc1: // PerfCtr0 - *valid_msr = 1; - return cpustate->perfctr[0]; - case 0xc2: // PerfCtr1 - *valid_msr = 1; - return cpustate->perfctr[1]; - default: - logerror("RDMSR: unimplemented register called %08x at %08x\n",offset,cpustate->pc-2); - *valid_msr = 1; - return 0; - } - return -1; -} - -void I386_OPS_BASE::p6_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr) -{ - switch(offset) - { - // Time Stamp Counter - case 0x10: - cpustate->tsc = data; - popmessage("WRMSR: Writing to TSC"); - *valid_msr = 1; - break; - // Performance Counters (TODO) - case 0xc1: // PerfCtr0 - cpustate->perfctr[0] = data; - *valid_msr = 1; - break; - case 0xc2: // PerfCtr1 - cpustate->perfctr[1] = data; - *valid_msr = 1; - break; - default: - logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2); - *valid_msr = 1; - break; - } -} - -// PIV (Pentium 4+) -UINT64 I386_OPS_BASE::piv_msr_read(UINT32 offset,UINT8 *valid_msr) -{ - switch(offset) - { - default: - logerror("RDMSR: unimplemented register called %08x at %08x\n",offset,cpustate->pc-2); - *valid_msr = 1; - return 0; - } - return -1; -} - -void I386_OPS_BASE::piv_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr) -{ - switch(offset) - { - default: - logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2); - *valid_msr = 1; - break; - } -} - diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.cpp deleted file mode 100644 index ec547dbeb..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.cpp +++ /dev/null @@ -1,4160 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -/* - Intel 386 emulator - - Written by Ville Linde - - Currently supports: - Intel 386 - Intel 486 - Intel Pentium - Cyrix MediaGX - Intel Pentium MMX - Intel Pentium Pro - Intel Pentium II - Intel Pentium III - Intel Pentium 4 -*/ - -#include "./i386_opdef.h" -#include "./i386ops.h" - -/* seems to be defined on mingw-gcc */ -#undef i386 - -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} - -/*************************************************************************/ - -UINT32 I386_OPS_BASE::i386_load_protected_mode_segment( I386_SREG *seg, UINT64 *desc ) -{ - UINT32 v1,v2; - UINT32 base, limit; - int entry; - - if(!seg->selector) - { - seg->flags = 0; - seg->base = 0; - seg->limit = 0; - seg->d = 0; - seg->valid = false; - return 0; - } - - if ( seg->selector & 0x4 ) - { - base = cpustate->ldtr.base; - limit = cpustate->ldtr.limit; - } else { - base = cpustate->gdtr.base; - limit = cpustate->gdtr.limit; - } - - entry = seg->selector & ~0x7; - if ((limit == 0) || ((UINT32)(entry + 7) > limit)) - return 0; - - v1 = READ32PL0(base + entry ); - v2 = READ32PL0(base + entry + 4 ); - - seg->flags = (v2 >> 8) & 0xf0ff; - seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff); - seg->limit = (v2 & 0xf0000) | (v1 & 0xffff); - if (seg->flags & 0x8000) - seg->limit = (seg->limit << 12) | 0xfff; - seg->d = (seg->flags & 0x4000) ? 1 : 0; - seg->valid = true; - - if(desc) - *desc = ((UINT64)v2<<32)|v1; - return 1; -} - -void I386_OPS_BASE::i386_load_call_gate(I386_CALL_GATE *gate) -{ - UINT32 v1,v2; - UINT32 base,limit; - int entry; - - if ( gate->segment & 0x4 ) - { - base = cpustate->ldtr.base; - limit = cpustate->ldtr.limit; - } else { - base = cpustate->gdtr.base; - limit = cpustate->gdtr.limit; - } - - entry = gate->segment & ~0x7; - if ((limit == 0) || ((UINT32)(entry + 7) > limit)) - return; - - v1 = READ32PL0(base + entry ); - v2 = READ32PL0(base + entry + 4 ); - - /* Note that for task gates, offset and dword_count are not used */ - gate->selector = (v1 >> 16) & 0xffff; - gate->offset = (v1 & 0x0000ffff) | (v2 & 0xffff0000); - gate->ar = (v2 >> 8) & 0xff; - gate->dword_count = v2 & 0x001f; - gate->present = (gate->ar >> 7) & 0x01; - gate->dpl = (gate->ar >> 5) & 0x03; -} - -void I386_OPS_BASE::i386_set_descriptor_accessed( UINT16 selector) -{ - // assume the selector is valid, we don't need to check it again - UINT32 base, addr; - UINT8 rights; - if(!(selector & ~3)) - return; - - if ( selector & 0x4 ) - base = cpustate->ldtr.base; - else - base = cpustate->gdtr.base; - - addr = base + (selector & ~7) + 5; - i386_translate_address(TRANSLATE_READ, &addr, NULL); - rights = cpustate->program->read_data8(addr); - // Should a fault be thrown if the table is read only? - cpustate->program->write_data8(addr, rights | 1); -} - -void I386_OPS_BASE::i386_load_segment_descriptor( int segment ) -{ - if (PROTECTED_MODE) - { - if (!V8086_MODE) - { - i386_load_protected_mode_segment(&cpustate->sreg[segment], NULL ); - { - i386_set_descriptor_accessed(cpustate->sreg[segment].selector); - cpustate->sreg[segment].flags |= 0x0001; - } - } - else - { - cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4; - cpustate->sreg[segment].limit = 0xffff; - cpustate->sreg[segment].flags = (segment == CS) ? 0x00fb : 0x00f3; - cpustate->sreg[segment].d = 0; - cpustate->sreg[segment].valid = true; - } -// if (segment == CS && cpustate->sreg[segment].flags != old_flags) -// debugger_privilege_hook(); - } - else - { - cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4; - cpustate->sreg[segment].d = 0; - cpustate->sreg[segment].valid = true; - - if( segment == CS ) - { - if( !cpustate->performed_intersegment_jump ) - cpustate->sreg[segment].base |= 0xfff00000; - if(cpustate->cpu_version < 0x5000) - cpustate->sreg[segment].flags = 0x93; - } - } -} - -/* Retrieves the stack selector located in the current TSS */ -UINT32 I386_OPS_BASE::i386_get_stack_segment(UINT8 privilege) -{ - UINT32 ret; - if(privilege >= 3) - return 0; - - if(cpustate->task.flags & 8) - ret = READ32PL0((cpustate->task.base+8) + (8*privilege)); - else - ret = READ16PL0((cpustate->task.base+4) + (4*privilege)); - - return ret; -} - -/* Retrieves the stack pointer located in the current TSS */ -UINT32 I386_OPS_BASE::i386_get_stack_ptr(UINT8 privilege) -{ - UINT32 ret; - if(privilege >= 3) - return 0; - - if(cpustate->task.flags & 8) - ret = READ32PL0((cpustate->task.base+4) + (8*privilege)); - else - ret = READ16PL0((cpustate->task.base+2) + (4*privilege)); - - return ret; -} - -UINT32 I386_OPS_BASE::get_flags() -{ - UINT32 f = 0x2; - f |= cpustate->CF; - f |= cpustate->PF << 2; - f |= cpustate->AF << 4; - f |= cpustate->ZF << 6; - f |= cpustate->SF << 7; - f |= cpustate->TF << 8; - f |= cpustate->IF << 9; - f |= cpustate->DF << 10; - f |= cpustate->OF << 11; - f |= cpustate->IOP1 << 12; - f |= cpustate->IOP2 << 13; - f |= cpustate->NT << 14; - f |= cpustate->RF << 16; - f |= cpustate->VM << 17; - f |= cpustate->AC << 18; - f |= cpustate->VIF << 19; - f |= cpustate->VIP << 20; - f |= cpustate->ID << 21; - return (cpustate->eflags & ~cpustate->eflags_mask) | (f & cpustate->eflags_mask); -} - -void I386_OPS_BASE::set_flags( UINT32 f ) -{ - f &= cpustate->eflags_mask;; - cpustate->CF = (f & 0x1) ? 1 : 0; - cpustate->PF = (f & 0x4) ? 1 : 0; - cpustate->AF = (f & 0x10) ? 1 : 0; - cpustate->ZF = (f & 0x40) ? 1 : 0; - cpustate->SF = (f & 0x80) ? 1 : 0; - cpustate->TF = (f & 0x100) ? 1 : 0; - cpustate->IF = (f & 0x200) ? 1 : 0; - cpustate->DF = (f & 0x400) ? 1 : 0; - cpustate->OF = (f & 0x800) ? 1 : 0; - cpustate->IOP1 = (f & 0x1000) ? 1 : 0; - cpustate->IOP2 = (f & 0x2000) ? 1 : 0; - cpustate->NT = (f & 0x4000) ? 1 : 0; - cpustate->RF = (f & 0x10000) ? 1 : 0; - cpustate->VM = (f & 0x20000) ? 1 : 0; - cpustate->AC = (f & 0x40000) ? 1 : 0; - cpustate->VIF = (f & 0x80000) ? 1 : 0; - cpustate->VIP = (f & 0x100000) ? 1 : 0; - cpustate->ID = (f & 0x200000) ? 1 : 0; - cpustate->eflags = f; -} - -void I386_OPS_BASE::sib_byte(UINT8 mod, UINT32* out_ea, UINT8* out_segment) -{ - UINT32 ea = 0; - UINT8 segment = 0; - UINT8 scale, i, base; - UINT8 sib = FETCH(); - scale = (sib >> 6) & 0x3; - i = (sib >> 3) & 0x7; - base = sib & 0x7; - - switch( base ) - { - case 0: ea = REG32(EAX); segment = DS; break; - case 1: ea = REG32(ECX); segment = DS; break; - case 2: ea = REG32(EDX); segment = DS; break; - case 3: ea = REG32(EBX); segment = DS; break; - case 4: ea = REG32(ESP); segment = SS; break; - case 5: - if( mod == 0 ) { - ea = FETCH32(); - segment = DS; - } else if( mod == 1 ) { - ea = REG32(EBP); - segment = SS; - } else if( mod == 2 ) { - ea = REG32(EBP); - segment = SS; - } - break; - case 6: ea = REG32(ESI); segment = DS; break; - case 7: ea = REG32(EDI); segment = DS; break; - } - switch( i ) - { - case 0: ea += REG32(EAX) * (1 << scale); break; - case 1: ea += REG32(ECX) * (1 << scale); break; - case 2: ea += REG32(EDX) * (1 << scale); break; - case 3: ea += REG32(EBX) * (1 << scale); break; - case 4: break; - case 5: ea += REG32(EBP) * (1 << scale); break; - case 6: ea += REG32(ESI) * (1 << scale); break; - case 7: ea += REG32(EDI) * (1 << scale); break; - } - *out_ea = ea; - *out_segment = segment; -} - -void I386_OPS_BASE::modrm_to_EA(UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment) -{ - INT8 disp8; - INT16 disp16; - INT32 disp32; - UINT8 mod = (mod_rm >> 6) & 0x3; - UINT8 rm = mod_rm & 0x7; - UINT32 ea; - UINT8 segment; - - if( mod_rm >= 0xc0 ) - fatalerror("i386: Called modrm_to_EA with modrm value %02X!\n",mod_rm); - - - if( cpustate->address_size ) { - switch( rm ) - { - default: - case 0: ea = REG32(EAX); segment = DS; break; - case 1: ea = REG32(ECX); segment = DS; break; - case 2: ea = REG32(EDX); segment = DS; break; - case 3: ea = REG32(EBX); segment = DS; break; - case 4: sib_byte(mod, &ea, &segment ); break; - case 5: - if( mod == 0 ) { - ea = FETCH32(); segment = DS; - } else { - ea = REG32(EBP); segment = SS; - } - break; - case 6: ea = REG32(ESI); segment = DS; break; - case 7: ea = REG32(EDI); segment = DS; break; - } - if( mod == 1 ) { - disp8 = FETCH(); - ea += (INT32)disp8; - } else if( mod == 2 ) { - disp32 = FETCH32(); - ea += disp32; - } - - if( cpustate->segment_prefix ) - segment = cpustate->segment_override; - - *out_ea = ea; - *out_segment = segment; - - } else { - switch( rm ) - { - default: - case 0: ea = REG16(BX) + REG16(SI); segment = DS; break; - case 1: ea = REG16(BX) + REG16(DI); segment = DS; break; - case 2: ea = REG16(BP) + REG16(SI); segment = SS; break; - case 3: ea = REG16(BP) + REG16(DI); segment = SS; break; - case 4: ea = REG16(SI); segment = DS; break; - case 5: ea = REG16(DI); segment = DS; break; - case 6: - if( mod == 0 ) { - ea = FETCH16(); segment = DS; - } else { - ea = REG16(BP); segment = SS; - } - break; - case 7: ea = REG16(BX); segment = DS; break; - } - if( mod == 1 ) { - disp8 = FETCH(); - ea += (INT32)disp8; - } else if( mod == 2 ) { - disp16 = FETCH16(); - ea += (INT32)disp16; - } - - if( cpustate->segment_prefix ) - segment = cpustate->segment_override; - - *out_ea = ea & 0xffff; - *out_segment = segment; - } -} - -UINT32 I386_OPS_BASE::GetNonTranslatedEA(UINT8 modrm,UINT8 *seg) -{ - UINT8 segment; - UINT32 ea; - modrm_to_EA(modrm, &ea, &segment ); - if(seg) *seg = segment; - return ea; -} - -UINT32 I386_OPS_BASE::GetEA(UINT8 modrm, int rwn, UINT32 size) -{ - UINT8 segment; - UINT32 ea; - modrm_to_EA(modrm, &ea, &segment ); - return i386_translate(segment, ea, rwn, size ); -} - -/* Check segment register for validity when changing privilege level after an RETF */ -void I386_OPS_BASE::i386_check_sreg_validity(int reg) -{ - UINT16 selector = cpustate->sreg[reg].selector; - UINT8 CPL = cpustate->CPL; - UINT8 DPL,RPL; - I386_SREG desc; - int invalid = 0; - - memset(&desc, 0, sizeof(desc)); - desc.selector = selector; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - RPL = selector & 0x03; - - /* Must be within the relevant descriptor table limits */ - if(selector & 0x04) - { - if((selector & ~0x07) > cpustate->ldtr.limit) - invalid = 1; - } - else - { - if((selector & ~0x07) > cpustate->gdtr.limit) - invalid = 1; - } - - /* Must be either a data or readable code segment */ - if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0002)) || (desc.flags & 0x0018) == 0x0010) - invalid = 0; - else - invalid = 1; - - /* If a data segment or non-conforming code segment, then either DPL >= CPL or DPL >= RPL */ - if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0004) == 0) || (desc.flags & 0x0018) == 0x0010) - { - if((DPL < CPL) || (DPL < RPL)) - invalid = 1; - } - - /* if segment is invalid, then segment register is nulled */ - if(invalid != 0) - { - cpustate->sreg[reg].selector = 0; - i386_load_segment_descriptor(reg); - } -} - -int I386_OPS_BASE::i386_limit_check( int seg, UINT32 offset, UINT32 size) -{ - if(PROTECTED_MODE && !V8086_MODE) - { - if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment - { - // compare if greater then 0xffffffff when we're passed the access size - if((offset <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset + size - 1) > 0xffff))) - { - logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x (expand-down)\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset); - return 1; - } - } - else - { - if((offset + size - 1) > cpustate->sreg[seg].limit) - { - logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset); - return 1; - } - } - } - return 0; -} - -void I386_OPS_BASE::i386_sreg_load( UINT16 selector, UINT8 reg, bool *fault) -{ - // Checks done when MOV changes a segment register in protected mode - UINT8 CPL,RPL,DPL; - - CPL = cpustate->CPL; - RPL = selector & 0x0003; - - if(!PROTECTED_MODE || V8086_MODE) - { - cpustate->sreg[reg].selector = selector; - i386_load_segment_descriptor(reg); - if(fault) *fault = false; - return; - } - - if(fault) *fault = true; - if(reg == SS) - { - I386_SREG stack; - - memset(&stack, 0, sizeof(stack)); - stack.selector = selector; - i386_load_protected_mode_segment(&stack,NULL); - DPL = (stack.flags >> 5) & 0x03; - - if((selector & ~0x0003) == 0) - { - logerror("SReg Load (%08x): Selector is null.\n",cpustate->pc); - FAULT(FAULT_GP,0) - } - if(selector & 0x0004) // LDT - { - if((selector & ~0x0007) > cpustate->ldtr.limit) - { - logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - } - else // GDT - { - if((selector & ~0x0007) > cpustate->gdtr.limit) - { - logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - } - if (RPL != CPL) - { - logerror("SReg Load (%08x): Selector RPL does not equal CPL.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0) - { - logerror("SReg Load (%08x): Segment is not a writable data segment.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - if(DPL != CPL) - { - logerror("SReg Load (%08x): Segment DPL does not equal CPL.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - if(!(stack.flags & 0x0080)) - { - logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc); - FAULT(FAULT_SS,selector & ~0x03) - } - } - if(reg == DS || reg == ES || reg == FS || reg == GS) - { - I386_SREG desc; - - if((selector & ~0x0003) == 0) - { - cpustate->sreg[reg].selector = selector; - i386_load_segment_descriptor(reg ); - if(fault) *fault = false; - return; - } - - memset(&desc, 0, sizeof(desc)); - desc.selector = selector; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; - - if(selector & 0x0004) // LDT - { - if((selector & ~0x0007) > cpustate->ldtr.limit) - { - logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - } - else // GDT - { - if((selector & ~0x0007) > cpustate->gdtr.limit) - { - logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - } - if((desc.flags & 0x0018) != 0x10) - { - if((((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18)) || !(desc.flags & 0x10)) - { - logerror("SReg Load (%08x): Segment is not a data segment or readable code segment.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - } - if(((desc.flags & 0x0018) == 0x10) || ((!(desc.flags & 0x0004)) && ((desc.flags & 0x0018) == 0x18))) - { - // if data or non-conforming code segment - if((RPL > DPL) || (CPL > DPL)) - { - logerror("SReg Load (%08x): Selector RPL or CPL is not less or equal to segment DPL.\n",cpustate->pc); - FAULT(FAULT_GP,selector & ~0x03) - } - } - if(!(desc.flags & 0x0080)) - { - logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc); - FAULT(FAULT_NP,selector & ~0x03) - } - } - - cpustate->sreg[reg].selector = selector; - i386_load_segment_descriptor(reg ); - if(fault) *fault = false; -} - -void I386_OPS_BASE::i386_trap(int irq, int irq_gate, int trap_level) -{ - /* I386 Interrupts/Traps/Faults: - * - * 0x00 Divide by zero - * 0x01 Debug exception - * 0x02 NMI - * 0x03 Int3 - * 0x04 Overflow - * 0x05 Array bounds check - * 0x06 Illegal Opcode - * 0x07 FPU not available - * 0x08 Double fault - * 0x09 Coprocessor segment overrun - * 0x0a Invalid task state - * 0x0b Segment not present - * 0x0c Stack exception - * 0x0d General Protection Fault - * 0x0e Page fault - * 0x0f Reserved - * 0x10 Coprocessor error - */ - UINT32 v1, v2; - UINT32 offset, oldflags = get_flags(); - UINT16 segment; - int entry = irq * (PROTECTED_MODE ? 8 : 4); - int SetRPL = 0; - cpustate->lock = false; - - if( !(PROTECTED_MODE) ) - { - /* 16-bit */ - PUSH16(oldflags & 0xffff ); - PUSH16(cpustate->sreg[CS].selector ); - if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1) - PUSH16(cpustate->eip ); - else - PUSH16(cpustate->prev_eip ); - - cpustate->sreg[CS].selector = READ16(cpustate->idtr.base + entry + 2 ); - cpustate->eip = READ16(cpustate->idtr.base + entry ); - - cpustate->TF = 0; - cpustate->IF = 0; - } - else - { - int type; - UINT16 flags; - I386_SREG desc; - UINT8 CPL = cpustate->CPL, DPL = 0; //, RPL = 0; - - /* 32-bit */ - v1 = READ32PL0(cpustate->idtr.base + entry ); - v2 = READ32PL0(cpustate->idtr.base + entry + 4 ); - offset = (v2 & 0xffff0000) | (v1 & 0xffff); - segment = (v1 >> 16) & 0xffff; - type = (v2>>8) & 0x1F; - flags = (v2>>8) & 0xf0ff; - - if(trap_level == 2) - { - logerror("IRQ: Double fault.\n"); - FAULT_EXP(FAULT_DF,0); - } - if(trap_level >= 3) - { - logerror("IRQ: Triple fault. CPU reset.\n"); - CPU_RESET_CALL(i386); //! - cpustate->shutdown = 1; - return; - } - - /* segment privilege checks */ - if(entry >= cpustate->idtr.limit) - { - logerror("IRQ (%08x): Vector %02xh is past IDT limit.\n",cpustate->pc,entry); - FAULT_EXP(FAULT_GP,entry+2) - } - /* segment must be interrupt gate, trap gate, or task gate */ - if(type != 0x05 && type != 0x06 && type != 0x07 && type != 0x0e && type != 0x0f) - { - logerror("IRQ#%02x (%08x): Vector segment %04x is not an interrupt, trap or task gate.\n",irq,cpustate->pc,segment); - FAULT_EXP(FAULT_GP,entry+2) - } - - if(cpustate->ext == 0) // if software interrupt (caused by INT/INTO/INT3) - { - if(((flags >> 5) & 0x03) < CPL) - { - logerror("IRQ (%08x): Software IRQ - gate DPL is less than CPL.\n",cpustate->pc); - FAULT_EXP(FAULT_GP,entry+2) - } - if(V8086_MODE) - { - if((!cpustate->IOP1 || !cpustate->IOP2) && (cpustate->opcode != 0xcc)) - { - logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc); - FAULT(FAULT_GP,0) - } - - } - } - - if((flags & 0x0080) == 0) - { - logerror("IRQ: Vector segment is not present.\n"); - FAULT_EXP(FAULT_NP,entry+2) - } - - if(type == 0x05) - { - /* Task gate */ - memset(&desc, 0, sizeof(desc)); - desc.selector = segment; - i386_load_protected_mode_segment(&desc,NULL); - if(segment & 0x04) - { - logerror("IRQ: Task gate: TSS is not in the GDT.\n"); - FAULT_EXP(FAULT_TS,segment & ~0x03); - } - else - { - if(segment > cpustate->gdtr.limit) - { - logerror("IRQ: Task gate: TSS is past GDT limit.\n"); - FAULT_EXP(FAULT_TS,segment & ~0x03); - } - } - if((desc.flags & 0x000f) != 0x09 && (desc.flags & 0x000f) != 0x01) - { - logerror("IRQ: Task gate: TSS is not an available TSS.\n"); - FAULT_EXP(FAULT_TS,segment & ~0x03); - } - if((desc.flags & 0x0080) == 0) - { - logerror("IRQ: Task gate: TSS is not present.\n"); - FAULT_EXP(FAULT_NP,segment & ~0x03); - } - if(!(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)) - cpustate->eip = cpustate->prev_eip; - if(desc.flags & 0x08) - i386_task_switch(desc.selector,1); - else - i286_task_switch(desc.selector,1); - return; - } - else - { - /* Interrupt or Trap gate */ - memset(&desc, 0, sizeof(desc)); - desc.selector = segment; - i386_load_protected_mode_segment(&desc,NULL); - CPL = cpustate->CPL; // current privilege level - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level -// RPL = segment & 0x03; // requested privilege level - - if((segment & ~0x03) == 0) - { - logerror("IRQ: Gate segment is null.\n"); - FAULT_EXP(FAULT_GP,cpustate->ext) - } - if(segment & 0x04) - { - if((segment & ~0x07) > cpustate->ldtr.limit) - { - logerror("IRQ: Gate segment is past LDT limit.\n"); - FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) - } - } - else - { - if((segment & ~0x07) > cpustate->gdtr.limit) - { - logerror("IRQ: Gate segment is past GDT limit.\n"); - FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) - } - } - if((desc.flags & 0x0018) != 0x18) - { - logerror("IRQ: Gate descriptor is not a code segment.\n"); - FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) - } - if((desc.flags & 0x0080) == 0) - { - logerror("IRQ: Gate segment is not present.\n"); - FAULT_EXP(FAULT_NP,(segment & 0x03)+cpustate->ext) - } - if((desc.flags & 0x0004) == 0 && (DPL < CPL)) - { - /* IRQ to inner privilege */ - I386_SREG stack; - UINT32 newESP,oldSS,oldESP; - - if(V8086_MODE && DPL) - { - logerror("IRQ: Gate to CPL>0 from VM86 mode.\n"); - FAULT_EXP(FAULT_GP,segment & ~0x03); - } - /* Check new stack segment in TSS */ - memset(&stack, 0, sizeof(stack)); - stack.selector = i386_get_stack_segment(DPL); - i386_load_protected_mode_segment(&stack,NULL); - oldSS = cpustate->sreg[SS].selector; - if(flags & 0x0008) - oldESP = REG32(ESP); - else - oldESP = REG16(SP); - if((stack.selector & ~0x03) == 0) - { - logerror("IRQ: New stack selector is null.\n"); - FAULT_EXP(FAULT_GP,cpustate->ext) - } - if(stack.selector & 0x04) - { - if((stack.selector & ~0x07) > cpustate->ldtr.base) - { - logerror("IRQ: New stack selector is past LDT limit.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - } - else - { - if((stack.selector & ~0x07) > cpustate->gdtr.base) - { - logerror("IRQ: New stack selector is past GDT limit.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - } - if((stack.selector & 0x03) != DPL) - { - logerror("IRQ: New stack selector RPL is not equal to code segment DPL.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - if(((stack.flags >> 5) & 0x03) != DPL) - { - logerror("IRQ: New stack segment DPL is not equal to code segment DPL.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0) - { - logerror("IRQ: New stack segment is not a writable data segment.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT) - } - if((stack.flags & 0x0080) == 0) - { - logerror("IRQ: New stack segment is not present.\n"); - FAULT_EXP(FAULT_SS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT) - } - newESP = i386_get_stack_ptr(DPL); - if(type & 0x08) // 32-bit gate - { - if(((newESP < (V8086_MODE?36:20)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?36:20))) && (stack.flags & 0x4))) - { - logerror("IRQ: New stack has no space for return addresses.\n"); - FAULT_EXP(FAULT_SS,0) - } - } - else // 16-bit gate - { - newESP &= 0xffff; - if(((newESP < (V8086_MODE?18:10)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?18:10))) && (stack.flags & 0x4))) - { - logerror("IRQ: New stack has no space for return addresses.\n"); - FAULT_EXP(FAULT_SS,0) - } - } - if(offset > desc.limit) - { - logerror("IRQ: New EIP is past code segment limit.\n"); - FAULT_EXP(FAULT_GP,0) - } - /* change CPL before accessing the stack */ - cpustate->CPL = DPL; - /* check for page fault at new stack TODO: check if stack frame crosses page boundary */ - WRITE_TEST(stack.base+newESP-1); - /* Load new stack segment descriptor */ - cpustate->sreg[SS].selector = stack.selector; - i386_load_protected_mode_segment(&cpustate->sreg[SS],NULL); - i386_set_descriptor_accessed(stack.selector); - REG32(ESP) = newESP; - if(V8086_MODE) - { - //logerror("IRQ (%08x): Interrupt during V8086 task\n",cpustate->pc); - if(type & 0x08) - { - PUSH32SEG(cpustate->sreg[GS].selector & 0xffff); - PUSH32SEG(cpustate->sreg[FS].selector & 0xffff); - PUSH32SEG(cpustate->sreg[DS].selector & 0xffff); - PUSH32SEG(cpustate->sreg[ES].selector & 0xffff); - } - else - { - PUSH16(cpustate->sreg[GS].selector); - PUSH16(cpustate->sreg[FS].selector); - PUSH16(cpustate->sreg[DS].selector); - PUSH16(cpustate->sreg[ES].selector); - } - cpustate->sreg[GS].selector = 0; - cpustate->sreg[FS].selector = 0; - cpustate->sreg[DS].selector = 0; - cpustate->sreg[ES].selector = 0; - cpustate->VM = 0; - i386_load_segment_descriptor(GS); - i386_load_segment_descriptor(FS); - i386_load_segment_descriptor(DS); - i386_load_segment_descriptor(ES); - } - if(type & 0x08) - { - // 32-bit gate - PUSH32SEG(oldSS); - PUSH32(oldESP); - } - else - { - // 16-bit gate - PUSH16(oldSS); - PUSH16(oldESP); - } - SetRPL = 1; - } - else - { - int stack_limit; - if((desc.flags & 0x0004) || (DPL == CPL)) - { - /* IRQ to same privilege */ - if(V8086_MODE && !cpustate->ext) - { - logerror("IRQ: Gate to same privilege from VM86 mode.\n"); - FAULT_EXP(FAULT_GP,segment & ~0x03); - } - if(type == 0x0e || type == 0x0f) // 32-bit gate - stack_limit = 10; - else - stack_limit = 6; - // TODO: Add check for error code (2 extra bytes) - if((int)(REG32(ESP)) < stack_limit) - { - logerror("IRQ: Stack has no space left (needs %i bytes).\n",stack_limit); - FAULT_EXP(FAULT_SS,0) - } - if(offset > desc.limit) - { - logerror("IRQ: Gate segment offset is past segment limit.\n"); - FAULT_EXP(FAULT_GP,0) - } - SetRPL = 1; - } - else - { - logerror("IRQ: Gate descriptor is non-conforming, and DPL does not equal CPL.\n"); - FAULT_EXP(FAULT_GP,segment) - } - } - } - UINT32 tempSP = REG32(ESP); - try - { - // this is ugly but the alternative is worse - if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate - { - PUSH16(oldflags & 0xffff ); - PUSH16(cpustate->sreg[CS].selector ); - if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1) - PUSH16(cpustate->eip ); - else - PUSH16(cpustate->prev_eip ); - } - else - { - PUSH32(oldflags & 0x00ffffff ); - PUSH32SEG(cpustate->sreg[CS].selector ); - if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1) - PUSH32(cpustate->eip ); - else - PUSH32(cpustate->prev_eip ); - } - } - catch(UINT64 e) - { - REG32(ESP) = tempSP; - throw e; - } - if(SetRPL != 0) - segment = (segment & ~0x03) | cpustate->CPL; - cpustate->sreg[CS].selector = segment; - cpustate->eip = offset; - - if(type == 0x0e || type == 0x06) - cpustate->IF = 0; - cpustate->TF = 0; - cpustate->NT = 0; - } - - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); - -} - -void I386_OPS_BASE::i386_trap_with_error(int irq, int irq_gate, int trap_level, UINT32 error) -{ - i386_trap(irq,irq_gate,trap_level); - if(irq == 8 || irq == 10 || irq == 11 || irq == 12 || irq == 13 || irq == 14) - { - // for these exceptions, an error code is pushed onto the stack by the processor. - // no error code is pushed for software interrupts, either. - if(PROTECTED_MODE) - { - UINT32 entry = irq * 8; - UINT32 v2,type; - v2 = READ32PL0(cpustate->idtr.base + entry + 4 ); - type = (v2>>8) & 0x1F; - if(type == 5) - { - v2 = READ32PL0(cpustate->idtr.base + entry); - v2 = READ32PL0(cpustate->gdtr.base + ((v2 >> 16) & 0xfff8) + 4); - type = (v2>>8) & 0x1F; - } - if(type >= 9) - PUSH32(error); - else - PUSH16(error); - } - else - PUSH16(error); - } -} - - -void I386_OPS_BASE::i286_task_switch( UINT16 selector, UINT8 nested) -{ - UINT32 tss; - I386_SREG seg; - UINT16 old_task; - UINT8 ar_byte; // access rights byte - - /* TODO: Task State Segment privilege checks */ - - /* For tasks that aren't nested, clear the busy bit in the task's descriptor */ - if(nested == 0) - { - if(cpustate->task.segment & 0x0004) - { - ar_byte = READ8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5); - WRITE8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02); - } - else - { - ar_byte = READ8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5); - WRITE8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02); - } - } - - /* Save the state of the current task in the current TSS (TR register base) */ - tss = cpustate->task.base; - WRITE16(tss+0x0e,cpustate->eip & 0x0000ffff); - WRITE16(tss+0x10,get_flags() & 0x0000ffff); - WRITE16(tss+0x12,REG16(AX)); - WRITE16(tss+0x14,REG16(CX)); - WRITE16(tss+0x16,REG16(DX)); - WRITE16(tss+0x18,REG16(BX)); - WRITE16(tss+0x1a,REG16(SP)); - WRITE16(tss+0x1c,REG16(BP)); - WRITE16(tss+0x1e,REG16(SI)); - WRITE16(tss+0x20,REG16(DI)); - WRITE16(tss+0x22,cpustate->sreg[ES].selector); - WRITE16(tss+0x24,cpustate->sreg[CS].selector); - WRITE16(tss+0x26,cpustate->sreg[SS].selector); - WRITE16(tss+0x28,cpustate->sreg[DS].selector); - - old_task = cpustate->task.segment; - - /* Load task register with the selector of the incoming task */ - cpustate->task.segment = selector; - memset(&seg, 0, sizeof(seg)); - seg.selector = cpustate->task.segment; - i386_load_protected_mode_segment(&seg,NULL); - cpustate->task.limit = seg.limit; - cpustate->task.base = seg.base; - cpustate->task.flags = seg.flags; - - /* Set TS bit in CR0 */ - cpustate->cr[0] |= 0x08; - - /* Load incoming task state from the new task's TSS */ - tss = cpustate->task.base; - cpustate->ldtr.segment = READ16(tss+0x2a) & 0xffff; - seg.selector = cpustate->ldtr.segment; - i386_load_protected_mode_segment(&seg,NULL); - cpustate->ldtr.limit = seg.limit; - cpustate->ldtr.base = seg.base; - cpustate->ldtr.flags = seg.flags; - cpustate->eip = READ16(tss+0x0e); - set_flags(READ16(tss+0x10)); - REG16(AX) = READ16(tss+0x12); - REG16(CX) = READ16(tss+0x14); - REG16(DX) = READ16(tss+0x16); - REG16(BX) = READ16(tss+0x18); - REG16(SP) = READ16(tss+0x1a); - REG16(BP) = READ16(tss+0x1c); - REG16(SI) = READ16(tss+0x1e); - REG16(DI) = READ16(tss+0x20); - cpustate->sreg[ES].selector = READ16(tss+0x22) & 0xffff; - i386_load_segment_descriptor(ES); - cpustate->sreg[CS].selector = READ16(tss+0x24) & 0xffff; - i386_load_segment_descriptor(CS); - cpustate->sreg[SS].selector = READ16(tss+0x26) & 0xffff; - i386_load_segment_descriptor(SS); - cpustate->sreg[DS].selector = READ16(tss+0x28) & 0xffff; - i386_load_segment_descriptor(DS); - - /* Set the busy bit in the new task's descriptor */ - if(selector & 0x0004) - { - ar_byte = READ8(cpustate->ldtr.base + (selector & ~0x0007) + 5); - WRITE8(cpustate->ldtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02); - } - else - { - ar_byte = READ8(cpustate->gdtr.base + (selector & ~0x0007) + 5); - WRITE8(cpustate->gdtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02); - } - - /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS, - and set the NT flag in the EFLAGS register */ - if(nested != 0) - { - WRITE16(tss+0,old_task); - cpustate->NT = 1; - } - CHANGE_PC(cpustate->eip); - - cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3; -// printf("286 Task Switch from selector %04x to %04x\n",old_task,selector); -} - -void I386_OPS_BASE::i386_task_switch( UINT16 selector, UINT8 nested) -{ - UINT32 tss; - I386_SREG seg; - UINT16 old_task; - UINT8 ar_byte; // access rights byte - UINT32 oldcr3 = cpustate->cr[3]; - - /* TODO: Task State Segment privilege checks */ - - /* For tasks that aren't nested, clear the busy bit in the task's descriptor */ - if(nested == 0) - { - if(cpustate->task.segment & 0x0004) - { - ar_byte = READ8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5); - WRITE8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02); - } - else - { - ar_byte = READ8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5); - WRITE8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02); - } - } - - /* Save the state of the current task in the current TSS (TR register base) */ - tss = cpustate->task.base; - WRITE32(tss+0x1c,cpustate->cr[3]); // correct? - WRITE32(tss+0x20,cpustate->eip); - WRITE32(tss+0x24,get_flags()); - WRITE32(tss+0x28,REG32(EAX)); - WRITE32(tss+0x2c,REG32(ECX)); - WRITE32(tss+0x30,REG32(EDX)); - WRITE32(tss+0x34,REG32(EBX)); - WRITE32(tss+0x38,REG32(ESP)); - WRITE32(tss+0x3c,REG32(EBP)); - WRITE32(tss+0x40,REG32(ESI)); - WRITE32(tss+0x44,REG32(EDI)); - WRITE32(tss+0x48,cpustate->sreg[ES].selector); - WRITE32(tss+0x4c,cpustate->sreg[CS].selector); - WRITE32(tss+0x50,cpustate->sreg[SS].selector); - WRITE32(tss+0x54,cpustate->sreg[DS].selector); - WRITE32(tss+0x58,cpustate->sreg[FS].selector); - WRITE32(tss+0x5c,cpustate->sreg[GS].selector); - - old_task = cpustate->task.segment; - - /* Load task register with the selector of the incoming task */ - cpustate->task.segment = selector; - memset(&seg, 0, sizeof(seg)); - seg.selector = cpustate->task.segment; - i386_load_protected_mode_segment(&seg,NULL); - cpustate->task.limit = seg.limit; - cpustate->task.base = seg.base; - cpustate->task.flags = seg.flags; - - /* Set TS bit in CR0 */ - cpustate->cr[0] |= 0x08; - - /* Load incoming task state from the new task's TSS */ - tss = cpustate->task.base; - cpustate->ldtr.segment = READ32(tss+0x60) & 0xffff; - seg.selector = cpustate->ldtr.segment; - i386_load_protected_mode_segment(&seg,NULL); - cpustate->ldtr.limit = seg.limit; - cpustate->ldtr.base = seg.base; - cpustate->ldtr.flags = seg.flags; - cpustate->eip = READ32(tss+0x20); - set_flags(READ32(tss+0x24)); - REG32(EAX) = READ32(tss+0x28); - REG32(ECX) = READ32(tss+0x2c); - REG32(EDX) = READ32(tss+0x30); - REG32(EBX) = READ32(tss+0x34); - REG32(ESP) = READ32(tss+0x38); - REG32(EBP) = READ32(tss+0x3c); - REG32(ESI) = READ32(tss+0x40); - REG32(EDI) = READ32(tss+0x44); - cpustate->sreg[ES].selector = READ32(tss+0x48) & 0xffff; - i386_load_segment_descriptor(ES); - cpustate->sreg[CS].selector = READ32(tss+0x4c) & 0xffff; - i386_load_segment_descriptor(CS); - cpustate->sreg[SS].selector = READ32(tss+0x50) & 0xffff; - i386_load_segment_descriptor(SS); - cpustate->sreg[DS].selector = READ32(tss+0x54) & 0xffff; - i386_load_segment_descriptor(DS); - cpustate->sreg[FS].selector = READ32(tss+0x58) & 0xffff; - i386_load_segment_descriptor(FS); - cpustate->sreg[GS].selector = READ32(tss+0x5c) & 0xffff; - i386_load_segment_descriptor(GS); - /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS, - and set the NT flag in the EFLAGS register before setting cr3 as the old tss address might be gone */ - if(nested != 0) - { - WRITE32(tss+0,old_task); - cpustate->NT = 1; - } - cpustate->cr[3] = READ32(tss+0x1c); // CR3 (PDBR) - if(oldcr3 != cpustate->cr[3]) - vtlb_flush_dynamic(cpustate->vtlb); - - /* Set the busy bit in the new task's descriptor */ - if(selector & 0x0004) - { - ar_byte = READ8(cpustate->ldtr.base + (selector & ~0x0007) + 5); - WRITE8(cpustate->ldtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02); - } - else - { - ar_byte = READ8(cpustate->gdtr.base + (selector & ~0x0007) + 5); - WRITE8(cpustate->gdtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02); - } - - CHANGE_PC(cpustate->eip); - - cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3; -// printf("386 Task Switch from selector %04x to %04x\n",old_task,selector); -} - -void I386_OPS_BASE::i386_check_irq_line() -{ - if(!cpustate->smm && cpustate->smi) - { - pentium_smi(); - return; - } - - /* Check if the interrupts are enabled */ - if ( (cpustate->irq_state) && cpustate->IF ) - { - cpustate->cycles -= 2; - i386_trap(cpustate->pic->get_intr_ack(), 1, 0); - cpustate->irq_state = 0; - } -} - -void I386_OPS_BASE::i386_protected_mode_jump( UINT16 seg, UINT32 off, int indirect, int operand32) -{ - I386_SREG desc; - I386_CALL_GATE call_gate; - UINT8 CPL,DPL,RPL; - UINT8 SetRPL = 0; - UINT16 segment = seg; - UINT32 offset = off; - - /* Check selector is not null */ - if((segment & ~0x03) == 0) - { - logerror("JMP: Segment is null.\n"); - FAULT(FAULT_GP,0) - } - /* Selector is within descriptor table limit */ - if((segment & 0x04) == 0) - { - /* check GDT limit */ - if((segment & ~0x07) > (cpustate->gdtr.limit)) - { - logerror("JMP: Segment is past GDT limit.\n"); - FAULT(FAULT_GP,segment & 0xfffc) - } - } - else - { - /* check LDT limit */ - if((segment & ~0x07) > (cpustate->ldtr.limit)) - { - logerror("JMP: Segment is past LDT limit.\n"); - FAULT(FAULT_GP,segment & 0xfffc) - } - } - /* Determine segment type */ - memset(&desc, 0, sizeof(desc)); - desc.selector = segment; - i386_load_protected_mode_segment(&desc,NULL); - CPL = cpustate->CPL; // current privilege level - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - RPL = segment & 0x03; // requested privilege level - if((desc.flags & 0x0018) == 0x0018) - { - /* code segment */ - if((desc.flags & 0x0004) == 0) - { - /* non-conforming */ - if(RPL > CPL) - { - logerror("JMP: RPL %i is less than CPL %i\n",RPL,CPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - if(DPL != CPL) - { - logerror("JMP: DPL %i is not equal CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - } - else - { - /* conforming */ - if(DPL > CPL) - { - logerror("JMP: DPL %i is less than CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - } - SetRPL = 1; - if((desc.flags & 0x0080) == 0) - { - logerror("JMP: Segment is not present\n"); - FAULT(FAULT_NP,segment & 0xfffc) - } - if(offset > desc.limit) - { - logerror("JMP: Offset is past segment limit\n"); - FAULT(FAULT_GP,0) - } - } - else - { - if((desc.flags & 0x0010) != 0) - { - logerror("JMP: Segment is a data segment\n"); - FAULT(FAULT_GP,segment & 0xfffc) // #GP (cannot execute code in a data segment) - } - else - { - switch(desc.flags & 0x000f) - { - case 0x01: // 286 Available TSS - case 0x09: // 386 Available TSS - logerror("JMP: Available 386 TSS at %08x\n",cpustate->pc); - memset(&desc, 0, sizeof(desc)); - desc.selector = segment; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - if(DPL < CPL) - { - logerror("JMP: TSS: DPL %i is less than CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - if(DPL < RPL) - { - logerror("JMP: TSS: DPL %i is less than TSS RPL %i\n",DPL,RPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - if((desc.flags & 0x0080) == 0) - { - logerror("JMP: TSS: Segment is not present\n"); - FAULT(FAULT_GP,segment & 0xfffc) - } - if(desc.flags & 0x0008) - i386_task_switch(desc.selector,0); - else - i286_task_switch(desc.selector,0); - return; - case 0x04: // 286 Call Gate - case 0x0c: // 386 Call Gate - //logerror("JMP: Call gate at %08x\n",cpustate->pc); - SetRPL = 1; - memset(&call_gate, 0, sizeof(call_gate)); - call_gate.segment = segment; - i386_load_call_gate(&call_gate); - DPL = call_gate.dpl; - if(DPL < CPL) - { - logerror("JMP: Call Gate: DPL %i is less than CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - if(DPL < RPL) - { - logerror("JMP: Call Gate: DPL %i is less than RPL %i\n",DPL,RPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - if((desc.flags & 0x0080) == 0) - { - logerror("JMP: Call Gate: Segment is not present\n"); - FAULT(FAULT_NP,segment & 0xfffc) - } - /* Now we examine the segment that the call gate refers to */ - if(call_gate.selector == 0) - { - logerror("JMP: Call Gate: Gate selector is null\n"); - FAULT(FAULT_GP,0) - } - if(call_gate.selector & 0x04) - { - if((call_gate.selector & ~0x07) > cpustate->ldtr.limit) - { - logerror("JMP: Call Gate: Gate Selector is past LDT segment limit\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - } - else - { - if((call_gate.selector & ~0x07) > cpustate->gdtr.limit) - { - logerror("JMP: Call Gate: Gate Selector is past GDT segment limit\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - } - desc.selector = call_gate.selector; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; - if((desc.flags & 0x0018) != 0x18) - { - logerror("JMP: Call Gate: Gate does not point to a code segment\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - if((desc.flags & 0x0004) == 0) - { // non-conforming - if(DPL != CPL) - { - logerror("JMP: Call Gate: Gate DPL does not equal CPL\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - } - else - { // conforming - if(DPL > CPL) - { - logerror("JMP: Call Gate: Gate DPL is greater than CPL\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - } - if((desc.flags & 0x0080) == 0) - { - logerror("JMP: Call Gate: Gate Segment is not present\n"); - FAULT(FAULT_NP,call_gate.selector & 0xfffc) - } - if(call_gate.offset > desc.limit) - { - logerror("JMP: Call Gate: Gate offset is past Gate segment limit\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - segment = call_gate.selector; - offset = call_gate.offset; - break; - case 0x05: // Task Gate - logerror("JMP: Task gate at %08x\n",cpustate->pc); - memset(&call_gate, 0, sizeof(call_gate)); - call_gate.segment = segment; - i386_load_call_gate(&call_gate); - DPL = call_gate.dpl; - if(DPL < CPL) - { - logerror("JMP: Task Gate: Gate DPL %i is less than CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - if(DPL < RPL) - { - logerror("JMP: Task Gate: Gate DPL %i is less than CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,segment & 0xfffc) - } - if(call_gate.present == 0) - { - logerror("JMP: Task Gate: Gate is not present.\n"); - FAULT(FAULT_GP,segment & 0xfffc) - } - /* Check the TSS that the task gate points to */ - desc.selector = call_gate.selector; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - RPL = call_gate.selector & 0x03; // requested privilege level - if(call_gate.selector & 0x04) - { - logerror("JMP: Task Gate TSS: TSS must be global.\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - else - { - if((call_gate.selector & ~0x07) > cpustate->gdtr.limit) - { - logerror("JMP: Task Gate TSS: TSS is past GDT limit.\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - } - if((call_gate.ar & 0x000f) == 0x0009 || (call_gate.ar & 0x000f) == 0x0001) - { - logerror("JMP: Task Gate TSS: Segment is not an available TSS.\n"); - FAULT(FAULT_GP,call_gate.selector & 0xfffc) - } - if(call_gate.present == 0) - { - logerror("JMP: Task Gate TSS: TSS is not present.\n"); - FAULT(FAULT_NP,call_gate.selector & 0xfffc) - } - if(call_gate.ar & 0x08) - i386_task_switch(call_gate.selector,0); - else - i286_task_switch(call_gate.selector,0); - return; - default: // invalid segment type - logerror("JMP: Invalid segment type (%i) to jump to.\n",desc.flags & 0x000f); - FAULT(FAULT_GP,segment & 0xfffc) - } - } - } - - if(SetRPL != 0) - segment = (segment & ~0x03) | cpustate->CPL; - if(operand32 == 0) - cpustate->eip = offset & 0x0000ffff; - else - cpustate->eip = offset; - cpustate->sreg[CS].selector = segment; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::i386_protected_mode_call( UINT16 seg, UINT32 off, int indirect, int operand32) -{ - I386_SREG desc; - I386_CALL_GATE gate; - UINT8 SetRPL = 0; - UINT8 CPL, DPL, RPL; - UINT16 selector = seg; - UINT32 offset = off; - int x; - - if((selector & ~0x03) == 0) - { - logerror("CALL (%08x): Selector is null.\n",cpustate->pc); - FAULT(FAULT_GP,0) // #GP(0) - } - if(selector & 0x04) - { - if((selector & ~0x07) > cpustate->ldtr.limit) - { - logerror("CALL: Selector is past LDT limit.\n"); - FAULT(FAULT_GP,selector & ~0x03) // #GP(selector) - } - } - else - { - if((selector & ~0x07) > cpustate->gdtr.limit) - { - logerror("CALL: Selector is past GDT limit.\n"); - FAULT(FAULT_GP,selector & ~0x03) // #GP(selector) - } - } - - /* Determine segment type */ - memset(&desc, 0, sizeof(desc)); - desc.selector = selector; - i386_load_protected_mode_segment(&desc,NULL); - CPL = cpustate->CPL; // current privilege level - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - RPL = selector & 0x03; // requested privilege level - if((desc.flags & 0x0018) == 0x18) // is a code segment - { - if(desc.flags & 0x0004) - { - /* conforming */ - if(DPL > CPL) - { - logerror("CALL: Code segment DPL %i is greater than CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,selector & ~0x03) // #GP(selector) - } - } - else - { - /* non-conforming */ - if(RPL > CPL) - { - logerror("CALL: RPL %i is greater than CPL %i\n",RPL,CPL); - FAULT(FAULT_GP,selector & ~0x03) // #GP(selector) - } - if(DPL != CPL) - { - logerror("CALL: Code segment DPL %i is not equal to CPL %i\n",DPL,CPL); - FAULT(FAULT_GP,selector & ~0x03) // #GP(selector) - } - } - SetRPL = 1; - if((desc.flags & 0x0080) == 0) - { - logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc); - FAULT(FAULT_NP,selector & ~0x03) // #NP(selector) - } - if (operand32 != 0) // if 32-bit - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) - 8 : (REG16(SP) - 8) & 0xffff); - if(i386_limit_check(SS, offset, 8)) - { - logerror("CALL (%08x): Stack has no room for return address.\n",cpustate->pc); - FAULT(FAULT_SS,0) // #SS(0) - } - } - else - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) - 4 : (REG16(SP) - 4) & 0xffff); - if(i386_limit_check(SS, offset, 4)) - { - logerror("CALL (%08x): Stack has no room for return address.\n",cpustate->pc); - FAULT(FAULT_SS,0) // #SS(0) - } - } - if(offset > desc.limit) - { - logerror("CALL: EIP is past segment limit.\n"); - FAULT(FAULT_GP,0) // #GP(0) - } - } - else - { - /* special segment type */ - if(desc.flags & 0x0010) - { - logerror("CALL: Segment is a data segment.\n"); - FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) - } - else - { - switch(desc.flags & 0x000f) - { - case 0x01: // Available 286 TSS - case 0x09: // Available 386 TSS - logerror("CALL: Available TSS at %08x\n",cpustate->pc); - if(DPL < CPL) - { - logerror("CALL: TSS: DPL is less than CPL.\n"); - FAULT(FAULT_TS,selector & ~0x03) // #TS(selector) - } - if(DPL < RPL) - { - logerror("CALL: TSS: DPL is less than RPL.\n"); - FAULT(FAULT_TS,selector & ~0x03) // #TS(selector) - } - if(desc.flags & 0x0002) - { - logerror("CALL: TSS: TSS is busy.\n"); - FAULT(FAULT_TS,selector & ~0x03) // #TS(selector) - } - if((desc.flags & 0x0080) == 0) - { - logerror("CALL: TSS: Segment %02x is not present.\n",selector); - FAULT(FAULT_NP,selector & ~0x03) // #NP(selector) - } - if(desc.flags & 0x08) - i386_task_switch(desc.selector,1); - else - i286_task_switch(desc.selector,1); - return; - case 0x04: // 286 call gate - case 0x0c: // 386 call gate - if((desc.flags & 0x000f) == 0x04) - operand32 = 0; - else - operand32 = 1; - memset(&gate, 0, sizeof(gate)); - gate.segment = selector; - i386_load_call_gate(&gate); - DPL = gate.dpl; - //logerror("CALL: Call gate at %08x (%i parameters)\n",cpustate->pc,gate.dword_count); - if(DPL < CPL) - { - logerror("CALL: Call gate DPL %i is less than CPL %i.\n",DPL,CPL); - FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) - } - if(DPL < RPL) - { - logerror("CALL: Call gate DPL %i is less than RPL %i.\n",DPL,RPL); - FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) - } - if(gate.present == 0) - { - logerror("CALL: Call gate is not present.\n"); - FAULT(FAULT_NP,desc.selector & ~0x03) // #GP(selector) - } - desc.selector = gate.selector; - if((gate.selector & ~0x03) == 0) - { - logerror("CALL: Call gate: Segment is null.\n"); - FAULT(FAULT_GP,0) // #GP(0) - } - if(desc.selector & 0x04) - { - if((desc.selector & ~0x07) > cpustate->ldtr.limit) - { - logerror("CALL: Call gate: Segment is past LDT limit\n"); - FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) - } - } - else - { - if((desc.selector & ~0x07) > cpustate->gdtr.limit) - { - logerror("CALL: Call gate: Segment is past GDT limit\n"); - FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) - } - } - i386_load_protected_mode_segment(&desc,NULL); - if((desc.flags & 0x0018) != 0x18) - { - logerror("CALL: Call gate: Segment is not a code segment.\n"); - FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) - } - DPL = ((desc.flags >> 5) & 0x03); - if(DPL > CPL) - { - logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL); - FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) - } - if((desc.flags & 0x0080) == 0) - { - logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc); - FAULT(FAULT_NP,desc.selector & ~0x03) // #NP(selector) - } - if(DPL < CPL && (desc.flags & 0x0004) == 0) - { - I386_SREG stack; - I386_SREG temp; - UINT32 oldSS,oldESP; - /* more privilege */ - /* Check new SS segment for privilege level from TSS */ - memset(&stack, 0, sizeof(stack)); - stack.selector = i386_get_stack_segment(DPL); - i386_load_protected_mode_segment(&stack,NULL); - if((stack.selector & ~0x03) == 0) - { - logerror("CALL: Call gate: TSS selector is null\n"); - FAULT(FAULT_TS,0) // #TS(0) - } - if(stack.selector & 0x04) - { - if((stack.selector & ~0x07) > cpustate->ldtr.limit) - { - logerror("CALL: Call gate: TSS selector is past LDT limit\n"); - FAULT(FAULT_TS,stack.selector) // #TS(SS selector) - } - } - else - { - if((stack.selector & ~0x07) > cpustate->gdtr.limit) - { - logerror("CALL: Call gate: TSS selector is past GDT limit\n"); - FAULT(FAULT_TS,stack.selector) // #TS(SS selector) - } - } - if((stack.selector & 0x03) != DPL) - { - logerror("CALL: Call gate: Stack selector RPL does not equal code segment DPL %i\n",DPL); - FAULT(FAULT_TS,stack.selector) // #TS(SS selector) - } - if(((stack.flags >> 5) & 0x03) != DPL) - { - logerror("CALL: Call gate: Stack DPL does not equal code segment DPL %i\n",DPL); - FAULT(FAULT_TS,stack.selector) // #TS(SS selector) - } - if((stack.flags & 0x0018) != 0x10 && (stack.flags & 0x0002)) - { - logerror("CALL: Call gate: Stack segment is not a writable data segment\n"); - FAULT(FAULT_TS,stack.selector) // #TS(SS selector) - } - if((stack.flags & 0x0080) == 0) - { - logerror("CALL: Call gate: Stack segment is not present\n"); - FAULT(FAULT_SS,stack.selector) // #SS(SS selector) - } - UINT32 newESP = i386_get_stack_ptr(DPL); - if(!stack.d) - { - newESP &= 0xffff; - } - if(operand32 != 0) - { - if(newESP < (UINT32)((gate.dword_count & 0x1f) + 16)) - { - logerror("CALL: Call gate: New stack has no room for 32-bit return address and parameters.\n"); - FAULT(FAULT_SS,0) // #SS(0) - } - if(gate.offset > desc.limit) - { - logerror("CALL: Call gate: EIP is past segment limit.\n"); - FAULT(FAULT_GP,0) // #GP(0) - } - } - else - { - if(newESP < (UINT32)((gate.dword_count & 0x1f) + 8)) - { - logerror("CALL: Call gate: New stack has no room for 16-bit return address and parameters.\n"); - FAULT(FAULT_SS,0) // #SS(0) - } - if((gate.offset & 0xffff) > desc.limit) - { - logerror("CALL: Call gate: IP is past segment limit.\n"); - FAULT(FAULT_GP,0) // #GP(0) - } - } - selector = gate.selector; - offset = gate.offset; - - cpustate->CPL = (stack.flags >> 5) & 0x03; - /* check for page fault at new stack */ - WRITE_TEST(stack.base+newESP-1); - /* switch to new stack */ - oldSS = cpustate->sreg[SS].selector; - cpustate->sreg[SS].selector = i386_get_stack_segment(cpustate->CPL); - if(operand32 != 0) - { - oldESP = REG32(ESP); - } - else - { - oldESP = REG16(SP); - } - i386_load_segment_descriptor(SS ); - REG32(ESP) = newESP; - - if(operand32 != 0) - { - PUSH32SEG(oldSS); - PUSH32(oldESP); - } - else - { - PUSH16(oldSS); - PUSH16(oldESP & 0xffff); - } - - memset(&temp, 0, sizeof(temp)); - temp.selector = oldSS; - i386_load_protected_mode_segment(&temp,NULL); - /* copy parameters from old stack to new stack */ - for(x=(gate.dword_count & 0x1f)-1;x>=0;x--) - { - UINT32 addr = oldESP + (operand32?(x*4):(x*2)); - addr = temp.base + (temp.d?addr:(addr&0xffff)); - if(operand32) - PUSH32(READ32(addr)); - else - PUSH16(READ16(addr)); - } - SetRPL = 1; - } - else - { - /* same privilege */ - if (operand32 != 0) // if 32-bit - { - UINT32 stkoff = (STACK_32BIT ? REG32(ESP) - 8 : (REG16(SP) - 8) & 0xffff); - if(i386_limit_check(SS, stkoff, 8)) - { - logerror("CALL: Stack has no room for return address.\n"); - FAULT(FAULT_SS,0) // #SS(0) - } - selector = gate.selector; - offset = gate.offset; - } - else - { - UINT32 stkoff = (STACK_32BIT ? REG32(ESP) - 4 : (REG16(SP) - 4) & 0xffff); - if(i386_limit_check(SS, stkoff, 4)) - { - logerror("CALL: Stack has no room for return address.\n"); - FAULT(FAULT_SS,0) // #SS(0) - } - selector = gate.selector; - offset = gate.offset & 0xffff; - } - if(offset > desc.limit) - { - logerror("CALL: EIP is past segment limit.\n"); - FAULT(FAULT_GP,0) // #GP(0) - } - SetRPL = 1; - } - break; - case 0x05: // task gate - logerror("CALL: Task gate at %08x\n",cpustate->pc); - memset(&gate, 0, sizeof(gate)); - gate.segment = selector; - i386_load_call_gate(&gate); - DPL = gate.dpl; - if(DPL < CPL) - { - logerror("CALL: Task Gate: Gate DPL is less than CPL.\n"); - FAULT(FAULT_TS,selector & ~0x03) // #TS(selector) - } - if(DPL < RPL) - { - logerror("CALL: Task Gate: Gate DPL is less than RPL.\n"); - FAULT(FAULT_TS,selector & ~0x03) // #TS(selector) - } - if((gate.ar & 0x0080) == 0) - { - logerror("CALL: Task Gate: Gate is not present.\n"); - FAULT(FAULT_NP,selector & ~0x03) // #NP(selector) - } - /* Check the TSS that the task gate points to */ - desc.selector = gate.selector; - i386_load_protected_mode_segment(&desc,NULL); - if(gate.selector & 0x04) - { - logerror("CALL: Task Gate: TSS is not global.\n"); - FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector) - } - else - { - if((gate.selector & ~0x07) > cpustate->gdtr.limit) - { - logerror("CALL: Task Gate: TSS is past GDT limit.\n"); - FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector) - } - } - if(desc.flags & 0x0002) - { - logerror("CALL: Task Gate: TSS is busy.\n"); - FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector) - } - if((desc.flags & 0x0080) == 0) - { - logerror("CALL: Task Gate: TSS is not present.\n"); - FAULT(FAULT_NP,gate.selector & ~0x03) // #TS(selector) - } - if(desc.flags & 0x08) - i386_task_switch(desc.selector,1); // with nesting - else - i286_task_switch(desc.selector,1); - return; - default: - logerror("CALL: Invalid special segment type (%i) to jump to.\n",desc.flags & 0x000f); - FAULT(FAULT_GP,selector & ~0x07) // #GP(selector) - } - } - } - - if(SetRPL != 0) - selector = (selector & ~0x03) | cpustate->CPL; - - UINT32 tempSP = REG32(ESP); - try - { - // this is ugly but the alternative is worse - if(operand32 == 0) - { - /* 16-bit operand size */ - PUSH16(cpustate->sreg[CS].selector ); - PUSH16(cpustate->eip & 0x0000ffff ); - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - cpustate->eip = offset; - i386_load_segment_descriptor(CS); - } - else - { - /* 32-bit operand size */ - PUSH32SEG(cpustate->sreg[CS].selector ); - PUSH32(cpustate->eip ); - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - cpustate->eip = offset; - i386_load_segment_descriptor(CS ); - } - } - catch(UINT64 e) - { - REG32(ESP) = tempSP; - throw e; - } - - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::i386_protected_mode_retf(UINT8 count, UINT8 operand32) -{ - UINT32 newCS, newEIP; - I386_SREG desc; - UINT8 CPL, RPL, DPL; - - UINT32 ea = i386_translate(SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32!=0) ? 8 : 4); - - if(operand32 == 0) - { - newEIP = READ16(ea) & 0xffff; - newCS = READ16(ea+2) & 0xffff; - } - else - { - newEIP = READ32(ea); - newCS = READ32(ea+4) & 0xffff; - } - - memset(&desc, 0, sizeof(desc)); - desc.selector = newCS; - i386_load_protected_mode_segment(&desc,NULL); - CPL = cpustate->CPL; // current privilege level - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - RPL = newCS & 0x03; - - if(RPL < CPL) - { - logerror("RETF (%08x): Return segment RPL is less than CPL.\n",cpustate->pc); - FAULT(FAULT_GP,newCS & ~0x03) - } - - if(RPL == CPL) - { - /* same privilege level */ - if((newCS & ~0x03) == 0) - { - logerror("RETF: Return segment is null.\n"); - FAULT(FAULT_GP,0) - } - if(newCS & 0x04) - { - if((newCS & ~0x07) >= cpustate->ldtr.limit) - { - logerror("RETF: Return segment is past LDT limit.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - else - { - if((newCS & ~0x07) >= cpustate->gdtr.limit) - { - logerror("RETF: Return segment is past GDT limit.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - if((desc.flags & 0x0018) != 0x0018) - { - logerror("RETF: Return segment is not a code segment.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - if(desc.flags & 0x0004) - { - if(DPL > RPL) - { - logerror("RETF: Conforming code segment DPL is greater than CS RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - else - { - if(DPL != RPL) - { - logerror("RETF: Non-conforming code segment DPL does not equal CS RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - if((desc.flags & 0x0080) == 0) - { - logerror("RETF (%08x): Code segment is not present.\n",cpustate->pc); - FAULT(FAULT_NP,newCS & ~0x03) - } - if(newEIP > desc.limit) - { - logerror("RETF: EIP is past code segment limit.\n"); - FAULT(FAULT_GP,0) - } - if(operand32 == 0) - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, count + 4) != 0) - { - logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc); - FAULT(FAULT_SS,0) - } - } - else - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, count + 8) != 0) - { - logerror("RETF: ESP is past stack segment limit.\n"); - FAULT(FAULT_SS,0) - } - } - if(STACK_32BIT) - REG16(SP) += (4+count); - else - REG32(ESP) += (8+count); - } - else if(RPL > CPL) - { - UINT32 newSS, newESP; // when changing privilege - /* outer privilege level */ - if(operand32 == 0) - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, count + 8) != 0) - { - logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc); - FAULT(FAULT_SS,0) - } - } - else - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, count + 16) != 0) - { - logerror("RETF: ESP is past stack segment limit.\n"); - FAULT(FAULT_SS,0) - } - } - /* Check CS selector and descriptor */ - if((newCS & ~0x03) == 0) - { - logerror("RETF: CS segment is null.\n"); - FAULT(FAULT_GP,0) - } - if(newCS & 0x04) - { - if((newCS & ~0x07) >= cpustate->ldtr.limit) - { - logerror("RETF: CS segment selector is past LDT limit.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - else - { - if((newCS & ~0x07) >= cpustate->gdtr.limit) - { - logerror("RETF: CS segment selector is past GDT limit.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - if((desc.flags & 0x0018) != 0x0018) - { - logerror("RETF: CS segment is not a code segment.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - if(desc.flags & 0x0004) - { - if(DPL > RPL) - { - logerror("RETF: Conforming CS segment DPL is greater than return selector RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - else - { - if(DPL != RPL) - { - logerror("RETF: Non-conforming CS segment DPL is not equal to return selector RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - if((desc.flags & 0x0080) == 0) - { - logerror("RETF: CS segment is not present.\n"); - FAULT(FAULT_NP,newCS & ~0x03) - } - if(newEIP > desc.limit) - { - logerror("RETF: EIP is past return CS segment limit.\n"); - FAULT(FAULT_GP,0) - } - - if(operand32 == 0) - { - ea += count+4; - newESP = READ16(ea) & 0xffff; - newSS = READ16(ea+2) & 0xffff; - } - else - { - ea += count+8; - newESP = READ32(ea); - newSS = READ32(ea+4) & 0xffff; - } - - /* Check SS selector and descriptor */ - desc.selector = newSS; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - if((newSS & ~0x07) == 0) - { - logerror("RETF: SS segment is null.\n"); - FAULT(FAULT_GP,0) - } - if(newSS & 0x04) - { - if((newSS & ~0x07) > cpustate->ldtr.limit) - { - logerror("RETF (%08x): SS segment selector is past LDT limit.\n",cpustate->pc); - FAULT(FAULT_GP,newSS & ~0x03) - } - } - else - { - if((newSS & ~0x07) > cpustate->gdtr.limit) - { - logerror("RETF (%08x): SS segment selector is past GDT limit.\n",cpustate->pc); - FAULT(FAULT_GP,newSS & ~0x03) - } - } - if((newSS & 0x03) != RPL) - { - logerror("RETF: SS segment RPL is not equal to CS segment RPL.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - if((desc.flags & 0x0018) != 0x0010 || (desc.flags & 0x0002) == 0) - { - logerror("RETF: SS segment is not a writable data segment.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - if(((desc.flags >> 5) & 0x03) != RPL) - { - logerror("RETF: SS DPL is not equal to CS segment RPL.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - if((desc.flags & 0x0080) == 0) - { - logerror("RETF: SS segment is not present.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - cpustate->CPL = newCS & 0x03; - - /* Load new SS:(E)SP */ - if(operand32 == 0) - REG16(SP) = (newESP+count) & 0xffff; - else - REG32(ESP) = newESP+count; - cpustate->sreg[SS].selector = newSS; - i386_load_segment_descriptor(SS ); - - /* Check that DS, ES, FS and GS are valid for the new privilege level */ - i386_check_sreg_validity(DS); - i386_check_sreg_validity(ES); - i386_check_sreg_validity(FS); - i386_check_sreg_validity(GS); - } - - /* Load new CS:(E)IP */ - if(operand32 == 0) - cpustate->eip = newEIP & 0xffff; - else - cpustate->eip = newEIP; - cpustate->sreg[CS].selector = newCS; - i386_load_segment_descriptor(CS ); - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::i386_protected_mode_iret(int operand32) -{ - UINT32 newCS, newEIP; - UINT32 newSS, newESP; // when changing privilege - I386_SREG desc,stack; - UINT8 CPL, RPL, DPL; - UINT32 newflags; - UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); - - CPL = cpustate->CPL; - UINT32 ea = i386_translate(SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32 != 0) ? 12 : 6); - if(operand32 == 0) - { - newEIP = READ16(ea) & 0xffff; - newCS = READ16(ea+2) & 0xffff; - newflags = READ16(ea+4) & 0xffff; - } - else - { - newEIP = READ32(ea); - newCS = READ32(ea+4) & 0xffff; - newflags = READ32(ea+8); - } - - if(V8086_MODE) - { - UINT32 oldflags = get_flags(); - if(IOPL != 3) - { - logerror("IRET (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc); - FAULT(FAULT_GP,0) - } - if(operand32 == 0) - { - cpustate->eip = newEIP & 0xffff; - cpustate->sreg[CS].selector = newCS & 0xffff; - newflags &= ~(3<<12); - newflags |= (((oldflags>>12)&3)<<12); // IOPL cannot be changed in V86 mode - set_flags((newflags & 0xffff) | (oldflags & ~0xffff)); - REG16(SP) += 6; - } - else - { - cpustate->eip = newEIP; - cpustate->sreg[CS].selector = newCS & 0xffff; - newflags &= ~(3<<12); - newflags |= 0x20000 | (((oldflags>>12)&3)<<12); // IOPL and VM cannot be changed in V86 mode - set_flags(newflags); - REG32(ESP) += 12; - } - } - else if(NESTED_TASK) - { - UINT32 task = READ32(cpustate->task.base); - /* Task Return */ - logerror("IRET (%08x): Nested task return.\n",cpustate->pc); - /* Check back-link selector in TSS */ - if(task & 0x04) - { - logerror("IRET: Task return: Back-linked TSS is not in GDT.\n"); - FAULT(FAULT_TS,task & ~0x03) - } - if((task & ~0x07) >= cpustate->gdtr.limit) - { - logerror("IRET: Task return: Back-linked TSS is not in GDT.\n"); - FAULT(FAULT_TS,task & ~0x03) - } - memset(&desc, 0, sizeof(desc)); - desc.selector = task; - i386_load_protected_mode_segment(&desc,NULL); - if((desc.flags & 0x001f) != 0x000b) - { - logerror("IRET (%08x): Task return: Back-linked TSS is not a busy TSS.\n",cpustate->pc); - FAULT(FAULT_TS,task & ~0x03) - } - if((desc.flags & 0x0080) == 0) - { - logerror("IRET: Task return: Back-linked TSS is not present.\n"); - FAULT(FAULT_NP,task & ~0x03) - } - if(desc.flags & 0x08) - i386_task_switch(desc.selector,0); - else - i286_task_switch(desc.selector,0); - return; - } - else - { - if(newflags & 0x00020000) // if returning to virtual 8086 mode - { - // 16-bit iret can't reach here - newESP = READ32(ea+12); - newSS = READ32(ea+16) & 0xffff; - /* Return to v86 mode */ - //logerror("IRET (%08x): Returning to Virtual 8086 mode.\n",cpustate->pc); - if(CPL != 0) - { - UINT32 oldflags = get_flags(); - newflags = (newflags & ~0x00003000) | (oldflags & 0x00003000); - if(CPL > IOPL) - newflags = (newflags & ~0x200 ) | (oldflags & 0x200); - } - set_flags(newflags); - cpustate->eip = POP32() & 0xffff; // high 16 bits are ignored - cpustate->sreg[CS].selector = POP32() & 0xffff; - POP32(); // already set flags - newESP = POP32(); - newSS = POP32() & 0xffff; - cpustate->sreg[ES].selector = POP32() & 0xffff; - cpustate->sreg[DS].selector = POP32() & 0xffff; - cpustate->sreg[FS].selector = POP32() & 0xffff; - cpustate->sreg[GS].selector = POP32() & 0xffff; - REG32(ESP) = newESP; // all 32 bits are loaded - cpustate->sreg[SS].selector = newSS; - i386_load_segment_descriptor(ES); - i386_load_segment_descriptor(DS); - i386_load_segment_descriptor(FS); - i386_load_segment_descriptor(GS); - i386_load_segment_descriptor(SS); - cpustate->CPL = 3; // Virtual 8086 tasks are always run at CPL 3 - } - else - { - if(operand32 == 0) - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, 4) != 0) - { - logerror("IRET: Data on stack is past SS limit.\n"); - FAULT(FAULT_SS,0) - } - } - else - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, 8) != 0) - { - logerror("IRET: Data on stack is past SS limit.\n"); - FAULT(FAULT_SS,0) - } - } - RPL = newCS & 0x03; - if(RPL < CPL) - { - logerror("IRET (%08x): Return CS RPL is less than CPL.\n",cpustate->pc); - FAULT(FAULT_GP,newCS & ~0x03) - } - if(RPL == CPL) - { - /* return to same privilege level */ - if(operand32 == 0) - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, 6) != 0) - { - logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc); - FAULT(FAULT_SS,0) - } - } - else - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, 12) != 0) - { - logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc); - FAULT(FAULT_SS,0) - } - } - if((newCS & ~0x03) == 0) - { - logerror("IRET: Return CS selector is null.\n"); - FAULT(FAULT_GP,0) - } - if(newCS & 0x04) - { - if((newCS & ~0x07) >= cpustate->ldtr.limit) - { - logerror("IRET: Return CS selector (%04x) is past LDT limit.\n",newCS); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - else - { - if((newCS & ~0x07) >= cpustate->gdtr.limit) - { - logerror("IRET: Return CS selector is past GDT limit.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - memset(&desc, 0, sizeof(desc)); - desc.selector = newCS; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - RPL = newCS & 0x03; - if((desc.flags & 0x0018) != 0x0018) - { - logerror("IRET (%08x): Return CS segment is not a code segment.\n",cpustate->pc); - FAULT(FAULT_GP,newCS & ~0x07) - } - if(desc.flags & 0x0004) - { - if(DPL > RPL) - { - logerror("IRET: Conforming return CS DPL is greater than CS RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - else - { - if(DPL != RPL) - { - logerror("IRET: Non-conforming return CS DPL is not equal to CS RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - if((desc.flags & 0x0080) == 0) - { - logerror("IRET: (%08x) Return CS segment is not present.\n", cpustate->pc); - FAULT(FAULT_NP,newCS & ~0x03) - } - if(newEIP > desc.limit) - { - logerror("IRET: Return EIP is past return CS limit.\n"); - FAULT(FAULT_GP,0) - } - - if(CPL != 0) - { - UINT32 oldflags = get_flags(); - newflags = (newflags & ~0x00003000) | (oldflags & 0x00003000); - } - - if(operand32 == 0) - { - cpustate->eip = newEIP; - cpustate->sreg[CS].selector = newCS; - set_flags(newflags); - REG16(SP) += 6; - } - else - { - cpustate->eip = newEIP; - cpustate->sreg[CS].selector = newCS & 0xffff; - set_flags(newflags); - REG32(ESP) += 12; - } - } - else if(RPL > CPL) - { - /* return to outer privilege level */ - memset(&desc, 0, sizeof(desc)); - desc.selector = newCS; - i386_load_protected_mode_segment(&desc,NULL); - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level - RPL = newCS & 0x03; - if(operand32 == 0) - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, 10) != 0) - { - logerror("IRET: SP is past SS limit.\n"); - FAULT(FAULT_SS,0) - } - } - else - { - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS, offset, 20) != 0) - { - logerror("IRET: ESP is past SS limit.\n"); - FAULT(FAULT_SS,0) - } - } - /* Check CS selector and descriptor */ - if((newCS & ~0x03) == 0) - { - logerror("IRET: Return CS selector is null.\n"); - FAULT(FAULT_GP,0) - } - if(newCS & 0x04) - { - if((newCS & ~0x07) >= cpustate->ldtr.limit) - { - logerror("IRET: Return CS selector is past LDT limit.\n"); - FAULT(FAULT_GP,newCS & ~0x03); - } - } - else - { - if((newCS & ~0x07) >= cpustate->gdtr.limit) - { - logerror("IRET: Return CS selector is past GDT limit.\n"); - FAULT(FAULT_GP,newCS & ~0x03); - } - } - if((desc.flags & 0x0018) != 0x0018) - { - logerror("IRET: Return CS segment is not a code segment.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - if(desc.flags & 0x0004) - { - if(DPL > RPL) - { - logerror("IRET: Conforming return CS DPL is greater than CS RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - else - { - if(DPL != RPL) - { - logerror("IRET: Non-conforming return CS DPL does not equal CS RPL.\n"); - FAULT(FAULT_GP,newCS & ~0x03) - } - } - if((desc.flags & 0x0080) == 0) - { - logerror("IRET: Return CS segment is not present.\n"); - FAULT(FAULT_NP,newCS & ~0x03) - } - - /* Check SS selector and descriptor */ - if(operand32 == 0) - { - newESP = READ16(ea+6) & 0xffff; - newSS = READ16(ea+8) & 0xffff; - } - else - { - newESP = READ32(ea+12); - newSS = READ32(ea+16) & 0xffff; - } - memset(&stack, 0, sizeof(stack)); - stack.selector = newSS; - i386_load_protected_mode_segment(&stack,NULL); - DPL = (stack.flags >> 5) & 0x03; - if((newSS & ~0x03) == 0) - { - logerror("IRET: Return SS selector is null.\n"); - FAULT(FAULT_GP,0) - } - if(newSS & 0x04) - { - if((newSS & ~0x07) >= cpustate->ldtr.limit) - { - logerror("IRET: Return SS selector is past LDT limit.\n"); - FAULT(FAULT_GP,newSS & ~0x03); - } - } - else - { - if((newSS & ~0x07) >= cpustate->gdtr.limit) - { - logerror("IRET: Return SS selector is past GDT limit.\n"); - FAULT(FAULT_GP,newSS & ~0x03); - } - } - if((newSS & 0x03) != RPL) - { - logerror("IRET: Return SS RPL is not equal to return CS RPL.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - if((stack.flags & 0x0018) != 0x0010) - { - logerror("IRET: Return SS segment is not a data segment.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - if((stack.flags & 0x0002) == 0) - { - logerror("IRET: Return SS segment is not writable.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - if(DPL != RPL) - { - logerror("IRET: Return SS DPL does not equal SS RPL.\n"); - FAULT(FAULT_GP,newSS & ~0x03) - } - if((stack.flags & 0x0080) == 0) - { - logerror("IRET: Return SS segment is not present.\n"); - FAULT(FAULT_NP,newSS & ~0x03) - } - if(newEIP > desc.limit) - { - logerror("IRET: EIP is past return CS limit.\n"); - FAULT(FAULT_GP,0) - } - -// if(operand32 == 0) -// REG16(SP) += 10; -// else -// REG32(ESP) += 20; - - // IOPL can only change if CPL is zero - if(CPL != 0) - { - UINT32 oldflags = get_flags(); - newflags = (newflags & ~0x00003000) | (oldflags & 0x00003000); - if(CPL > IOPL) - newflags = (newflags & ~0x200 ) | (oldflags & 0x200); - } - - if(operand32 == 0) - { - cpustate->eip = newEIP & 0xffff; - cpustate->sreg[CS].selector = newCS; - set_flags(newflags); - REG16(SP) = newESP & 0xffff; - cpustate->sreg[SS].selector = newSS; - } - else - { - cpustate->eip = newEIP; - cpustate->sreg[CS].selector = newCS & 0xffff; - set_flags(newflags); - REG32(ESP) = newESP; - cpustate->sreg[SS].selector = newSS & 0xffff; - } - cpustate->CPL = newCS & 0x03; - i386_load_segment_descriptor(SS); - - /* Check that DS, ES, FS and GS are valid for the new privilege level */ - i386_check_sreg_validity(DS); - i386_check_sreg_validity(ES); - i386_check_sreg_validity(FS); - i386_check_sreg_validity(GS); - } - } - } - - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); -} - -#include "cycles.h" - -void I386_OPS_BASE::build_cycle_table() -{ - uint32_t i, j; - for (j=0; j < X86_NUM_CPUS; j++) - { -// cycle_table_rm[j] = (UINT8 *)malloc(CYCLES_NUM_OPCODES); -// cycle_table_pm[j] = (UINT8 *)malloc(CYCLES_NUM_OPCODES); - - for (i=0; i < sizeof(x86_cycle_table)/sizeof(X86_CYCLE_TABLE); i++) - { - int opcode = x86_cycle_table[i].op; - cycle_table_rm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][0]; - cycle_table_pm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][1]; - } - } -} - -void I386_OPS_BASE::report_invalid_opcode() -{ -#ifndef DEBUG_MISSING_OPCODE - logerror("i386: Invalid opcode %02X at %08X %s\n", cpustate->opcode, cpustate->pc - 1, cpustate->lock ? "with lock" : ""); -#else - logerror("i386: Invalid opcode"); - for (int a = 0; a < cpustate->opcode_bytes_length; a++) - logerror(" %02X", cpustate->opcode_bytes[a]); - logerror(" at %08X\n", cpustate->opcode_pc); -#endif -} - -void I386_OPS_BASE::report_invalid_modrm( const char* opcode, UINT8 modrm) -{ -#ifndef DEBUG_MISSING_OPCODE - logerror("i386: Invalid %s modrm %01X at %08X\n", opcode, modrm, cpustate->pc - 2); -#else - logerror("i386: Invalid %s modrm %01X", opcode, modrm); - for (int a = 0; a < cpustate->opcode_bytes_length; a++) - logerror(" %02X", cpustate->opcode_bytes[a]); - logerror(" at %08X\n", cpustate->opcode_pc); -#endif - i386_trap(6, 0, 0); -} - -/* Forward declarations */ - - -void I386_OPS_BASE::I386OP(decode_opcode)() -{ - cpustate->opcode = FETCH(); - - if(cpustate->lock && !cpustate->lock_table[0][cpustate->opcode]) - return I386OP(invalid)(); - - if( cpustate->operand_size ) - (this->*cpustate->opcode_table1_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table1_16[cpustate->opcode])(); -} - -/* Two-byte opcode 0f xx */ -void I386_OPS_BASE::I386OP(decode_two_byte)() -{ - cpustate->opcode = FETCH(); - - if(cpustate->lock && !cpustate->lock_table[1][cpustate->opcode]) - return I386OP(invalid)(); - - if( cpustate->operand_size ) - (this->*cpustate->opcode_table2_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table2_16[cpustate->opcode])(); -} - -/* Three-byte opcode 0f 38 xx */ -void I386_OPS_BASE::I386OP(decode_three_byte38)() -{ - cpustate->opcode = FETCH(); - - if (cpustate->operand_size) - (this->*cpustate->opcode_table338_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table338_16[cpustate->opcode])(); -} - -/* Three-byte opcode 0f 3a xx */ -void I386_OPS_BASE::I386OP(decode_three_byte3a)() -{ - cpustate->opcode = FETCH(); - - if (cpustate->operand_size) - (this->*cpustate->opcode_table33a_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table33a_16[cpustate->opcode])(); -} - -/* Three-byte opcode prefix 66 0f xx */ -void I386_OPS_BASE::I386OP(decode_three_byte66)() -{ - cpustate->opcode = FETCH(); - if( cpustate->operand_size ) - (this->*cpustate->opcode_table366_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table366_16[cpustate->opcode])(); -} - -/* Three-byte opcode prefix f2 0f xx */ -void I386_OPS_BASE::I386OP(decode_three_bytef2)() -{ - cpustate->opcode = FETCH(); - if( cpustate->operand_size ) - (this->*cpustate->opcode_table3f2_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table3f2_16[cpustate->opcode])(); -} - -/* Three-byte opcode prefix f3 0f */ -void I386_OPS_BASE::I386OP(decode_three_bytef3)() -{ - cpustate->opcode = FETCH(); - if( cpustate->operand_size ) - (this->*cpustate->opcode_table3f3_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table3f3_16[cpustate->opcode])(); -} - -/* Four-byte opcode prefix 66 0f 38 xx */ -void I386_OPS_BASE::I386OP(decode_four_byte3866)() -{ - cpustate->opcode = FETCH(); - if (cpustate->operand_size) - (this->*cpustate->opcode_table46638_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table46638_16[cpustate->opcode])(); -} - -/* Four-byte opcode prefix 66 0f 3a xx */ -void I386_OPS_BASE::I386OP(decode_four_byte3a66)() -{ - cpustate->opcode = FETCH(); - if (cpustate->operand_size) - (this->*cpustate->opcode_table4663a_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table4663a_16[cpustate->opcode])(); -} - -/* Four-byte opcode prefix f2 0f 38 xx */ -void I386_OPS_BASE::I386OP(decode_four_byte38f2)() -{ - cpustate->opcode = FETCH(); - if (cpustate->operand_size) - (this->*cpustate->opcode_table4f238_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table4f238_16[cpustate->opcode])(); -} - -/* Four-byte opcode prefix f2 0f 3a xx */ -void I386_OPS_BASE::I386OP(decode_four_byte3af2)() -{ - cpustate->opcode = FETCH(); - if (cpustate->operand_size) - (this->*cpustate->opcode_table4f23a_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table4f23a_16[cpustate->opcode])(); -} - -/* Four-byte opcode prefix f3 0f 38 xx */ -void I386_OPS_BASE::I386OP(decode_four_byte38f3)() -{ - cpustate->opcode = FETCH(); - if (cpustate->operand_size) - (this->*cpustate->opcode_table4f338_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table4f338_16[cpustate->opcode])(); -} - - -/*************************************************************************/ - -void I386_OPS_BASE::i386_postload() -{ - int i; - for (i = 0; i < 6; i++) - i386_load_segment_descriptor(i); - CHANGE_PC(cpustate->eip); -} - -#include "./i386_ops_table.h" - -i386_state *I386_OPS_BASE::i386_common_init(int tlbsize) -{ - int i, j; - static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH}; - static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI}; - static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI}; - cpustate = &__cpustate; - //cpustate = (i386_state *)malloc(sizeof(i386_state)); - //x86_cycle_table = _x86_cycle_table_real; - //x86_opcode_table = _x86_opcode_table_fake; - - assert((sizeof(XMM_REG)/sizeof(double)) == 2); - - build_cycle_table(); - - for( i=0; i < 256; i++ ) { - int c=0; - for( j=0; j < 8; j++ ) { - if( i & (1 << j) ) - c++; - } - i386_parity_table[i] = ~(c & 0x1) & 0x1; - } - - for( i=0; i < 256; i++ ) { - i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7]; - i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7]; - i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7]; - - i386_MODRM_table[i].rm.b = regs8[i & 0x7]; - i386_MODRM_table[i].rm.w = regs16[i & 0x7]; - i386_MODRM_table[i].rm.d = regs32[i & 0x7]; - } - - cpustate->vtlb = vtlb_alloc((void *)cpustate, AS_PROGRAM, 0, tlbsize); - cpustate->smi = false; - cpustate->lock = false; - -// i386_interface *intf = (i386_interface *) device->static_config(); -// -// if (intf != NULL) -// cpustate->smiact.resolve(intf->smiact, *device); -// else -// memset(&cpustate->smiact, 0, sizeof(cpustate->smiact)); - - zero_state(); - cpustate->program = d_mem; - cpustate->io = d_io; - cpustate->pic = d_pic; - - return cpustate; -} -void I386_OPS_BASE::i386_vtlb_free(void) -{ - vtlb_free(cpustate->vtlb); - cpustate->vtlb = NULL; -} - -void I386_OPS_BASE::i386_free_state(void) -{ - //if(cpustate != NULL) free(cpustate); -} - -void *I386_OPS_BASE::cpu_init_i386(void) -{ - i386_common_init(32); - build_opcode_table(OP_I386); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386]; - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I386]; - return cpustate; -} - - -void I386_OPS_BASE::process_state_SREG(I386_SREG* val, FILEIO* state_fio) -{ - state_fio->StateValue(val->selector); - state_fio->StateValue(val->flags); - state_fio->StateValue(val->base); - state_fio->StateValue(val->limit); - state_fio->StateValue(val->d); - state_fio->StateValue(val->valid); -} - -void I386_OPS_BASE::process_state_SYS_TABLE(I386_SYS_TABLE* val, FILEIO* state_fio) -{ - state_fio->StateValue(val->base); - state_fio->StateValue(val->limit); -} - -void I386_OPS_BASE::process_state_SEG_DESC(I386_SEG_DESC* val, FILEIO* state_fio) -{ - state_fio->StateValue(val->segment); - state_fio->StateValue(val->flags); - state_fio->StateValue(val->base); - state_fio->StateValue(val->limit); -} - -void I386_OPS_BASE::process_state_GPR(I386_GPR* val, FILEIO* state_fio) -{ - state_fio->StateArray(val->d, sizeof(val->d), 1); - state_fio->StateArray(val->w, sizeof(val->w), 1); - state_fio->StateArray(val->b, sizeof(val->b), 1); -} - -void I386_OPS_BASE::process_state_floatx80(floatx80* val, FILEIO* state_fio) -{ - state_fio->StateValue(val->high); - state_fio->StateValue(val->low); -} - -void I386_OPS_BASE::process_state_XMM_REG(XMM_REG* val, FILEIO* state_fio) -{ - state_fio->StateArray(val->b, sizeof(val->b), 1); - state_fio->StateArray(val->w, sizeof(val->w), 1); - state_fio->StateArray(val->d, sizeof(val->d), 1); - state_fio->StateArray(val->q, sizeof(val->q), 1); - state_fio->StateArray(val->c, sizeof(val->c), 1); - state_fio->StateArray(val->s, sizeof(val->s), 1); - state_fio->StateArray(val->i, sizeof(val->i), 1); - state_fio->StateArray(val->l, sizeof(val->l), 1); - state_fio->StateArray(val->f, sizeof(val->f), 1); - state_fio->StateArray(val->f64, sizeof(val->f64), 1); -} - -void I386_OPS_BASE::process_state_vtlb(vtlb_state* val, FILEIO* state_fio) -{ -// state_fio->StateValue(val->space); -// state_fio->StateValue(val->dynamic); -// state_fio->StateValue(val->fixed); - state_fio->StateValue(val->dynindex); -// state_fio->StateValue(val->pageshift); -// state_fio->StateValue(val->addrwidth); - if(val->live != NULL) { - state_fio->StateArray(val->live, val->fixed + val->dynamic, 1); - } - if(val->fixedpages != NULL) { - state_fio->StateArray(val->fixedpages, val->fixed, 1); - } - if(val->table != NULL) { - state_fio->StateArray(val->table, (size_t) 1 << (val->addrwidth - val->pageshift), 1); - } -} - - -bool I386_OPS_BASE::process_state(FILEIO *state_fio, bool loading) -{ - // ToDo: Write endian - vtlb_state *vtlb = cpustate->vtlb; - void *cpudevice = NULL; - offs_t *live = NULL; - int live_size = 0; - int *fixedpages = NULL; - int fixedpages_size = 0; - vtlb_entry *table = NULL; - int table_size = 0; -// vtlb_entry *save = NULL; -// int save_size = 0; - - - process_state_GPR(&cpustate->reg, state_fio); - for(int i = 0; i < (int)array_length(cpustate->sreg); i++) { - process_state_SREG(&cpustate->sreg[i], state_fio); - } - state_fio->StateValue(cpustate->eip); - state_fio->StateValue(cpustate->pc); - state_fio->StateValue(cpustate->prev_eip); - state_fio->StateValue(cpustate->prev_pc); - state_fio->StateValue(cpustate->eflags); - state_fio->StateValue(cpustate->eflags_mask); - state_fio->StateValue(cpustate->CF); - state_fio->StateValue(cpustate->DF); - state_fio->StateValue(cpustate->SF); - state_fio->StateValue(cpustate->OF); - state_fio->StateValue(cpustate->ZF); - state_fio->StateValue(cpustate->PF); - state_fio->StateValue(cpustate->AF); - state_fio->StateValue(cpustate->IF); - state_fio->StateValue(cpustate->TF); - state_fio->StateValue(cpustate->IOP1); - state_fio->StateValue(cpustate->IOP2); - state_fio->StateValue(cpustate->NT); - state_fio->StateValue(cpustate->RF); - state_fio->StateValue(cpustate->VM); - state_fio->StateValue(cpustate->AC); - state_fio->StateValue(cpustate->VIF); - state_fio->StateValue(cpustate->VIP); - state_fio->StateValue(cpustate->ID); - state_fio->StateValue(cpustate->CPL); - state_fio->StateValue(cpustate->performed_intersegment_jump); - state_fio->StateValue(cpustate->delayed_interrupt_enable); - state_fio->StateArray(cpustate->cr, sizeof(cpustate->cr), 1); - state_fio->StateArray(cpustate->dr, sizeof(cpustate->dr), 1); - state_fio->StateArray(cpustate->tr, sizeof(cpustate->tr), 1); - process_state_SYS_TABLE(&cpustate->gdtr, state_fio); - process_state_SYS_TABLE(&cpustate->idtr, state_fio); - process_state_SEG_DESC(&cpustate->task, state_fio); - process_state_SEG_DESC(&cpustate->ldtr, state_fio); - state_fio->StateValue(cpustate->ext); - state_fio->StateValue(cpustate->halted); - state_fio->StateValue(cpustate->busreq); - state_fio->StateValue(cpustate->shutdown); - state_fio->StateValue(cpustate->operand_size); - state_fio->StateValue(cpustate->xmm_operand_size); - state_fio->StateValue(cpustate->address_size); - state_fio->StateValue(cpustate->operand_prefix); - state_fio->StateValue(cpustate->address_prefix); - state_fio->StateValue(cpustate->segment_prefix); - state_fio->StateValue(cpustate->segment_override); - - state_fio->StateValue(cpustate->total_cycles); - - state_fio->StateValue(cpustate->cycles); - state_fio->StateValue(cpustate->extra_cycles); - state_fio->StateValue(cpustate->base_cycles); - state_fio->StateValue(cpustate->opcode); - state_fio->StateValue(cpustate->irq_state); - state_fio->StateValue(cpustate->a20_mask); - state_fio->StateValue(cpustate->cpuid_max_input_value_eax); - state_fio->StateValue(cpustate->cpuid_id0); - state_fio->StateValue(cpustate->cpuid_id1); - state_fio->StateValue(cpustate->cpuid_id2); - state_fio->StateValue(cpustate->cpu_version); - state_fio->StateValue(cpustate->feature_flags); - state_fio->StateValue(cpustate->tsc); - state_fio->StateArray(cpustate->perfctr, sizeof(cpustate->perfctr), 1); - for(int i = 0; i < array_length(cpustate->x87_reg); i++) { - process_state_floatx80(&cpustate->x87_reg[i], state_fio); - } - state_fio->StateValue(cpustate->x87_cw); - state_fio->StateValue(cpustate->x87_sw); - state_fio->StateValue(cpustate->x87_tw); - state_fio->StateValue(cpustate->x87_data_ptr); - state_fio->StateValue(cpustate->x87_inst_ptr); - state_fio->StateValue(cpustate->x87_opcode); - for(int i = 0; i < array_length(cpustate->sse_reg); i++) { - process_state_XMM_REG(&cpustate->sse_reg[i], state_fio); - } - state_fio->StateValue(cpustate->mxcsr); - state_fio->StateArray(&cpustate->lock_table[0][0], sizeof(cpustate->lock_table), 1); - - if(cpustate->vtlb != NULL) { - process_state_vtlb(cpustate->vtlb, state_fio); - } - state_fio->StateValue(cpustate->smm); - state_fio->StateValue(cpustate->smi); - state_fio->StateValue(cpustate->smi_latched); - state_fio->StateValue(cpustate->nmi_masked); - state_fio->StateValue(cpustate->nmi_latched); - state_fio->StateValue(cpustate->smbase); -// state_fio->StateValue(cpustate->smiact); - state_fio->StateValue(cpustate->lock); -#ifdef DEBUG_MISSING_OPCODE - state_fio->StateArray(cpustate->opcode_bytes, sizeof(cpustate->opcode_bytes), 1); - state_fio->StateValue(cpustate->opcode_pc); - state_fio->StateValue(cpustate->opcode_bytes_length); -#endif - - return true; -} - -void I386_OPS_BASE::build_opcode_table(UINT32 features) -{ - int i; - i386_state *_cpustate = cpustate; - for (i=0; i < 256; i++) - { - _cpustate->opcode_table1_16[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table1_32[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table2_16[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table2_32[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table366_16[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table366_32[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table3f2_16[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table3f2_32[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table3f3_16[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->opcode_table3f3_32[i] = &I386_OPS_BASE::I386OP(invalid); - _cpustate->lock_table[0][i] = false; - _cpustate->lock_table[1][i] = false; - } - - for (i=0; i < (int)(sizeof(x86_opcode_table) / sizeof(X86_OPCODE)); i++) - { - const X86_OPCODE *op = &x86_opcode_table[i]; - - if ((op->flags & features)) - { - if (op->flags & OP_2BYTE) - { - _cpustate->opcode_table2_32[op->opcode] = op->handler32; - _cpustate->opcode_table2_16[op->opcode] = op->handler16; - _cpustate->opcode_table366_32[op->opcode] = op->handler32; - _cpustate->opcode_table366_16[op->opcode] = op->handler16; - _cpustate->lock_table[1][op->opcode] = op->lockable; - } - else if (op->flags & OP_3BYTE66) - { - _cpustate->opcode_table366_32[op->opcode] = op->handler32; - _cpustate->opcode_table366_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_3BYTEF2) - { - _cpustate->opcode_table3f2_32[op->opcode] = op->handler32; - _cpustate->opcode_table3f2_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_3BYTEF3) - { - _cpustate->opcode_table3f3_32[op->opcode] = op->handler32; - _cpustate->opcode_table3f3_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_3BYTE38) - { - _cpustate->opcode_table338_32[op->opcode] = op->handler32; - _cpustate->opcode_table338_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_3BYTE3A) - { - _cpustate->opcode_table33a_32[op->opcode] = op->handler32; - _cpustate->opcode_table33a_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_4BYTE3866) - { - _cpustate->opcode_table46638_32[op->opcode] = op->handler32; - _cpustate->opcode_table46638_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_4BYTE3A66) - { - _cpustate->opcode_table4663a_32[op->opcode] = op->handler32; - _cpustate->opcode_table4663a_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_4BYTE38F2) - { - _cpustate->opcode_table4f238_32[op->opcode] = op->handler32; - _cpustate->opcode_table4f238_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_4BYTE3AF2) - { - _cpustate->opcode_table4f23a_32[op->opcode] = op->handler32; - _cpustate->opcode_table4f23a_16[op->opcode] = op->handler16; - } - else if (op->flags & OP_4BYTE38F3) - { - _cpustate->opcode_table4f338_32[op->opcode] = op->handler32; - _cpustate->opcode_table4f338_16[op->opcode] = op->handler16; - } - else - { - _cpustate->opcode_table1_32[op->opcode] = op->handler32; - _cpustate->opcode_table1_16[op->opcode] = op->handler16; - _cpustate->lock_table[0][op->opcode] = op->lockable; - } - } - } - -} - -void I386_OPS_BASE::zero_state() -{ - memset( &cpustate->reg, 0, sizeof(cpustate->reg) ); - memset( cpustate->sreg, 0, sizeof(cpustate->sreg) ); - - cpustate->total_cycles = 0; - cpustate->prev_total_cycles = 0; - - cpustate->eip = 0; - cpustate->pc = 0; - cpustate->prev_eip = 0; - cpustate->eflags = 0; - cpustate->eflags_mask = 0; - cpustate->CF = 0; - cpustate->DF = 0; - cpustate->SF = 0; - cpustate->OF = 0; - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->AF = 0; - cpustate->IF = 0; - cpustate->TF = 0; - cpustate->IOP1 = 0; - cpustate->IOP2 = 0; - cpustate->NT = 0; - cpustate->RF = 0; - cpustate->VM = 0; - cpustate->AC = 0; - cpustate->VIF = 0; - cpustate->VIP = 0; - cpustate->ID = 0; - cpustate->CPL = 0; - cpustate->performed_intersegment_jump = 0; - cpustate->delayed_interrupt_enable = 0; - memset( cpustate->cr, 0, sizeof(cpustate->cr) ); - memset( cpustate->dr, 0, sizeof(cpustate->dr) ); - memset( cpustate->tr, 0, sizeof(cpustate->tr) ); - memset( &cpustate->gdtr, 0, sizeof(cpustate->gdtr) ); - memset( &cpustate->idtr, 0, sizeof(cpustate->idtr) ); - memset( &cpustate->task, 0, sizeof(cpustate->task) ); - memset( &cpustate->ldtr, 0, sizeof(cpustate->ldtr) ); - cpustate->ext = 0; - cpustate->halted = 0; - cpustate->busreq = 0; - cpustate->shutdown = 0; - cpustate->operand_size = 0; - cpustate->xmm_operand_size = 0; - cpustate->address_size = 0; - cpustate->operand_prefix = 0; - cpustate->address_prefix = 0; - cpustate->segment_prefix = 0; - cpustate->segment_override = 0; -// cpustate->cycles = 0; -// cpustate->base_cycles = 0; - cpustate->opcode = 0; - cpustate->irq_state = 0; - cpustate->a20_mask = 0; - cpustate->cpuid_max_input_value_eax = 0; - cpustate->cpuid_id0 = 0; - cpustate->cpuid_id1 = 0; - cpustate->cpuid_id2 = 0; - cpustate->cpu_version = 0; - cpustate->feature_flags = 0; - cpustate->tsc = 0; - cpustate->perfctr[0] = cpustate->perfctr[1] = 0; - memset( cpustate->x87_reg, 0, sizeof(cpustate->x87_reg) ); - cpustate->x87_cw = 0; - cpustate->x87_sw = 0; - cpustate->x87_tw = 0; - cpustate->x87_data_ptr = 0; - cpustate->x87_inst_ptr = 0; - cpustate->x87_opcode = 0; - memset( cpustate->sse_reg, 0, sizeof(cpustate->sse_reg) ); - cpustate->mxcsr = 0; - cpustate->smm = false; - cpustate->smi = false; - cpustate->smi_latched = false; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - cpustate->smbase = 0; -#ifdef DEBUG_MISSING_OPCODE - memset( cpustate->opcode_bytes, 0, sizeof(cpustate->opcode_bytes) ); - cpustate->opcode_pc = 0; - cpustate->opcode_bytes_length = 0; -#endif -} - -void I386_OPS_BASE::cpu_reset_i386(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x93; - cpustate->sreg[CS].valid = true; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - cpustate->sreg[DS].valid = cpustate->sreg[ES].valid = cpustate->sreg[FS].valid = cpustate->sreg[GS].valid = cpustate->sreg[SS].valid =true; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x7fffffe0; // reserved bits set to 1 - cpustate->eflags = 0; - cpustate->eflags_mask = 0x00037fd7; - cpustate->eip = 0xfff0; - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 3 (386), Model 0 (DX), Stepping 8 (D1) - REG32(EAX) = 0; - REG32(EDX) = (3 << 8) | (0 << 4) | (8); - - cpustate->CPL = 0; - - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::pentium_smi() -{ - UINT32 smram_state = cpustate->smbase + 0xfe00; - UINT32 old_cr0 = cpustate->cr[0]; - UINT32 old_flags = get_flags(); - - if(cpustate->smm) - return; - - cpustate->cr[0] &= ~(0x8000000d); - set_flags(2); -// if(!cpustate->smiact.isnull()) -// cpustate->smiact(true); - cpustate->smm = true; - cpustate->smi_latched = false; - - // save state - WRITE32(cpustate->cr[4], smram_state+SMRAM_IP5_CR4); - WRITE32(cpustate->sreg[ES].limit, smram_state+SMRAM_IP5_ESLIM); - WRITE32(cpustate->sreg[ES].base, smram_state+SMRAM_IP5_ESBASE); - WRITE32(cpustate->sreg[ES].flags, smram_state+SMRAM_IP5_ESACC); - WRITE32(cpustate->sreg[CS].limit, smram_state+SMRAM_IP5_CSLIM); - WRITE32(cpustate->sreg[CS].base, smram_state+SMRAM_IP5_CSBASE); - WRITE32(cpustate->sreg[CS].flags, smram_state+SMRAM_IP5_CSACC); - WRITE32(cpustate->sreg[SS].limit, smram_state+SMRAM_IP5_SSLIM); - WRITE32(cpustate->sreg[SS].base, smram_state+SMRAM_IP5_SSBASE); - WRITE32(cpustate->sreg[SS].flags, smram_state+SMRAM_IP5_SSACC); - WRITE32(cpustate->sreg[DS].limit, smram_state+SMRAM_IP5_DSLIM); - WRITE32(cpustate->sreg[DS].base, smram_state+SMRAM_IP5_DSBASE); - WRITE32(cpustate->sreg[DS].flags, smram_state+SMRAM_IP5_DSACC); - WRITE32(cpustate->sreg[FS].limit, smram_state+SMRAM_IP5_FSLIM); - WRITE32(cpustate->sreg[FS].base, smram_state+SMRAM_IP5_FSBASE); - WRITE32(cpustate->sreg[FS].flags, smram_state+SMRAM_IP5_FSACC); - WRITE32(cpustate->sreg[GS].limit, smram_state+SMRAM_IP5_GSLIM); - WRITE32(cpustate->sreg[GS].base, smram_state+SMRAM_IP5_GSBASE); - WRITE32(cpustate->sreg[GS].flags, smram_state+SMRAM_IP5_GSACC); - WRITE32(cpustate->ldtr.flags, smram_state+SMRAM_IP5_LDTACC); - WRITE32(cpustate->ldtr.limit, smram_state+SMRAM_IP5_LDTLIM); - WRITE32(cpustate->ldtr.base, smram_state+SMRAM_IP5_LDTBASE); - WRITE32(cpustate->gdtr.limit, smram_state+SMRAM_IP5_GDTLIM); - WRITE32(cpustate->gdtr.base, smram_state+SMRAM_IP5_GDTBASE); - WRITE32(cpustate->idtr.limit, smram_state+SMRAM_IP5_IDTLIM); - WRITE32(cpustate->idtr.base, smram_state+SMRAM_IP5_IDTBASE); - WRITE32(cpustate->task.limit, smram_state+SMRAM_IP5_TRLIM); - WRITE32(cpustate->task.base, smram_state+SMRAM_IP5_TRBASE); - WRITE32(cpustate->task.flags, smram_state+SMRAM_IP5_TRACC); - - WRITE32(cpustate->sreg[ES].selector, smram_state+SMRAM_ES); - WRITE32(cpustate->sreg[CS].selector, smram_state+SMRAM_CS); - WRITE32(cpustate->sreg[SS].selector, smram_state+SMRAM_SS); - WRITE32(cpustate->sreg[DS].selector, smram_state+SMRAM_DS); - WRITE32(cpustate->sreg[FS].selector, smram_state+SMRAM_FS); - WRITE32(cpustate->sreg[GS].selector, smram_state+SMRAM_GS); - WRITE32(cpustate->ldtr.segment, smram_state+SMRAM_LDTR); - WRITE32(cpustate->task.segment, smram_state+SMRAM_TR); - - WRITE32(cpustate->dr[7], smram_state+SMRAM_DR7); - WRITE32(cpustate->dr[6], smram_state+SMRAM_DR6); - WRITE32(REG32(EAX), smram_state+SMRAM_EAX); - WRITE32(REG32(ECX), smram_state+SMRAM_ECX); - WRITE32(REG32(EDX), smram_state+SMRAM_EDX); - WRITE32(REG32(EBX), smram_state+SMRAM_EBX); - WRITE32(REG32(ESP), smram_state+SMRAM_ESP); - WRITE32(REG32(EBP), smram_state+SMRAM_EBP); - WRITE32(REG32(ESI), smram_state+SMRAM_ESI); - WRITE32(REG32(EDI), smram_state+SMRAM_EDI); - WRITE32(cpustate->eip, smram_state+SMRAM_EIP); - WRITE32(old_flags, smram_state+SMRAM_EFLAGS); - WRITE32(cpustate->cr[3], smram_state+SMRAM_CR3); - WRITE32(old_cr0, smram_state+SMRAM_CR0); - - cpustate->sreg[DS].selector = cpustate->sreg[ES].selector = cpustate->sreg[FS].selector = cpustate->sreg[GS].selector = cpustate->sreg[SS].selector = 0; - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffffffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x8093; - cpustate->sreg[DS].valid = cpustate->sreg[ES].valid = cpustate->sreg[FS].valid = cpustate->sreg[GS].valid = cpustate->sreg[SS].valid =true; - cpustate->sreg[CS].selector = 0x3000; // pentium only, ppro sel = smbase >> 4 - cpustate->sreg[CS].base = cpustate->smbase; - cpustate->sreg[CS].limit = 0xffffffff; - cpustate->sreg[CS].flags = 0x8093; - cpustate->sreg[CS].valid = true; - cpustate->cr[4] = 0; - cpustate->dr[7] = 0x400; - cpustate->eip = 0x8000; - - cpustate->nmi_masked = true; - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::i386_set_irq_line(int irqline, int state) -{ - int first_cycles = cpustate->cycles; - - if (state != CLEAR_LINE && cpustate->halted) - { - cpustate->halted = 0; - } - - if ( irqline == INPUT_LINE_NMI ) - { - /* NMI (I do not think that this is 100% right) */ - if(cpustate->nmi_masked) - { - cpustate->nmi_latched = true; - return; - } - if ( state ) - i386_trap(2, 1, 0); - } - else - { - cpustate->irq_state = state; - } - cpustate->extra_cycles += first_cycles - cpustate->cycles; - cpustate->cycles = first_cycles; -} - -void I386_OPS_BASE::i386_set_a20_line(int state) -{ - if (state) - { - cpustate->a20_mask = ~0; - } - else - { - cpustate->a20_mask = ~(1 << 20); - } - // TODO: how does A20M and the tlb interact - vtlb_flush_dynamic(cpustate->vtlb); -} - -// BASE execution : EXECUTE without DMA, BIOS and debugger. -#include "../../debugger.h" -int I386_OPS_BASE::cpu_execute_i386(int cycles) -{ - CHANGE_PC(cpustate->eip); - - if (cpustate->halted || cpustate->busreq) - { - if (cycles == -1) { - int passed_cycles = max(1, cpustate->extra_cycles); - // this is main cpu, cpustate->cycles is not used - /*cpustate->cycles = */cpustate->extra_cycles = 0; - cpustate->tsc += passed_cycles; - cpustate->total_cycles += passed_cycles; - return passed_cycles; - } else { - cpustate->cycles += cycles; - cpustate->base_cycles = cpustate->cycles; - - /* adjust for any interrupts that came in */ - cpustate->cycles -= cpustate->extra_cycles; - cpustate->extra_cycles = 0; - - /* if busreq is raised, spin cpu while remained clock */ - if (cpustate->cycles > 0) { - cpustate->cycles = 0; - } - int passed_cycles = cpustate->base_cycles - cpustate->cycles; - cpustate->tsc += passed_cycles; - cpustate->total_cycles += passed_cycles; - return passed_cycles; - } - } - - if (cycles == -1) { - cpustate->cycles = 1; - } else { - cpustate->cycles += cycles; - } - cpustate->base_cycles = cpustate->cycles; - - /* adjust for any interrupts that came in */ - cpustate->cycles -= cpustate->extra_cycles; - cpustate->extra_cycles = 0; - - while( cpustate->cycles > 0 && !cpustate->busreq ) - { - int first_cycles = cpustate->cycles; - i386_check_irq_line(); - cpustate->operand_size = cpustate->sreg[CS].d; - cpustate->xmm_operand_size = 0; - cpustate->address_size = cpustate->sreg[CS].d; - cpustate->operand_prefix = 0; - cpustate->address_prefix = 0; - - cpustate->ext = 1; - int old_tf = cpustate->TF; - - cpustate->debugger->add_cpu_trace(cpustate->pc); - cpustate->segment_prefix = 0; - cpustate->prev_eip = cpustate->eip; - cpustate->prev_pc = cpustate->pc; - - if(cpustate->delayed_interrupt_enable != 0) - { - cpustate->IF = 1; - cpustate->delayed_interrupt_enable = 0; - } -#ifdef DEBUG_MISSING_OPCODE - cpustate->opcode_bytes_length = 0; - cpustate->opcode_pc = cpustate->pc; -#endif - try - { - I386OP(decode_opcode)(); - if(cpustate->TF && old_tf) - { - cpustate->prev_eip = cpustate->eip; - cpustate->ext = 1; - i386_trap(1,0,0); - } - if(cpustate->lock && (cpustate->opcode != 0xf0)) - cpustate->lock = false; - } - catch(UINT64 e) - { - cpustate->ext = 1; - i386_trap_with_error(e&0xffffffff,0,0,e>>32); - } - /* adjust for any interrupts that came in */ - cpustate->cycles -= cpustate->extra_cycles; - cpustate->extra_cycles = 0; - cpustate->total_cycles += first_cycles - cpustate->cycles; - } - - /* if busreq is raised, spin cpu while remained clock */ - if (cpustate->cycles > 0 && cpustate->busreq) { - cpustate->total_cycles += cpustate->cycles; - cpustate->cycles = 0; - } - int passed_cycles = cpustate->base_cycles - cpustate->cycles; - cpustate->tsc += passed_cycles; - cpustate->total_cycles += passed_cycles; - return passed_cycles; -} - -/*************************************************************************/ - -int I386_OPS_BASE::cpu_translate_i386(void *cpudevice, address_spacenum space, int intention, offs_t *address) -{ - i386_state *cpu_state = (i386_state *)cpudevice; - int ret = TRUE; - if(space == AS_PROGRAM) - ret = i386_translate_address(intention, address, NULL); - *address &= cpu_state->a20_mask; - return ret; -} - -/*****************************************************************************/ -/* Intel 486 */ - - -void *I386_OPS_BASE::cpu_init_i486(void) -{ - i386_common_init(32); - build_opcode_table(OP_I386 | OP_FPU | OP_I486); - build_x87_opcode_table(); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I486]; - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I486]; - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_i486(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x0093; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x00000010; - cpustate->eflags = 0; - cpustate->eflags_mask = 0x00077fd7; - cpustate->eip = 0xfff0; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 4 (486), Model 0/1 (DX), Stepping 3 - REG32(EAX) = 0; - REG32(EDX) = (4 << 8) | (0 << 4) | (3); - - CHANGE_PC(cpustate->eip); -} - -/*****************************************************************************/ -/* Pentium */ - - -void *I386_OPS_BASE::cpu_init_pentium(void) -{ - // 64 dtlb small, 8 dtlb large, 32 itlb - i386_common_init(96); - build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM); - build_x87_opcode_table(); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM]; - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM]; - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_pentium(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x0093; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x00000010; - cpustate->eflags = 0x00200000; - cpustate->eflags_mask = 0x003f7fd7; - cpustate->eip = 0xfff0; - cpustate->mxcsr = 0x1f80; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->smbase = 0x30000; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 5 (Pentium), Model 2 (75 - 200MHz), Stepping 5 - REG32(EAX) = 0; - REG32(EDX) = (5 << 8) | (2 << 4) | (5); - - cpustate->cpuid_id0 = 0x756e6547; // Genu - cpustate->cpuid_id1 = 0x49656e69; // ineI - cpustate->cpuid_id2 = 0x6c65746e; // ntel - - cpustate->cpuid_max_input_value_eax = 0x01; - cpustate->cpu_version = REG32(EDX); - - // [ 0:0] FPU on chip - // [ 2:2] I/O breakpoints - // [ 4:4] Time Stamp Counter - // [ 5:5] Pentium CPU style model specific registers - // [ 7:7] Machine Check Exception - // [ 8:8] CMPXCHG8B instruction - cpustate->feature_flags = 0x000001bf; - - CHANGE_PC(cpustate->eip); -} - -/*****************************************************************************/ -/* Cyrix MediaGX */ - - -void *I386_OPS_BASE::cpu_init_mediagx(void) -{ - // probably 32 unified - i386_common_init(32); - build_x87_opcode_table(); - build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_CYRIX); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_MEDIAGX]; - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_MEDIAGX]; - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_mediagx(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x0093; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x00000010; - cpustate->eflags = 0x00200000; - cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ - cpustate->eip = 0xfff0; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 4, Model 4 (MediaGX) - REG32(EAX) = 0; - REG32(EDX) = (4 << 8) | (4 << 4) | (1); /* TODO: is this correct? */ - - cpustate->cpuid_id0 = 0x69727943; // Cyri - cpustate->cpuid_id1 = 0x736e4978; // xIns - cpustate->cpuid_id2 = 0x6d616574; // tead - - cpustate->cpuid_max_input_value_eax = 0x01; - cpustate->cpu_version = REG32(EDX); - - // [ 0:0] FPU on chip - cpustate->feature_flags = 0x00000001; - - CHANGE_PC(cpustate->eip); -} - -/*****************************************************************************/ -/* Intel Pentium Pro */ - -void *I386_OPS_BASE::cpu_init_pentium_pro(void) -{ - // 64 dtlb small, 32 itlb - i386_common_init(96); - build_x87_opcode_table(); - build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_pentium_pro(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x0093; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x60000010; - cpustate->eflags = 0x00200000; - cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ - cpustate->eip = 0xfff0; - cpustate->mxcsr = 0x1f80; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->smbase = 0x30000; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 6, Model 1 (Pentium Pro) - REG32(EAX) = 0; - REG32(EDX) = (6 << 8) | (1 << 4) | (1); /* TODO: is this correct? */ - - cpustate->cpuid_id0 = 0x756e6547; // Genu - cpustate->cpuid_id1 = 0x49656e69; // ineI - cpustate->cpuid_id2 = 0x6c65746e; // ntel - - cpustate->cpuid_max_input_value_eax = 0x02; - cpustate->cpu_version = REG32(EDX); - - // [ 0:0] FPU on chip - // [ 2:2] I/O breakpoints - // [ 4:4] Time Stamp Counter - // [ 5:5] Pentium CPU style model specific registers - // [ 7:7] Machine Check Exception - // [ 8:8] CMPXCHG8B instruction - // [15:15] CMOV and FCMOV - // No MMX - cpustate->feature_flags = 0x000081bf; - - CHANGE_PC(cpustate->eip); -} - -/*****************************************************************************/ -/* Intel Pentium MMX */ - -void *I386_OPS_BASE::cpu_init_pentium_mmx(void) -{ - // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large - i386_common_init(96); - build_x87_opcode_table(); - build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_MMX); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_pentium_mmx(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x0093; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x60000010; - cpustate->eflags = 0x00200000; - cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ - cpustate->eip = 0xfff0; - cpustate->mxcsr = 0x1f80; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->smbase = 0x30000; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 5, Model 4 (P55C) - REG32(EAX) = 0; - REG32(EDX) = (5 << 8) | (4 << 4) | (1); - - cpustate->cpuid_id0 = 0x756e6547; // Genu - cpustate->cpuid_id1 = 0x49656e69; // ineI - cpustate->cpuid_id2 = 0x6c65746e; // ntel - - cpustate->cpuid_max_input_value_eax = 0x01; - cpustate->cpu_version = REG32(EDX); - - // [ 0:0] FPU on chip - // [ 2:2] I/O breakpoints - // [ 4:4] Time Stamp Counter - // [ 5:5] Pentium CPU style model specific registers - // [ 7:7] Machine Check Exception - // [ 8:8] CMPXCHG8B instruction - // [23:23] MMX instructions - cpustate->feature_flags = 0x008001bf; - - CHANGE_PC(cpustate->eip); -} - -/*****************************************************************************/ -/* Intel Pentium II */ - -void *I386_OPS_BASE::cpu_init_pentium2(void) -{ - // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large - i386_common_init(96); - build_x87_opcode_table(); - build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_pentium2(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x0093; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x60000010; - cpustate->eflags = 0x00200000; - cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ - cpustate->eip = 0xfff0; - cpustate->mxcsr = 0x1f80; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->smbase = 0x30000; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 6, Model 3 (Pentium II / Klamath) - REG32(EAX) = 0; - REG32(EDX) = (6 << 8) | (3 << 4) | (1); /* TODO: is this correct? */ - - cpustate->cpuid_id0 = 0x756e6547; // Genu - cpustate->cpuid_id1 = 0x49656e69; // ineI - cpustate->cpuid_id2 = 0x6c65746e; // ntel - - cpustate->cpuid_max_input_value_eax = 0x02; - cpustate->cpu_version = REG32(EDX); - - // [ 0:0] FPU on chip - cpustate->feature_flags = 0x008081bf; // TODO: enable relevant flags here - - CHANGE_PC(cpustate->eip); -} - -/*****************************************************************************/ -/* Intel Pentium III */ - -void *I386_OPS_BASE::cpu_init_pentium3(void) -{ - // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large - i386_common_init(96); - build_x87_opcode_table(); - build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX | OP_SSE); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_pentium3(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x0093; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x60000010; - cpustate->eflags = 0x00200000; - cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ - cpustate->eip = 0xfff0; - cpustate->mxcsr = 0x1f80; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->smbase = 0x30000; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [11:8] Family - // [ 7:4] Model - // [ 3:0] Stepping ID - // Family 6, Model 8 (Pentium III / Coppermine) - REG32(EAX) = 0; - REG32(EDX) = (6 << 8) | (8 << 4) | (10); - - cpustate->cpuid_id0 = 0x756e6547; // Genu - cpustate->cpuid_id1 = 0x49656e69; // ineI - cpustate->cpuid_id2 = 0x6c65746e; // ntel - - cpustate->cpuid_max_input_value_eax = 0x03; - cpustate->cpu_version = REG32(EDX); - - // [ 0:0] FPU on chip - // [ 4:4] Time Stamp Counter - // [ D:D] PTE Global Bit - cpustate->feature_flags = 0x00002011; // TODO: enable relevant flags here - - CHANGE_PC(cpustate->eip); -} - -/*****************************************************************************/ -/* Intel Pentium 4 */ - -void *I386_OPS_BASE::cpu_init_pentium4(void) -{ - // 128 dtlb, 64 itlb - i386_common_init(196); - build_x87_opcode_table(); - build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX | OP_SSE | OP_SSE2); - cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM]; // TODO: generate own cycle tables - return cpustate; -} - -void I386_OPS_BASE::cpu_reset_pentium4(void) -{ - zero_state(); - vtlb_flush_dynamic(cpustate->vtlb); - - cpustate->sreg[CS].selector = 0xf000; - cpustate->sreg[CS].base = 0xffff0000; - cpustate->sreg[CS].limit = 0xffff; - cpustate->sreg[CS].flags = 0x009b; - - cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000; - cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff; - cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092; - - cpustate->idtr.base = 0; - cpustate->idtr.limit = 0x3ff; - - cpustate->a20_mask = ~0; - - cpustate->cr[0] = 0x60000010; - cpustate->eflags = 0x00200000; - cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */ - cpustate->eip = 0xfff0; - cpustate->mxcsr = 0x1f80; - cpustate->smm = false; - cpustate->smi_latched = false; - cpustate->smbase = 0x30000; - cpustate->nmi_masked = false; - cpustate->nmi_latched = false; - - x87_reset(); - - // [27:20] Extended family - // [19:16] Extended model - // [13:12] Type - // [11: 8] Family - // [ 7: 4] Model - // [ 3: 0] Stepping ID - // Family 15, Model 0 (Pentium 4 / Willamette) - REG32(EAX) = 0; - REG32(EDX) = (0 << 20) | (0xf << 8) | (0 << 4) | (1); - - cpustate->cpuid_id0 = 0x756e6547; // Genu - cpustate->cpuid_id1 = 0x49656e69; // ineI - cpustate->cpuid_id2 = 0x6c65746e; // ntel - - cpustate->cpuid_max_input_value_eax = 0x02; - cpustate->cpu_version = REG32(EDX); - - // [ 0:0] FPU on chip - cpustate->feature_flags = 0x00000001; // TODO: enable relevant flags here - - CHANGE_PC(cpustate->eip); -} - diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.h b/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.h deleted file mode 100644 index bfc970d47..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386_opdef.h +++ /dev/null @@ -1,2961 +0,0 @@ - -#ifndef __LIB_I386_OPDEF_H__ -#define __LIB_I386_OPDEF_H__ - -#include "../../../common.h" -#ifndef __BIG_ENDIAN__ -#define LSB_FIRST -#endif -#include "../../../fileio.h" -#include "../device.h" -#include "./i386priv.h" -#include "./i386ops.h" -#include "./vtlb.h" - -#ifndef INLINE -#define INLINE inline -#endif - -#define U64(v) UINT64(v) - -//#define fatalerror(...) exit(1) -#define fatalerror(...) -#define logerror(...) -#define popmessage(...) - -#define X86_NUM_CPUS 4 -#define CPU_CYCLES_I386 0 -#define CPU_CYCLES_I486 1 -#define CPU_CYCLES_PENTIUM 2 -#define CPU_CYCLES_MEDIAGX 3 - -enum X86_CYCLES -{ - CYCLES_MOV_REG_REG, - CYCLES_MOV_REG_MEM, - CYCLES_MOV_MEM_REG, - CYCLES_MOV_IMM_REG, - CYCLES_MOV_IMM_MEM, - CYCLES_MOV_ACC_MEM, - CYCLES_MOV_MEM_ACC, - CYCLES_MOV_REG_SREG, - CYCLES_MOV_MEM_SREG, - CYCLES_MOV_SREG_REG, - CYCLES_MOV_SREG_MEM, - CYCLES_MOVSX_REG_REG, - CYCLES_MOVSX_MEM_REG, - CYCLES_MOVZX_REG_REG, - CYCLES_MOVZX_MEM_REG, - CYCLES_PUSH_RM, - CYCLES_PUSH_REG_SHORT, - CYCLES_PUSH_SREG, - CYCLES_PUSH_IMM, - CYCLES_PUSHA, - CYCLES_POP_RM, - CYCLES_POP_REG_SHORT, - CYCLES_POP_SREG, - CYCLES_POPA, - CYCLES_XCHG_REG_REG, - CYCLES_XCHG_REG_MEM, - CYCLES_IN, - CYCLES_IN_VAR, - CYCLES_OUT, - CYCLES_OUT_VAR, - CYCLES_LEA, - CYCLES_LDS, - CYCLES_LES, - CYCLES_LFS, - CYCLES_LGS, - CYCLES_LSS, - CYCLES_CLC, - CYCLES_CLD, - CYCLES_CLI, - CYCLES_CLTS, - CYCLES_CMC, - CYCLES_LAHF, - CYCLES_POPF, - CYCLES_PUSHF, - CYCLES_SAHF, - CYCLES_STC, - CYCLES_STD, - CYCLES_STI, - CYCLES_ALU_REG_REG, - CYCLES_ALU_REG_MEM, - CYCLES_ALU_MEM_REG, - CYCLES_ALU_IMM_REG, - CYCLES_ALU_IMM_MEM, - CYCLES_ALU_IMM_ACC, - CYCLES_INC_REG, - CYCLES_INC_MEM, - CYCLES_DEC_REG, - CYCLES_DEC_MEM, - CYCLES_CMP_REG_REG, - CYCLES_CMP_REG_MEM, - CYCLES_CMP_MEM_REG, - CYCLES_CMP_IMM_REG, - CYCLES_CMP_IMM_MEM, - CYCLES_CMP_IMM_ACC, - CYCLES_TEST_REG_REG, - CYCLES_TEST_REG_MEM, - CYCLES_TEST_IMM_REG, - CYCLES_TEST_IMM_MEM, - CYCLES_TEST_IMM_ACC, - CYCLES_NEG_REG, - CYCLES_NEG_MEM, - CYCLES_AAA, - CYCLES_AAS, - CYCLES_DAA, - CYCLES_DAS, - CYCLES_MUL8_ACC_REG, - CYCLES_MUL8_ACC_MEM, - CYCLES_MUL16_ACC_REG, - CYCLES_MUL16_ACC_MEM, - CYCLES_MUL32_ACC_REG, - CYCLES_MUL32_ACC_MEM, - CYCLES_IMUL8_ACC_REG, - CYCLES_IMUL8_ACC_MEM, - CYCLES_IMUL16_ACC_REG, - CYCLES_IMUL16_ACC_MEM, - CYCLES_IMUL32_ACC_REG, - CYCLES_IMUL32_ACC_MEM, - CYCLES_IMUL8_REG_REG, - CYCLES_IMUL8_REG_MEM, - CYCLES_IMUL16_REG_REG, - CYCLES_IMUL16_REG_MEM, - CYCLES_IMUL32_REG_REG, - CYCLES_IMUL32_REG_MEM, - CYCLES_IMUL16_REG_IMM_REG, - CYCLES_IMUL16_MEM_IMM_REG, - CYCLES_IMUL32_REG_IMM_REG, - CYCLES_IMUL32_MEM_IMM_REG, - CYCLES_DIV8_ACC_REG, - CYCLES_DIV8_ACC_MEM, - CYCLES_DIV16_ACC_REG, - CYCLES_DIV16_ACC_MEM, - CYCLES_DIV32_ACC_REG, - CYCLES_DIV32_ACC_MEM, - CYCLES_IDIV8_ACC_REG, - CYCLES_IDIV8_ACC_MEM, - CYCLES_IDIV16_ACC_REG, - CYCLES_IDIV16_ACC_MEM, - CYCLES_IDIV32_ACC_REG, - CYCLES_IDIV32_ACC_MEM, - CYCLES_AAD, - CYCLES_AAM, - CYCLES_CBW, - CYCLES_CWD, - CYCLES_ROTATE_REG, - CYCLES_ROTATE_MEM, - CYCLES_ROTATE_CARRY_REG, - CYCLES_ROTATE_CARRY_MEM, - CYCLES_SHLD_REG, - CYCLES_SHLD_MEM, - CYCLES_SHRD_REG, - CYCLES_SHRD_MEM, - CYCLES_NOT_REG, - CYCLES_NOT_MEM, - CYCLES_CMPS, - CYCLES_INS, - CYCLES_LODS, - CYCLES_MOVS, - CYCLES_OUTS, - CYCLES_SCAS, - CYCLES_STOS, - CYCLES_XLAT, - CYCLES_REP_CMPS_BASE, - CYCLES_REP_INS_BASE, - CYCLES_REP_LODS_BASE, - CYCLES_REP_MOVS_BASE, - CYCLES_REP_OUTS_BASE, - CYCLES_REP_SCAS_BASE, - CYCLES_REP_STOS_BASE, - CYCLES_REP_CMPS, - CYCLES_REP_INS, - CYCLES_REP_LODS, - CYCLES_REP_MOVS, - CYCLES_REP_OUTS, - CYCLES_REP_SCAS, - CYCLES_REP_STOS, - CYCLES_BSF_BASE, - CYCLES_BSF, - CYCLES_BSR_BASE, - CYCLES_BSR, - CYCLES_BT_IMM_REG, - CYCLES_BT_IMM_MEM, - CYCLES_BT_REG_REG, - CYCLES_BT_REG_MEM, - CYCLES_BTC_IMM_REG, - CYCLES_BTC_IMM_MEM, - CYCLES_BTC_REG_REG, - CYCLES_BTC_REG_MEM, - CYCLES_BTR_IMM_REG, - CYCLES_BTR_IMM_MEM, - CYCLES_BTR_REG_REG, - CYCLES_BTR_REG_MEM, - CYCLES_BTS_IMM_REG, - CYCLES_BTS_IMM_MEM, - CYCLES_BTS_REG_REG, - CYCLES_BTS_REG_MEM, - CYCLES_CALL, // E8 - CYCLES_CALL_REG, // FF /2 - CYCLES_CALL_MEM, // FF /2 - CYCLES_CALL_INTERSEG, // 9A - CYCLES_CALL_REG_INTERSEG, // FF /3 - CYCLES_CALL_MEM_INTERSEG, // FF /3 - CYCLES_JMP_SHORT, // EB - CYCLES_JMP, // E9 - CYCLES_JMP_REG, // FF /4 - CYCLES_JMP_MEM, // FF /4 - CYCLES_JMP_INTERSEG, // EA - CYCLES_JMP_REG_INTERSEG, // FF /5 - CYCLES_JMP_MEM_INTERSEG, // FF /5 - CYCLES_RET, // C3 - CYCLES_RET_IMM, // C2 - CYCLES_RET_INTERSEG, // CB - CYCLES_RET_IMM_INTERSEG, // CA - CYCLES_JCC_DISP8, - CYCLES_JCC_FULL_DISP, - CYCLES_JCC_DISP8_NOBRANCH, - CYCLES_JCC_FULL_DISP_NOBRANCH, - CYCLES_JCXZ, - CYCLES_JCXZ_NOBRANCH, - CYCLES_LOOP, - CYCLES_LOOPZ, - CYCLES_LOOPNZ, - CYCLES_SETCC_REG, - CYCLES_SETCC_MEM, - CYCLES_ENTER, - CYCLES_LEAVE, - CYCLES_INT, - CYCLES_INT3, - CYCLES_INTO_OF1, - CYCLES_INTO_OF0, - CYCLES_BOUND_IN_RANGE, - CYCLES_BOUND_OUT_RANGE, - CYCLES_IRET, - CYCLES_HLT, - CYCLES_MOV_REG_CR0, - CYCLES_MOV_REG_CR2, - CYCLES_MOV_REG_CR3, - CYCLES_MOV_CR_REG, - CYCLES_MOV_REG_DR0_3, - CYCLES_MOV_REG_DR6_7, - CYCLES_MOV_DR6_7_REG, - CYCLES_MOV_DR0_3_REG, - CYCLES_MOV_REG_TR6_7, - CYCLES_MOV_TR6_7_REG, - CYCLES_NOP, - CYCLES_WAIT, - CYCLES_ARPL_REG, - CYCLES_ARPL_MEM, - CYCLES_LAR_REG, - CYCLES_LAR_MEM, - CYCLES_LGDT, - CYCLES_LIDT, - CYCLES_LLDT_REG, - CYCLES_LLDT_MEM, - CYCLES_LMSW_REG, - CYCLES_LMSW_MEM, - CYCLES_LSL_REG, - CYCLES_LSL_MEM, - CYCLES_LTR_REG, - CYCLES_LTR_MEM, - CYCLES_SGDT, - CYCLES_SIDT, - CYCLES_SLDT_REG, - CYCLES_SLDT_MEM, - CYCLES_SMSW_REG, - CYCLES_SMSW_MEM, - CYCLES_STR_REG, - CYCLES_STR_MEM, - CYCLES_VERR_REG, - CYCLES_VERR_MEM, - CYCLES_VERW_REG, - CYCLES_VERW_MEM, - CYCLES_LOCK, - - CYCLES_BSWAP, - CYCLES_CMPXCHG8B, - CYCLES_CMPXCHG, - CYCLES_CPUID, - CYCLES_CPUID_EAX1, - CYCLES_INVD, - CYCLES_XADD, - CYCLES_RDTSC, - CYCLES_RSM, - CYCLES_RDMSR, - - CYCLES_FABS, - CYCLES_FADD, - CYCLES_FBLD, - CYCLES_FBSTP, - CYCLES_FCHS, - CYCLES_FCLEX, - CYCLES_FCOM, - CYCLES_FCOS, - CYCLES_FDECSTP, - CYCLES_FDISI, - CYCLES_FDIV, - CYCLES_FDIVR, - CYCLES_FENI, - CYCLES_FFREE, - CYCLES_FIADD, - CYCLES_FICOM, - CYCLES_FIDIV, - CYCLES_FILD, - CYCLES_FIMUL, - CYCLES_FINCSTP, - CYCLES_FINIT, - CYCLES_FIST, - CYCLES_FISUB, - CYCLES_FLD, - CYCLES_FLDZ, - CYCLES_FLD1, - CYCLES_FLDL2E, - CYCLES_FLDL2T, - CYCLES_FLDLG2, - CYCLES_FLDLN2, - CYCLES_FLDPI, - CYCLES_FLDCW, - CYCLES_FLDENV, - CYCLES_FMUL, - CYCLES_FNOP, - CYCLES_FPATAN, - CYCLES_FPREM, - CYCLES_FPREM1, - CYCLES_FPTAN, - CYCLES_FRNDINT, - CYCLES_FRSTOR, - CYCLES_FSAVE, - CYCLES_FSCALE, - CYCLES_FSETPM, - CYCLES_FSIN, - CYCLES_FSINCOS, - CYCLES_FSQRT, - CYCLES_FST, - CYCLES_FSTCW, - CYCLES_FSTENV, - CYCLES_FSTSW, - CYCLES_FSUB, - CYCLES_FSUBR, - CYCLES_FTST, - CYCLES_FUCOM, - CYCLES_FXAM, - CYCLES_FXCH, - CYCLES_FXTRACT, - CYCLES_FYL2X, - CYCLES_FYL2XPI, - CYCLES_CMPXCHG_REG_REG_T, - CYCLES_CMPXCHG_REG_REG_F, - CYCLES_CMPXCHG_REG_MEM_T, - CYCLES_CMPXCHG_REG_MEM_F, - CYCLES_XADD_REG_REG, - CYCLES_XADD_REG_MEM, - - CYCLES_NUM_OPCODES -}; - -struct X86_CYCLE_TABLE -{ - X86_CYCLES op; - UINT8 cpu_cycles[X86_NUM_CPUS][2]; -}; - -/************************************* - * - * Defines - * - *************************************/ - -#define X87_SW_IE 0x0001 -#define X87_SW_DE 0x0002 -#define X87_SW_ZE 0x0004 -#define X87_SW_OE 0x0008 -#define X87_SW_UE 0x0010 -#define X87_SW_PE 0x0020 -#define X87_SW_SF 0x0040 -#define X87_SW_ES 0x0080 -#define X87_SW_C0 0x0100 -#define X87_SW_C1 0x0200 -#define X87_SW_C2 0x0400 -#define X87_SW_TOP_SHIFT 11 -#define X87_SW_TOP_MASK 7 -#define X87_SW_C3 0x4000 -#define X87_SW_BUSY 0x8000 - -#define X87_CW_IM 0x0001 -#define X87_CW_DM 0x0002 -#define X87_CW_ZM 0x0004 -#define X87_CW_OM 0x0008 -#define X87_CW_UM 0x0010 -#define X87_CW_PM 0x0020 -#define X87_CW_IEM 0x0080 -#define X87_CW_PC_SHIFT 8 -#define X87_CW_PC_MASK 3 -#define X87_CW_PC_SINGLE 0 -#define X87_CW_PC_DOUBLE 2 -#define X87_CW_PC_EXTEND 3 -#define X87_CW_RC_SHIFT 10 -#define X87_CW_RC_MASK 3 -#define X87_CW_RC_NEAREST 0 -#define X87_CW_RC_DOWN 1 -#define X87_CW_RC_UP 2 -#define X87_CW_RC_ZERO 3 - -#define X87_TW_MASK 3 -#define X87_TW_VALID 0 -#define X87_TW_ZERO 1 -#define X87_TW_SPECIAL 2 -#define X87_TW_EMPTY 3 - - -/************************************* - * - * Macros - * - *************************************/ - -#define ST_TO_PHYS(x) (((cpustate->x87_sw >> X87_SW_TOP_SHIFT) + (x)) & X87_SW_TOP_MASK) -#define ST(x) (cpustate->x87_reg[ST_TO_PHYS(x)]) -#define X87_TW_FIELD_SHIFT(x) ((x) << 1) -#define X87_TAG(x) ((cpustate->x87_tw >> X87_TW_FIELD_SHIFT(x)) & X87_TW_MASK) -#define X87_RC ((cpustate->x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK) -#define X87_IS_ST_EMPTY(x) (X87_TAG(ST_TO_PHYS(x)) == X87_TW_EMPTY) -#define X87_SW_C3_0 X87_SW_C0 - -#define UNIMPLEMENTED fatalerror("Unimplemented x87 op: %s (PC:%x)\n", __FUNCTION__, cpustate->pc) - -/*****************************************************************************/ -/* src/emu/devcpu.h */ - -// CPU interface functions -#define CPU_INIT_NAME(name) I386_OPS_BASE::cpu_init_##name -#define CPU_INIT(name) void* CPU_INIT_NAME(name)() -#define CPU_INIT_CALL_NAME(name) cpu_init_##name -#define CPU_INIT_CALL(name) CPU_INIT_CALL_NAME(name)() - -#define CPU_RESET_NAME(name) I386_OPS_BASE::cpu_reset_##name -#define CPU_RESET(name) void CPU_RESET_NAME(name)() -#define CPU_RESET_CALL_NAME(name) cpu_reset_##name -#define CPU_RESET_CALL(name) CPU_RESET_CALL_NAME(name)() - -#define CPU_EXECUTE_NAME(name) I386_OPS_BASE::cpu_execute_##name -#define CPU_EXECUTE(name) int CPU_EXECUTE_NAME(name)(int cycles) -#define CPU_EXECUTE_CALL_NAME(name) cpu_execute_##name -#define CPU_EXECUTE_CALL(name) CPU_EXECUTE_CALL_NAME(name)(cycles) - -#define CPU_TRANSLATE_NAME(name) I386_OPS_BASE::cpu_translate_##name -#define CPU_TRANSLATE(name) int CPU_TRANSLATE_NAME(name)(void *cpudevice, address_spacenum space, int intention, offs_t *address) -#define CPU_TRANSLATE_CALL_NAME(name) cpu_translate_##name -#define CPU_TRANSLATE_CALL(name) CPU_TRANSLATE_CALL_NAME(name)(cpudevice, space, intention, address) - -#define CPU_DISASSEMBLE_NAME(name) I386_OPS_BASE::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(name) cpu_disassemble_##name -#define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_CALL_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/dimemory.h */ - -enum { - I386_OPS_CPUTYPE_I386 = 0, - I386_OPS_CPUTYPE_I486, - I386_OPS_CPUTYPE_PENTIUM, - I386_OPS_CPUTYPE_MEDIAGX, - I386_OPS_CPUTYPE_PENTIUM_PRO, - I386_OPS_CPUTYPE_PENTIUM_MMX, - I386_OPS_CPUTYPE_PENTIUM2, - I386_OPS_CPUTYPE_PENTIUM3, - I386_OPS_CPUTYPE_PENTIUM4, - I386_OPS_CPUTYPE_IX87FPU, - I386_OPS_CPUTYPE_END -}; - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ -/* VTLB state */ -struct vtlb_state -{ - void * cpudevice; /* CPU device */ - address_spacenum space; /* address space */ - int dynamic; /* number of dynamic entries */ - int fixed; /* number of fixed entries */ - int dynindex; /* index of next dynamic entry */ - int pageshift; /* bits to shift to get page index */ - int addrwidth; /* logical address bus width */ - offs_t * live; /* array of live entries by table index */ - int * fixedpages; /* number of pages each fixed entry covers */ - vtlb_entry * table; /* table of entries by address */ - vtlb_entry * save; /* cache of live table entries for saving */ -}; - -class DEBUG; -class I386_OPS_BASE { -protected: - i386_state *cpustate; - int _cputype; -// Parameters. - //const X86_CYCLE_TABLE *x86_cycle_table; - //const X86_OPCODE *x86_opcode_table; - //X86_OPCODE x86_opcode_table[]; - - int i386_parity_table[256]; - MODRM_TABLE i386_MODRM_table[256]; - i386_state __cpustate; - UINT8 cycle_table_rm[X86_NUM_CPUS][CYCLES_NUM_OPCODES]; - UINT8 cycle_table_pm[X86_NUM_CPUS][CYCLES_NUM_OPCODES]; - const floatx80 fx80_zero = { 0x0000, U64(0x0000000000000000) }; - const floatx80 fx80_one = { 0x3fff, U64(0x8000000000000000) }; - const floatx80 fx80_ninf = { 0xffff, U64(0x8000000000000000) }; - const floatx80 fx80_inan = { 0xffff, U64(0xc000000000000000) }; -/* Maps x87 round modes to SoftFloat round modes */ - const int x87_to_sf_rc[4] = { - float_round_nearest_even, - float_round_down, - float_round_up, - float_round_to_zero, - }; - DEVICE *d_mem; - DEVICE *d_io; - DEVICE *d_pic; - DEVICE *d_bios; - DEVICE *d_dma; - - UINT32 i386_escape_ea; // hack around GCC 4.6 error because we need the side effects of GetEA() - - - void process_state_SREG(I386_SREG* val, FILEIO* state_fio); - void process_state_SYS_TABLE(I386_SYS_TABLE* val, FILEIO* state_fio); - void process_state_SEG_DESC(I386_SEG_DESC* val, FILEIO* state_fio); - void process_state_GPR(I386_GPR* val, FILEIO* state_fio); - void process_state_floatx80(floatx80* val, FILEIO* state_fio); - void process_state_XMM_REG(XMM_REG* val, FILEIO* state_fio); - void process_state_vtlb(vtlb_state* val, FILEIO* state_fio); - -public: - I386_OPS_BASE(int cputypes = I386_OPS_CPUTYPE_I386) - { - cpustate = NULL; - _cputype = cputypes; - } - ~I386_OPS_BASE() {} - virtual void I386OP_D(decode_opcode)(); - - int i386_translate_address(int intention, offs_t *address, vtlb_entry *entry); - virtual int cpu_translate_i386(void *cpudevice, address_spacenum space, int intention, offs_t *address); - virtual int cpu_execute_i386(int cycles); - virtual void i386_trap(int irq, int irq_gate, int trap_level); - virtual void i386_trap_with_error(int irq, int irq_gate, int trap_level, UINT32 error); - void i386_set_irq_line(int irqline, int state); - void i386_set_a20_line(int state); - int i386_limit_check( int seg, UINT32 offset, UINT32 size); - void i386_vtlb_free(void); - void i386_free_state(void); - - i386_state *get_cpu_state(void) { return cpustate; } - int get_extra_clock() { return cpustate->extra_cycles; } - void set_extra_clock(int n) { cpustate->extra_cycles += n; } - - uint32_t get_pc() { return cpustate->pc; } - uint32_t get_prev_pc() { return cpustate->prev_pc; } - void set_address_mask(uint32_t mask) { cpustate->a20_mask = mask; } - uint32_t get_address_mask() { return cpustate->a20_mask; } - void set_shutdown_flag(int n) { cpustate->shutdown = n; } - int get_shutdown_flag() { return cpustate->shutdown; } - - void set_busreq(bool n) { cpustate->busreq = n ? 1 : 0; } - bool get_busreq() { return cpustate->busreq; } - INLINE void check_ioperm( offs_t port, UINT8 mask); - - void set_context_pic(DEVICE *dev) { - cpustate->pic = dev; - d_pic = dev; - } - virtual void set_context_progmem_stored(DEVICE *dev) { - //cpustate->program_stored = dev; - } - void set_context_progmem(DEVICE *dev) { - cpustate->program = dev; - d_mem = dev; - } - - virtual void set_context_pseudo_bios(DEVICE *dev) { - //cpustate->bios = dev; - //d_bios = dev; - } - - virtual void set_context_dma(DEVICE *dev) { - //cpustate->dma = dev; - //d_dma = dev; - } - - void set_context_io(DEVICE *dev) { - cpustate->io = dev; - d_io = dev; - } - - virtual void set_context_io_stored(DEVICE *dev) { - //cpustate->io_stored = dev; - - } - - virtual void set_context_emu(EMU *p_emu) { - //cpustate->emu = p_emu; - } - - virtual void set_context_debugger(DEBUGGER *debugger) { - //cpustate->debugger = dev; - } - - virtual bool write_debug_reg(const _TCHAR *reg, uint32_t data) { return false; } - virtual uint32_t read_debug_reg(const _TCHAR *reg) { return 0; } - - virtual int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len) { return 0;} - void vtlb_flush_dynamic(void) { vtlb_flush_dynamic(cpustate->vtlb); } - - bool process_state(FILEIO *state_fio, bool loading); - -protected: - // Utilities - void build_cycle_table(); - virtual i386_state *i386_common_init(int tlbsize); - void build_opcode_table( UINT32 features); - void zero_state(); - void pentium_smi(); - - UINT32 i386_load_protected_mode_segment( I386_SREG *seg, UINT64 *desc ); - void i386_load_call_gate(I386_CALL_GATE *gate); - void i386_set_descriptor_accessed( UINT16 selector); - void i386_load_segment_descriptor( int segment ); - UINT32 i386_get_stack_segment(UINT8 privilege); - UINT32 i386_get_stack_ptr(UINT8 privilege); - - UINT32 get_flags(); - void set_flags( UINT32 f ); - - void sib_byte(UINT8 mod, UINT32* out_ea, UINT8* out_segment); - void modrm_to_EA(UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment); - - UINT32 GetNonTranslatedEA(UINT8 modrm,UINT8 *seg); - UINT32 GetEA(UINT8 modrm, int rwn, UINT32 size); - - // - void i386_check_sreg_validity(int reg); - void i386_sreg_load( UINT16 selector, UINT8 reg, bool *fault); - void i286_task_switch( UINT16 selector, UINT8 nested); - void i386_task_switch( UINT16 selector, UINT8 nested); - void i386_check_irq_line(); - - void i386_protected_mode_jump( UINT16 seg, UINT32 off, int indirect, int operand32); - void i386_protected_mode_call( UINT16 seg, UINT32 off, int indirect, int operand32); - void i386_protected_mode_retf(UINT8 count, UINT8 operand32); - void i386_protected_mode_iret(int operand32); - - // Reporter. - void report_invalid_opcode(); - void report_invalid_modrm(const char* opcode, UINT8 modrm); - - //LINES - void i386_postload(); - - /* ----- initialization/teardown ----- */ - /* allocate a new VTLB for the given CPU */ - vtlb_state *vtlb_alloc(void *cpu, address_spacenum space, int fixed_entries, int dynamic_entries); - /* free an allocated VTLB */ - void vtlb_free(vtlb_state *vtlb); - - /* called by the CPU core in response to an unmapped access */ - int vtlb_fill(vtlb_state *vtlb, offs_t address, int intention); - /* load a fixed VTLB entry */ - void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value); - /* load a dynamic VTLB entry */ - void vtlb_dynload(vtlb_state *vtlb, UINT32 index, offs_t address, vtlb_entry value); - /* ----- flushing ----- */ - /* flush all knowledge from the dynamic part of the VTLB */ - void vtlb_flush_dynamic(vtlb_state *vtlb); - /* flush knowledge of a particular address from the VTLB */ - void vtlb_flush_address(vtlb_state *vtlb, offs_t address); - /* ----- accessors ----- */ - /* return a pointer to the base of the linear VTLB lookup table */ - const vtlb_entry *vtlb_table(vtlb_state *vtlb); - - virtual int cpu_disassemble_x86_16(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom) { return 0; } - virtual int cpu_disassemble_x86_32(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom) { return 0; } - virtual int cpu_disassemble_x86_64(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom) { return 0; } - -public: - // Init per vm.. - void *cpu_init_i386(void); - void *cpu_init_i486(void); - void *cpu_init_pentium(void); - void *cpu_init_mediagx(void); - void *cpu_init_pentium_pro(void); - void *cpu_init_pentium_mmx(void); - void *cpu_init_pentium2(void); - void *cpu_init_pentium3(void); - void *cpu_init_pentium4(void); - // Reset per type. - void cpu_reset_i386(void); - void cpu_reset_i486(void); - void cpu_reset_pentium(void); - void cpu_reset_mediagx(void); - void cpu_reset_pentium_pro(void); - void cpu_reset_pentium_mmx(void); - void cpu_reset_pentium2(void); - void cpu_reset_pentium3(void); - void cpu_reset_pentium4(void); - - // INSNs. - // i386/op16 - void I386OP_D(adc_rm16_r16)(); // Opcode 0x11 - void I386OP_D(adc_r16_rm16)(); // Opcode 0x13 - void I386OP_D(adc_ax_i16)(); // Opcode 0x15 - void I386OP_D(add_rm16_r16)(); // Opcode 0x01 - void I386OP_D(add_r16_rm16)(); // Opcode 0x03 - void I386OP_D(add_ax_i16)(); // Opcode 0x05 - void I386OP_D(and_rm16_r16)(); // Opcode 0x21 - void I386OP_D(and_r16_rm16)(); // Opcode 0x23 - void I386OP_D(and_ax_i16)(); // Opcode 0x25 - void I386OP_D(bsf_r16_rm16)(); // Opcode 0x0f bc - void I386OP_D(bsr_r16_rm16)(); // Opcode 0x0f bd - void I386OP_D(bt_rm16_r16)(); // Opcode 0x0f a3 - void I386OP_D(btc_rm16_r16)(); // Opcode 0x0f bb - void I386OP_D(btr_rm16_r16)(); // Opcode 0x0f b3 - void I386OP_D(bts_rm16_r16)(); // Opcode 0x0f ab - virtual void I386OP_D(call_abs16)(); // Opcode 0x9a - virtual void I386OP_D(call_rel16)(); // Opcode 0xe8 - void I386OP_D(cbw)(); // Opcode 0x98 - void I386OP_D(cmp_rm16_r16)(); // Opcode 0x39 - void I386OP_D(cmp_r16_rm16)(); // Opcode 0x3b - void I386OP_D(cmp_ax_i16)(); // Opcode 0x3d - void I386OP_D(cmpsw)(); // Opcode 0xa7 - void I386OP_D(cwd)(); // Opcode 0x99 - void I386OP_D(dec_ax)(); // Opcode 0x48 - void I386OP_D(dec_cx)(); // Opcode 0x49 - void I386OP_D(dec_dx)(); // Opcode 0x4a - void I386OP_D(dec_bx)(); // Opcode 0x4b - void I386OP_D(dec_sp)(); // Opcode 0x4c - void I386OP_D(dec_bp)(); // Opcode 0x4d - void I386OP_D(dec_si)(); // Opcode 0x4e - void I386OP_D(dec_di)(); // Opcode 0x4f - void I386OP_D(imul_r16_rm16)(); // Opcode 0x0f af - void I386OP_D(imul_r16_rm16_i16)(); // Opcode 0x69 - void I386OP_D(imul_r16_rm16_i8)(); // Opcode 0x6b - void I386OP_D(in_ax_i8)(); // Opcode 0xe5 - void I386OP_D(in_ax_dx)(); // Opcode 0xed - void I386OP_D(inc_ax)(); // Opcode 0x40 - void I386OP_D(inc_cx)(); // Opcode 0x41 - void I386OP_D(inc_dx)(); // Opcode 0x42 - void I386OP_D(inc_bx)(); // Opcode 0x43 - void I386OP_D(inc_sp)(); // Opcode 0x44 - void I386OP_D(inc_bp)(); // Opcode 0x45 - void I386OP_D(inc_si)(); // Opcode 0x46 - void I386OP_D(inc_di)(); // Opcode 0x47 - void I386OP_D(iret16)(); // Opcode 0xcf - void I386OP_D(ja_rel16)(); // Opcode 0x0f 87 - void I386OP_D(jbe_rel16)(); // Opcode 0x0f 86 - void I386OP_D(jc_rel16)(); // Opcode 0x0f 82 - void I386OP_D(jg_rel16)(); // Opcode 0x0f 8f - void I386OP_D(jge_rel16)(); // Opcode 0x0f 8d - void I386OP_D(jl_rel16)(); // Opcode 0x0f 8c - void I386OP_D(jle_rel16)(); // Opcode 0x0f 8e - void I386OP_D(jnc_rel16)(); // Opcode 0x0f 83 - void I386OP_D(jno_rel16)(); // Opcode 0x0f 81 - void I386OP_D(jnp_rel16)(); // Opcode 0x0f 8b - void I386OP_D(jns_rel16)(); // Opcode 0x0f 89 - void I386OP_D(jnz_rel16)(); // Opcode 0x0f 85 - void I386OP_D(jo_rel16)(); // Opcode 0x0f 80 - void I386OP_D(jp_rel16)(); // Opcode 0x0f 8a - void I386OP_D(js_rel16)(); // Opcode 0x0f 88 - void I386OP_D(jz_rel16)(); // Opcode 0x0f 84 - void I386OP_D(jcxz16)(); // Opcode 0xe3 - void I386OP_D(jmp_rel16)(); // Opcode 0xe9 - void I386OP_D(jmp_abs16)(); // Opcode 0xea - void I386OP_D(lea16)(); // Opcode 0x8d - void I386OP_D(enter16)(); // Opcode 0xc8 - void I386OP_D(leave16)(); // Opcode 0xc9 - void I386OP_D(lodsw)(); // Opcode 0xad - void I386OP_D(loop16)(); // Opcode 0xe2 - void I386OP_D(loopne16)(); // Opcode 0xe0 - void I386OP_D(loopz16)(); // Opcode 0xe1 - void I386OP_D(mov_rm16_r16)(); // Opcode 0x89 - void I386OP_D(mov_r16_rm16)(); // Opcode 0x8b - void I386OP_D(mov_rm16_i16)(); // Opcode 0xc7 - void I386OP_D(mov_ax_m16)(); // Opcode 0xa1 - void I386OP_D(mov_m16_ax)(); // Opcode 0xa3 - void I386OP_D(mov_ax_i16)(); // Opcode 0xb8 - void I386OP_D(mov_cx_i16)(); // Opcode 0xb9 - void I386OP_D(mov_dx_i16)(); // Opcode 0xba - void I386OP_D(mov_bx_i16)(); // Opcode 0xbb - void I386OP_D(mov_sp_i16)(); // Opcode 0xbc - void I386OP_D(mov_bp_i16)(); // Opcode 0xbd - void I386OP_D(mov_si_i16)(); // Opcode 0xbe - void I386OP_D(mov_di_i16)(); // Opcode 0xbf - void I386OP_D(movsw)(); // Opcode 0xa5 - void I386OP_D(movsx_r16_rm8)(); // Opcode 0x0f be - void I386OP_D(movzx_r16_rm8)(); // Opcode 0x0f b6 - void I386OP_D(or_rm16_r16)(); // Opcode 0x09 - void I386OP_D(or_r16_rm16)(); // Opcode 0x0b - void I386OP_D(or_ax_i16)(); // Opcode 0x0d - void I386OP_D(out_ax_i8)(); // Opcode 0xe7 - void I386OP_D(out_ax_dx)(); // Opcode 0xef - void I386OP_D(pop_ax)(); // Opcode 0x58 - void I386OP_D(pop_cx)(); // Opcode 0x59 - void I386OP_D(pop_dx)(); // Opcode 0x5a - void I386OP_D(pop_bx)(); // Opcode 0x5b - void I386OP_D(pop_sp)(); // Opcode 0x5c - void I386OP_D(pop_bp)(); // Opcode 0x5d - void I386OP_D(pop_si)(); // Opcode 0x5e - void I386OP_D(pop_di)(); // Opcode 0x5f - void I386OP_D(pop_ds16)(); // Opcode 0x1f - void I386OP_D(pop_es16)(); // Opcode 0x07 - void I386OP_D(pop_fs16)(); // Opcode 0x0f a1 - void I386OP_D(pop_gs16)(); // Opcode 0x0f a9 - void I386OP_D(pop_ss16)(); // Opcode 0x17 - void I386OP_D(pop_rm16)(); // Opcode 0x8f - void I386OP_D(popa)(); // Opcode 0x61 - void I386OP_D(popf)(); // Opcode 0x9d - void I386OP_D(push_ax)(); // Opcode 0x50 - void I386OP_D(push_cx)(); // Opcode 0x51 - void I386OP_D(push_dx)(); // Opcode 0x52 - void I386OP_D(push_bx)(); // Opcode 0x53 - void I386OP_D(push_sp)(); // Opcode 0x54 - void I386OP_D(push_bp)(); // Opcode 0x55 - void I386OP_D(push_si)(); // Opcode 0x56 - void I386OP_D(push_di)(); // Opcode 0x57 - void I386OP_D(push_cs16)(); // Opcode 0x0e - void I386OP_D(push_ds16)(); // Opcode 0x1e - void I386OP_D(push_es16)(); // Opcode 0x06 - void I386OP_D(push_fs16)(); // Opcode 0x0f a0 - void I386OP_D(push_gs16)(); // Opcode 0x0f a8 - void I386OP_D(push_ss16)(); // Opcode 0x16 - void I386OP_D(push_i16)(); // Opcode 0x68 - void I386OP_D(pusha)(); // Opcode 0x60 - void I386OP_D(pushf)(); // Opcode 0x9c - void I386OP_D(ret_near16_i16)(); // Opcode 0xc2 - void I386OP_D(ret_near16)(); // Opcode 0xc3 - void I386OP_D(sbb_rm16_r16)(); // Opcode 0x19 - void I386OP_D(sbb_r16_rm16)(); // Opcode 0x1b - void I386OP_D(sbb_ax_i16)(); // Opcode 0x1d - void I386OP_D(scasw)(); // Opcode 0xaf - void I386OP_D(shld16_i8)(); // Opcode 0x0f a4 - void I386OP_D(shld16_cl)(); // Opcode 0x0f a5 - void I386OP_D(shrd16_i8)(); // Opcode 0x0f ac - void I386OP_D(shrd16_cl)(); // Opcode 0x0f ad - void I386OP_D(stosw)(); // Opcode 0xab - void I386OP_D(sub_rm16_r16)(); // Opcode 0x29 - void I386OP_D(sub_r16_rm16)(); // Opcode 0x2b - void I386OP_D(sub_ax_i16)(); // Opcode 0x2d - void I386OP_D(test_ax_i16)(); // Opcode 0xa9 - void I386OP_D(test_rm16_r16)(); // Opcode 0x85 - void I386OP_D(xchg_ax_cx)(); // Opcode 0x91 - void I386OP_D(xchg_ax_dx)(); // Opcode 0x92 - void I386OP_D(xchg_ax_bx)(); // Opcode 0x93 - void I386OP_D(xchg_ax_sp)(); // Opcode 0x94 - void I386OP_D(xchg_ax_bp)(); // Opcode 0x95 - void I386OP_D(xchg_ax_si)(); // Opcode 0x96 - void I386OP_D(xchg_ax_di)(); // Opcode 0x97 - void I386OP_D(xchg_r16_rm16)(); // Opcode 0x87 - void I386OP_D(xor_rm16_r16)(); // Opcode 0x31 - void I386OP_D(xor_r16_rm16)(); // Opcode 0x33 - void I386OP_D(xor_ax_i16)(); // Opcode 0x35 - void I386OP_D(group81_16)(); // Opcode 0x81 - void I386OP_D(group83_16)(); // Opcode 0x83 - void I386OP_D(groupC1_16)(); // Opcode 0xc1 - void I386OP_D(groupD1_16)(); // Opcode 0xd1 - void I386OP_D(groupD3_16)(); // Opcode 0xd3 - void I386OP_D(groupF7_16)(); // Opcode 0xf7 - virtual void I386OP_D(groupFF_16)(); // Opcode 0xff - void I386OP_D(group0F00_16)(); // Opcode 0x0f 00 - void I386OP_D(group0F01_16)(); // Opcode 0x0f 01 - void I386OP_D(group0FBA_16)(); // Opcode 0x0f ba - void I386OP_D(lar_r16_rm16)(); // Opcode 0x0f 0x02 - void I386OP_D(lsl_r16_rm16)(); // Opcode 0x0f 0x03 - void I386OP_D(bound_r16_m16_m16)(); // Opcode 0x62 - void I386OP_D(retf16)(); // Opcode 0xcb - void I386OP_D(retf_i16)(); // Opcode 0xca - void I386OP_D(lds16)(); // Opcode 0xc5 - void I386OP_D(lss16)(); // Opcode 0x0f 0xb2 - void I386OP_D(les16)(); // Opcode 0xc4 - void I386OP_D(lfs16)(); // Opcode 0x0f 0xb4 - void I386OP_D(lgs16)(); // Opcode 0x0f 0xb5 - UINT16 I386OP_D(shift_rotate16)( UINT8 modrm, UINT32 value, UINT8 shift); - UINT8 I386OP_D(shift_rotate8)( UINT8 modrm, UINT32 value, UINT8 shift); - //i386/op32 - void I386OP_D(adc_rm32_r32)(); // Opcode 0x11 - void I386OP_D(adc_r32_rm32)(); // Opcode 0x13 - void I386OP_D(adc_eax_i32)(); // Opcode 0x15 - void I386OP_D(add_rm32_r32)(); // Opcode 0x01 - void I386OP_D(add_r32_rm32)(); // Opcode 0x03 - void I386OP_D(add_eax_i32)(); // Opcode 0x05 - void I386OP_D(and_rm32_r32)(); // Opcode 0x21 - void I386OP_D(and_r32_rm32)(); // Opcode 0x23 - void I386OP_D(and_eax_i32)(); // Opcode 0x25 - void I386OP_D(bsf_r32_rm32)(); // Opcode 0x0f bc - void I386OP_D(bsr_r32_rm32)(); // Opcode 0x0f bd - void I386OP_D(bt_rm32_r32)(); // Opcode 0x0f a3 - void I386OP_D(btc_rm32_r32)(); // Opcode 0x0f bb - void I386OP_D(btr_rm32_r32)(); // Opcode 0x0f b3 - void I386OP_D(bts_rm32_r32)(); // Opcode 0x0f ab - void I386OP_D(call_abs32)(); // Opcode 0x9a - void I386OP_D(call_rel32)(); // Opcode 0xe8 - void I386OP_D(cdq)(); // Opcode 0x99 - void I386OP_D(cmp_rm32_r32)(); // Opcode 0x39 - void I386OP_D(cmp_r32_rm32)(); // Opcode 0x3b - void I386OP_D(cmp_eax_i32)(); // Opcode 0x3d - void I386OP_D(cmpsd)(); // Opcode 0xa7 - void I386OP_D(cwde)(); // Opcode 0x98 - void I386OP_D(dec_eax)(); // Opcode 0x48 - void I386OP_D(dec_ecx)(); // Opcode 0x49 - void I386OP_D(dec_edx)(); // Opcode 0x4a - void I386OP_D(dec_ebx)(); // Opcode 0x4b - void I386OP_D(dec_esp)(); // Opcode 0x4c - void I386OP_D(dec_ebp)(); // Opcode 0x4d - void I386OP_D(dec_esi)(); // Opcode 0x4e - void I386OP_D(dec_edi)(); // Opcode 0x4f - void I386OP_D(imul_r32_rm32)(); // Opcode 0x0f af - void I386OP_D(imul_r32_rm32_i32)(); // Opcode 0x69 - void I386OP_D(imul_r32_rm32_i8)(); // Opcode 0x6b - void I386OP_D(in_eax_i8)(); // Opcode 0xe5 - void I386OP_D(in_eax_dx)(); // Opcode 0xed - void I386OP_D(inc_eax)(); // Opcode 0x40 - void I386OP_D(inc_ecx)(); // Opcode 0x41 - void I386OP_D(inc_edx)(); // Opcode 0x42 - void I386OP_D(inc_ebx)(); // Opcode 0x43 - void I386OP_D(inc_esp)(); // Opcode 0x44 - void I386OP_D(inc_ebp)(); // Opcode 0x45 - void I386OP_D(inc_esi)(); // Opcode 0x46 - void I386OP_D(inc_edi)(); // Opcode 0x47 - void I386OP_D(iret32)(); // Opcode 0xcf - void I386OP_D(ja_rel32)(); // Opcode 0x0f 87 - void I386OP_D(jbe_rel32)(); // Opcode 0x0f 86 - void I386OP_D(jc_rel32)(); // Opcode 0x0f 82 - void I386OP_D(jg_rel32)(); // Opcode 0x0f 8f - void I386OP_D(jge_rel32)(); // Opcode 0x0f 8d - void I386OP_D(jl_rel32)(); // Opcode 0x0f 8c - void I386OP_D(jle_rel32)(); // Opcode 0x0f 8e - void I386OP_D(jnc_rel32)(); // Opcode 0x0f 83 - void I386OP_D(jno_rel32)(); // Opcode 0x0f 81 - void I386OP_D(jnp_rel32)(); // Opcode 0x0f 8b - void I386OP_D(jns_rel32)(); // Opcode 0x0f 89 - void I386OP_D(jnz_rel32)(); // Opcode 0x0f 85 - void I386OP_D(jo_rel32)(); // Opcode 0x0f 80 - void I386OP_D(jp_rel32)(); // Opcode 0x0f 8a - void I386OP_D(js_rel32)(); // Opcode 0x0f 88 - void I386OP_D(jz_rel32)(); // Opcode 0x0f 84 - void I386OP_D(jcxz32)(); // Opcode 0xe3 - void I386OP_D(jmp_rel32)(); // Opcode 0xe9 - void I386OP_D(jmp_abs32)(); // Opcode 0xea - void I386OP_D(lea32)(); // Opcode 0x8d - void I386OP_D(enter32)(); // Opcode 0xc8 - void I386OP_D(leave32)(); // Opcode 0xc9 - void I386OP_D(lodsd)(); // Opcode 0xad - void I386OP_D(loop32)(); // Opcode 0xe2 - void I386OP_D(loopne32)(); // Opcode 0xe0 - void I386OP_D(loopz32)(); // Opcode 0xe1 - void I386OP_D(mov_rm32_r32)(); // Opcode 0x89 - void I386OP_D(mov_r32_rm32)(); // Opcode 0x8b - void I386OP_D(mov_rm32_i32)(); // Opcode 0xc7 - void I386OP_D(mov_eax_m32)(); // Opcode 0xa1 - void I386OP_D(mov_m32_eax)(); // Opcode 0xa3 - void I386OP_D(mov_eax_i32)(); // Opcode 0xb8 - void I386OP_D(mov_ecx_i32)(); // Opcode 0xb9 - void I386OP_D(mov_edx_i32)(); // Opcode 0xba - void I386OP_D(mov_ebx_i32)(); // Opcode 0xbb - void I386OP_D(mov_esp_i32)(); // Opcode 0xbc - void I386OP_D(mov_ebp_i32)(); // Opcode 0xbd - void I386OP_D(mov_esi_i32)(); // Opcode 0xbe - void I386OP_D(mov_edi_i32)(); // Opcode 0xbf - void I386OP_D(movsd)(); // Opcode 0xa5 - void I386OP_D(movsx_r32_rm8)(); // Opcode 0x0f be - void I386OP_D(movsx_r32_rm16)(); // Opcode 0x0f bf - void I386OP_D(movzx_r32_rm8)(); // Opcode 0x0f b6 - void I386OP_D(movzx_r32_rm16)(); // Opcode 0x0f b7 - void I386OP_D(or_rm32_r32)(); // Opcode 0x09 - void I386OP_D(or_r32_rm32)(); // Opcode 0x0b - void I386OP_D(or_eax_i32)(); // Opcode 0x0d - void I386OP_D(out_eax_i8)(); // Opcode 0xe7 - void I386OP_D(out_eax_dx)(); // Opcode 0xef - void I386OP_D(pop_eax)(); // Opcode 0x58 - void I386OP_D(pop_ecx)(); // Opcode 0x59 - void I386OP_D(pop_edx)(); // Opcode 0x5a - void I386OP_D(pop_ebx)(); // Opcode 0x5b - void I386OP_D(pop_esp)(); // Opcode 0x5c - void I386OP_D(pop_ebp)(); // Opcode 0x5d - void I386OP_D(pop_esi)(); // Opcode 0x5e - void I386OP_D(pop_edi)(); // Opcode 0x5f - void I386OP_D(pop_ds32)(); // Opcode 0x1f - void I386OP_D(pop_es32)(); // Opcode 0x07 - void I386OP_D(pop_fs32)(); // Opcode 0x0f a1 - void I386OP_D(pop_gs32)(); // Opcode 0x0f a9 - void I386OP_D(pop_ss32)(); // Opcode 0x17 - void I386OP_D(pop_rm32)(); // Opcode 0x8f - void I386OP_D(popad)(); // Opcode 0x61 - void I386OP_D(popfd)(); // Opcode 0x9d - void I386OP_D(push_eax)(); // Opcode 0x50 - void I386OP_D(push_ecx)(); // Opcode 0x51 - void I386OP_D(push_edx)(); // Opcode 0x52 - void I386OP_D(push_ebx)(); // Opcode 0x53 - void I386OP_D(push_esp)(); // Opcode 0x54 - void I386OP_D(push_ebp)(); // Opcode 0x55 - void I386OP_D(push_esi)(); // Opcode 0x56 - void I386OP_D(push_edi)(); // Opcode 0x57 - void I386OP_D(push_cs32)(); // Opcode 0x0e - void I386OP_D(push_ds32)(); // Opcode 0x1e - void I386OP_D(push_es32)(); // Opcode 0x06 - void I386OP_D(push_fs32)(); // Opcode 0x0f a0 - void I386OP_D(push_gs32)(); // Opcode 0x0f a8 - void I386OP_D(push_ss32)(); // Opcode 0x16 - void I386OP_D(push_i32)(); // Opcode 0x68 - void I386OP_D(pushad)(); // Opcode 0x60 - void I386OP_D(pushfd)(); // Opcode 0x9c - void I386OP_D(ret_near32_i16)(); // Opcode 0xc2 - void I386OP_D(ret_near32)(); // Opcode 0xc3 - void I386OP_D(sbb_rm32_r32)(); // Opcode 0x19 - void I386OP_D(sbb_r32_rm32)(); // Opcode 0x1b - void I386OP_D(sbb_eax_i32)(); // Opcode 0x1d - void I386OP_D(scasd)(); // Opcode 0xaf - void I386OP_D(shld32_i8)(); // Opcode 0x0f a4 - void I386OP_D(shld32_cl)(); // Opcode 0x0f a5 - void I386OP_D(shrd32_i8)(); // Opcode 0x0f ac - void I386OP_D(shrd32_cl)(); // Opcode 0x0f ad - void I386OP_D(stosd)(); // Opcode 0xab - void I386OP_D(sub_rm32_r32)(); // Opcode 0x29 - void I386OP_D(sub_r32_rm32)(); // Opcode 0x2b - void I386OP_D(sub_eax_i32)(); // Opcode 0x2d - void I386OP_D(test_eax_i32)(); // Opcode 0xa9 - void I386OP_D(test_rm32_r32)(); // Opcode 0x85 - void I386OP_D(xchg_eax_ecx)(); // Opcode 0x91 - void I386OP_D(xchg_eax_edx)(); // Opcode 0x92 - void I386OP_D(xchg_eax_ebx)(); // Opcode 0x93 - void I386OP_D(xchg_eax_esp)(); // Opcode 0x94 - void I386OP_D(xchg_eax_ebp)(); // Opcode 0x95 - void I386OP_D(xchg_eax_esi)(); // Opcode 0x96 - void I386OP_D(xchg_eax_edi)(); // Opcode 0x97 - void I386OP_D(xchg_r32_rm32)(); // Opcode 0x87 - void I386OP_D(xor_rm32_r32)(); // Opcode 0x31 - void I386OP_D(xor_r32_rm32)(); // Opcode 0x33 - void I386OP_D(xor_eax_i32)(); // Opcode 0x35 - void I386OP_D(group81_32)(); // Opcode 0x81 - void I386OP_D(group83_32)(); // Opcode 0x83 - void I386OP_D(groupC1_32)(); // Opcode 0xc1 - void I386OP_D(groupD1_32)(); // Opcode 0xd1 - void I386OP_D(groupD3_32)(); // Opcode 0xd3 - void I386OP_D(groupF7_32)(); // Opcode 0xf7 - void I386OP_D(groupFF_32)(); // Opcode 0xff - void I386OP_D(group0F00_32)(); // Opcode 0x0f 00 - void I386OP_D(group0F01_32)(); // Opcode 0x0f 01 - void I386OP_D(group0FBA_32)(); // Opcode 0x0f ba - void I386OP_D(lar_r32_rm32)(); // Opcode 0x0f 0x02 - void I386OP_D(lsl_r32_rm32)(); // Opcode 0x0f 0x03 - void I386OP_D(bound_r32_m32_m32)(); // Opcode 0x62 - void I386OP_D(retf32)(); // Opcode 0xcb - void I386OP_D(retf_i32)(); // Opcode 0xca - void I386OP_D(load_far_pointer32)( int s); - void I386OP_D(lds32)(); // Opcode 0xc5 - void I386OP_D(lss32)(); // Opcode 0x0f 0xb2 - void I386OP_D(les32)(); // Opcode 0xc4 - void I386OP_D(lfs32)(); // Opcode 0x0f 0xb4 - void I386OP_D(lgs32)(); // Opcode 0x0f 0xb5 -// i386 other OPS. - void I386OP_D(adc_rm8_r8)(); // Opcode 0x10 - void I386OP_D(adc_r8_rm8)(); // Opcode 0x12 - void I386OP_D(adc_al_i8)(); // Opcode 0x14 - void I386OP_D(add_rm8_r8)(); // Opcode 0x00 - void I386OP_D(add_r8_rm8)(); // Opcode 0x02 - void I386OP_D(add_al_i8)(); // Opcode 0x04 - void I386OP_D(and_rm8_r8)(); // Opcode 0x20 - void I386OP_D(and_r8_rm8)(); // Opcode 0x22 - void I386OP_D(and_al_i8)(); // Opcode 0x24 - void I386OP_D(clc)(); // Opcode 0xf8 - void I386OP_D(cld)(); // Opcode 0xfc - void I386OP_D(cli)(); // Opcode 0xfa - void I386OP_D(cmc)(); // Opcode 0xf5 - void I386OP_D(cmp_rm8_r8)(); // Opcode 0x38 - void I386OP_D(cmp_r8_rm8)(); // Opcode 0x3a - void I386OP_D(cmp_al_i8)(); // Opcode 0x3c - void I386OP_D(cmpsb)(); // Opcode 0xa6 - void I386OP_D(in_al_i8)(); // Opcode 0xe4 - void I386OP_D(in_al_dx)(); // Opcode 0xec - void I386OP_D(ja_rel8)(); // Opcode 0x77 - void I386OP_D(jbe_rel8)(); // Opcode 0x76 - void I386OP_D(jc_rel8)(); // Opcode 0x72 - void I386OP_D(jg_rel8)(); // Opcode 0x7f - void I386OP_D(jge_rel8)(); // Opcode 0x7d - void I386OP_D(jl_rel8)(); // Opcode 0x7c - void I386OP_D(jle_rel8)(); // Opcode 0x7e - void I386OP_D(jnc_rel8)(); // Opcode 0x73 - void I386OP_D(jno_rel8)(); // Opcode 0x71 - void I386OP_D(jnp_rel8)(); // Opcode 0x7b - void I386OP_D(jns_rel8)(); // Opcode 0x79 - void I386OP_D(jnz_rel8)(); // Opcode 0x75 - void I386OP_D(jo_rel8)(); // Opcode 0x70 - void I386OP_D(jp_rel8)(); // Opcode 0x7a - void I386OP_D(js_rel8)(); // Opcode 0x78 - void I386OP_D(jz_rel8)(); // Opcode 0x74 - void I386OP_D(jmp_rel8)(); // Opcode 0xeb - void I386OP_D(lahf)(); // Opcode 0x9f - void I386OP_D(lodsb)(); // Opcode 0xac - void I386OP_D(mov_rm8_r8)(); // Opcode 0x88 - void I386OP_D(mov_r8_rm8)(); // Opcode 0x8a - void I386OP_D(mov_rm8_i8)(); // Opcode 0xc6 - void I386OP_D(mov_r32_cr)(); // Opcode 0x0f 20 - void I386OP_D(mov_r32_dr)(); // Opcode 0x0f 21 - void I386OP_D(mov_cr_r32)(); // Opcode 0x0f 22 - void I386OP_D(mov_dr_r32)(); // Opcode 0x0f 23 - void I386OP_D(mov_al_m8)(); // Opcode 0xa0 - void I386OP_D(mov_m8_al)(); // Opcode 0xa2 - void I386OP_D(mov_rm16_sreg)(); // Opcode 0x8c - void I386OP_D(mov_sreg_rm16)(); // Opcode 0x8e - void I386OP_D(mov_al_i8)(); // Opcode 0xb0 - void I386OP_D(mov_cl_i8)(); // Opcode 0xb1 - void I386OP_D(mov_dl_i8)(); // Opcode 0xb2 - void I386OP_D(mov_bl_i8)(); // Opcode 0xb3 - void I386OP_D(mov_ah_i8)(); // Opcode 0xb4 - void I386OP_D(mov_ch_i8)(); // Opcode 0xb5 - void I386OP_D(mov_dh_i8)(); // Opcode 0xb6 - void I386OP_D(mov_bh_i8)(); // Opcode 0xb7 - void I386OP_D(movsb)(); // Opcode 0xa4 - void I386OP_D(or_rm8_r8)(); // Opcode 0x08 - void I386OP_D(or_r8_rm8)(); // Opcode 0x0a - void I386OP_D(or_al_i8)(); // Opcode 0x0c - void I386OP_D(out_al_i8)(); // Opcode 0xe6 - void I386OP_D(out_al_dx)(); // Opcode 0xee - void I386OP_D(arpl)(); // Opcode 0x63 - void I386OP_D(push_i8)(); // Opcode 0x6a - void I386OP_D(ins_generic)( int size); - void I386OP_D(insb)(); // Opcode 0x6c - void I386OP_D(insw)(); // Opcode 0x6d - void I386OP_D(insd)(); // Opcode 0x6d - void I386OP_D(outs_generic)( int size); - void I386OP_D(outsb)(); // Opcode 0x6e - void I386OP_D(outsw)(); // Opcode 0x6f - void I386OP_D(outsd)(); // Opcode 0x6f - void I386OP_D(repeat)( int invert_flag); - void I386OP_D(rep)(); // Opcode 0xf3 - void I386OP_D(repne)(); // Opcode 0xf2 - void I386OP_D(sahf)(); // Opcode 0x9e - void I386OP_D(sbb_rm8_r8)(); // Opcode 0x18 - void I386OP_D(sbb_r8_rm8)(); // Opcode 0x1a - void I386OP_D(sbb_al_i8)(); // Opcode 0x1c - void I386OP_D(scasb)(); // Opcode 0xae - void I386OP_D(setalc)(); // Opcode 0xd6 (undocumented) - void I386OP_D(seta_rm8)(); // Opcode 0x0f 97 - void I386OP_D(setbe_rm8)(); // Opcode 0x0f 96 - void I386OP_D(setc_rm8)(); // Opcode 0x0f 92 - void I386OP_D(setg_rm8)(); // Opcode 0x0f 9f - void I386OP_D(setge_rm8)(); // Opcode 0x0f 9d - void I386OP_D(setl_rm8)(); // Opcode 0x0f 9c - void I386OP_D(setle_rm8)(); // Opcode 0x0f 9e - void I386OP_D(setnc_rm8)(); // Opcode 0x0f 93 - void I386OP_D(setno_rm8)(); // Opcode 0x0f 91 - void I386OP_D(setnp_rm8)(); // Opcode 0x0f 9b - void I386OP_D(setns_rm8)(); // Opcode 0x0f 99 - void I386OP_D(setnz_rm8)(); // Opcode 0x0f 95 - void I386OP_D(seto_rm8)(); // Opcode 0x0f 90 - void I386OP_D(setp_rm8)(); // Opcode 0x0f 9a - void I386OP_D(sets_rm8)(); // Opcode 0x0f 98 - void I386OP_D(setz_rm8)(); // Opcode 0x0f 94 - void I386OP_D(stc)(); // Opcode 0xf9 - void I386OP_D(std)(); // Opcode 0xfd - void I386OP_D(sti)(); // Opcode 0xfb - void I386OP_D(stosb)(); // Opcode 0xaa - void I386OP_D(sub_rm8_r8)(); // Opcode 0x28 - void I386OP_D(sub_r8_rm8)(); // Opcode 0x2a - void I386OP_D(sub_al_i8)(); // Opcode 0x2c - void I386OP_D(test_al_i8)(); // Opcode 0xa8 - void I386OP_D(test_rm8_r8)(); // Opcode 0x84 - void I386OP_D(xchg_r8_rm8)(); // Opcode 0x86 - void I386OP_D(xor_rm8_r8)(); // Opcode 0x30 - void I386OP_D(xor_r8_rm8)(); // Opcode 0x32 - void I386OP_D(xor_al_i8)(); // Opcode 0x34 - void I386OP_D(group80_8)(); // Opcode 0x80 - void I386OP_D(groupC0_8)(); // Opcode 0xc0 - void I386OP_D(groupD0_8)(); // Opcode 0xd0 - void I386OP_D(groupD2_8)(); // Opcode 0xd2 - void I386OP_D(groupF6_8)(); // Opcode 0xf6 - void I386OP_D(groupFE_8)(); // Opcode 0xfe - void I386OP_D(segment_CS)(); // Opcode 0x2e - void I386OP_D(segment_DS)(); // Opcode 0x3e - void I386OP_D(segment_ES)(); // Opcode 0x26 - void I386OP_D(segment_FS)(); // Opcode 0x64 - void I386OP_D(segment_GS)(); // Opcode 0x65 - void I386OP_D(segment_SS)(); // Opcode 0x36 - void I386OP_D(operand_size)(); // Opcode prefix 0x66 - void I386OP_D(address_size)(); // Opcode 0x67 - void I386OP_D(nop)(); // Opcode 0x90 - void I386OP_D(int3)(); // Opcode 0xcc - virtual void I386OP_D(_int)(); // Opcode 0xcd - void I386OP_D(into)(); // Opcode 0xce - void I386OP_D(escape)(); // Opcodes 0xd8 - 0xdf - void I386OP_D(hlt)(); // Opcode 0xf4 - void I386OP_D(decimal_adjust)(int direction); - void I386OP_D(daa)(); // Opcode 0x27 - void I386OP_D(das)(); // Opcode 0x2f - void I386OP_D(aaa)(); // Opcode 0x37 - void I386OP_D(aas)(); // Opcode 0x3f - void I386OP_D(aad)(); // Opcode 0xd5 - void I386OP_D(aam)(); // Opcode 0xd4 - void I386OP_D(clts)(); // Opcode 0x0f 0x06 - void I386OP_D(wait)(); // Opcode 0x9B - void I386OP_D(lock)(); // Opcode 0xf0 - void I386OP_D(mov_r32_tr)(); // Opcode 0x0f 24 - void I386OP_D(mov_tr_r32)(); // Opcode 0x0f 26 - void I386OP_D(loadall)(); // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented - void I386OP_D(invalid)(); - void I386OP_D(xlat)(); // Opcode 0xd7 - bool I386OP_D(pop_seg16)( int segment); - bool I386OP_D(load_far_pointer16)(int s); - bool I386OP_D(pop_seg32)( int segment); -//i486 - void I486OP_D(cpuid)(); // Opcode 0x0F A2 - void I486OP_D(invd)(); // Opcode 0x0f 08 - void I486OP_D(wbinvd)(); // Opcode 0x0f 09 - void I486OP_D(cmpxchg_rm8_r8)(); // Opcode 0x0f b0 - void I486OP_D(cmpxchg_rm16_r16)(); // Opcode 0x0f b1 - void I486OP_D(cmpxchg_rm32_r32)(); // Opcode 0x0f b1 - void I486OP_D(xadd_rm8_r8)(); // Opcode 0x0f c0 - void I486OP_D(xadd_rm16_r16)(); // Opcode 0x0f c1 - void I486OP_D(xadd_rm32_r32)(); // Opcode 0x0f c1 - void I486OP_D(group0F01_16)(); // Opcode 0x0f 01 - void I486OP_D(group0F01_32)(); // Opcode 0x0f 01 - void I486OP_D(bswap_eax)(); // Opcode 0x0f 38 - void I486OP_D(bswap_ecx)(); // Opcode 0x0f 39 - void I486OP_D(bswap_edx)(); // Opcode 0x0f 3A - void I486OP_D(bswap_ebx)(); // Opcode 0x0f 3B - void I486OP_D(bswap_esp)(); // Opcode 0x0f 3C - void I486OP_D(bswap_ebp)(); // Opcode 0x0f 3D - void I486OP_D(bswap_esi)(); // Opcode 0x0f 3E - void I486OP_D(bswap_edi)(); // Opcode 0x0f 3F - void I486OP_D(mov_cr_r32)(); // Opcode 0x0f 22 -//Pentium, MMX, SSE. - void PENTIUMOP_D(rdmsr)(); // Opcode 0x0f 32 - void PENTIUMOP_D(wrmsr)(); // Opcode 0x0f 30 - void PENTIUMOP_D(rdtsc)(); // Opcode 0x0f 31 - void PENTIUMOP_D(ud2)(); // Opcode 0x0f 0b - void PENTIUMOP_D(rsm)(); - void PENTIUMOP_D(prefetch_m8)(); // Opcode 0x0f 18 - void PENTIUMOP_D(cmovo_r16_rm16)(); // Opcode 0x0f 40 - void PENTIUMOP_D(cmovo_r32_rm32)(); // Opcode 0x0f 40 - void PENTIUMOP_D(cmovno_r16_rm16)(); // Opcode 0x0f 41 - void PENTIUMOP_D(cmovno_r32_rm32)(); // Opcode 0x0f 41 - void PENTIUMOP_D(cmovb_r16_rm16)(); // Opcode 0x0f 42 - void PENTIUMOP_D(cmovb_r32_rm32)(); // Opcode 0x0f 42 - void PENTIUMOP_D(cmovae_r16_rm16)(); // Opcode 0x0f 43 - void PENTIUMOP_D(cmovae_r32_rm32)(); // Opcode 0x0f 43 - void PENTIUMOP_D(cmove_r16_rm16)(); // Opcode 0x0f 44 - void PENTIUMOP_D(cmove_r32_rm32)(); // Opcode 0x0f 44 - void PENTIUMOP_D(cmovne_r16_rm16)(); // Opcode 0x0f 45 - void PENTIUMOP_D(cmovne_r32_rm32)(); // Opcode 0x0f 45 - void PENTIUMOP_D(cmovbe_r16_rm16)(); // Opcode 0x0f 46 - void PENTIUMOP_D(cmovbe_r32_rm32)(); // Opcode 0x0f 46 - void PENTIUMOP_D(cmova_r16_rm16)(); // Opcode 0x0f 47 - void PENTIUMOP_D(cmova_r32_rm32)(); // Opcode 0x0f 47 - void PENTIUMOP_D(cmovs_r16_rm16)(); // Opcode 0x0f 48 - void PENTIUMOP_D(cmovs_r32_rm32)(); // Opcode 0x0f 48 - void PENTIUMOP_D(cmovns_r16_rm16)(); // Opcode 0x0f 49 - void PENTIUMOP_D(cmovns_r32_rm32)(); // Opcode 0x0f 49 - void PENTIUMOP_D(cmovp_r16_rm16)(); // Opcode 0x0f 4a - void PENTIUMOP_D(cmovp_r32_rm32)(); // Opcode 0x0f 4a - void PENTIUMOP_D(cmovnp_r16_rm16)(); // Opcode 0x0f 4b - void PENTIUMOP_D(cmovnp_r32_rm32)(); // Opcode 0x0f 4b - void PENTIUMOP_D(cmovl_r16_rm16)(); // Opcode 0x0f 4c - void PENTIUMOP_D(cmovl_r32_rm32)(); // Opcode 0x0f 4c - void PENTIUMOP_D(cmovge_r16_rm16)(); // Opcode 0x0f 4d - void PENTIUMOP_D(cmovge_r32_rm32)(); // Opcode 0x0f 4d - void PENTIUMOP_D(cmovle_r16_rm16)(); // Opcode 0x0f 4e - void PENTIUMOP_D(cmovle_r32_rm32)(); // Opcode 0x0f 4e - void PENTIUMOP_D(cmovg_r16_rm16)(); // Opcode 0x0f 4f - void PENTIUMOP_D(cmovg_r32_rm32)(); // Opcode 0x0f 4f - void PENTIUMOP_D(movnti_m16_r16)(); // Opcode 0f c3 - void PENTIUMOP_D(movnti_m32_r32)(); // Opcode 0f c3 - void PENTIUMOP_D(cmpxchg8b_m64)(); // Opcode 0x0f c7 - void PENTIUMOP_D(movntq_m64_r64)(); // Opcode 0f e7 - void PENTIUMOP_D(maskmovq_r64_r64)(); // Opcode 0f f7 - void SSEOP_D(maskmovdqu_r128_r128)(); // Opcode 66 0f f7 - void PENTIUMOP_D(popcnt_r16_rm16)(); // Opcode f3 0f b8 - void PENTIUMOP_D(popcnt_r32_rm32)(); // Opcode f3 0f b8 - void PENTIUMOP_D(tzcnt_r16_rm16)(); - void PENTIUMOP_D(tzcnt_r32_rm32)(); - void I386OP_D(cyrix_special)(); - void I386OP_D(cyrix_unknown)(); - void I386OP_D(cyrix_svdc)(); - void I386OP_D(cyrix_rsdc)(); - void I386OP_D(cyrix_svldt)(); - void I386OP_D(cyrix_rsldt)(); - void I386OP_D(cyrix_svts)(); - void I386OP_D(cyrix_rsts)(); - - void MMXOP_D(group_0f71)(); // Opcode 0f 71 - void SSEOP_D(group_660f71)(); // Opcode 66 0f 71 - void MMXOP_D(group_0f72)(); // Opcode 0f 72 - void SSEOP_D(group_660f72)(); // Opcode 66 0f 72 - void MMXOP_D(group_0f73)(); // Opcode 0f 73 - void SSEOP_D(group_660f73)(); // Opcode 66 0f 73 - void MMXOP_D(psrlw_r64_rm64)(); // Opcode 0f d1 - void MMXOP_D(psrld_r64_rm64)(); // Opcode 0f d2 - void MMXOP_D(psrlq_r64_rm64)(); // Opcode 0f d3 - void MMXOP_D(paddq_r64_rm64)(); // Opcode 0f d4 - void MMXOP_D(pmullw_r64_rm64)(); // Opcode 0f d5 - void MMXOP_D(psubusb_r64_rm64)(); // Opcode 0f d8 - void MMXOP_D(psubusw_r64_rm64)(); // Opcode 0f d9 - void MMXOP_D(pand_r64_rm64)(); // Opcode 0f db - void MMXOP_D(paddusb_r64_rm64)(); // Opcode 0f dc - void MMXOP_D(paddusw_r64_rm64)(); // Opcode 0f dd - void MMXOP_D(pandn_r64_rm64)(); // Opcode 0f df - void MMXOP_D(psraw_r64_rm64)(); // Opcode 0f e1 - void MMXOP_D(psrad_r64_rm64)(); // Opcode 0f e2 - void MMXOP_D(pmulhw_r64_rm64)(); // Opcode 0f e5 - void MMXOP_D(psubsb_r64_rm64)(); // Opcode 0f e8 - void MMXOP_D(psubsw_r64_rm64)(); // Opcode 0f e9 - void MMXOP_D(por_r64_rm64)(); // Opcode 0f eb - void MMXOP_D(paddsb_r64_rm64)(); // Opcode 0f ec - void MMXOP_D(paddsw_r64_rm64)(); // Opcode 0f ed - void MMXOP_D(pxor_r64_rm64)(); // Opcode 0f ef - void MMXOP_D(psllw_r64_rm64)(); // Opcode 0f f1 - void MMXOP_D(pslld_r64_rm64)(); // Opcode 0f f2 - void MMXOP_D(psllq_r64_rm64)(); // Opcode 0f f3 - void MMXOP_D(pmaddwd_r64_rm64)(); // Opcode 0f f5 - void MMXOP_D(psubb_r64_rm64)(); // Opcode 0f f8 - void MMXOP_D(psubw_r64_rm64)(); // Opcode 0f f9 - void MMXOP_D(psubd_r64_rm64)(); // Opcode 0f fa - void MMXOP_D(paddb_r64_rm64)(); // Opcode 0f fc - void MMXOP_D(paddw_r64_rm64)(); // Opcode 0f fd - void MMXOP_D(paddd_r64_rm64)(); // Opcode 0f fe - void MMXOP_D(emms)(); // Opcode 0f 77 - void MMXOP_D(movd_r64_rm32)(); // Opcode 0f 6e - void MMXOP_D(movq_r64_rm64)(); // Opcode 0f 6f - void MMXOP_D(movd_rm32_r64)(); // Opcode 0f 7e - void MMXOP_D(movq_rm64_r64)(); // Opcode 0f 7f - void MMXOP_D(pcmpeqb_r64_rm64)(); // Opcode 0f 74 - void MMXOP_D(pcmpeqw_r64_rm64)(); // Opcode 0f 75 - void MMXOP_D(pcmpeqd_r64_rm64)(); // Opcode 0f 76 - void MMXOP_D(pshufw_r64_rm64_i8)(); // Opcode 0f 70 - void SSEOP_D(punpcklbw_r128_rm128)(); // Opcode 66 0f 60 - void SSEOP_D(punpcklwd_r128_rm128)(); - void SSEOP_D(punpckldq_r128_rm128)(); - void SSEOP_D(punpcklqdq_r128_rm128)(); - void MMXOP_D(punpcklbw_r64_r64m32)(); // Opcode 0f 60 - void MMXOP_D(punpcklwd_r64_r64m32)(); // Opcode 0f 61 - void MMXOP_D(punpckldq_r64_r64m32)(); // Opcode 0f 62 - void MMXOP_D(packsswb_r64_rm64)(); // Opcode 0f 63 - void MMXOP_D(pcmpgtb_r64_rm64)(); // Opcode 0f 64 - void MMXOP_D(pcmpgtw_r64_rm64)(); // Opcode 0f 65 - void MMXOP_D(pcmpgtd_r64_rm64)(); // Opcode 0f 66 - void MMXOP_D(packuswb_r64_rm64)(); // Opcode 0f 67 - void MMXOP_D(punpckhbw_r64_rm64)(); // Opcode 0f 68 - void MMXOP_D(punpckhwd_r64_rm64)(); // Opcode 0f 69 - void MMXOP_D(punpckhdq_r64_rm64)(); // Opcode 0f 6a - void MMXOP_D(packssdw_r64_rm64)(); // Opcode 0f 6b - void SSEOP_D(group_0fae)(); // Opcode 0f ae - void SSEOP_D(cvttps2dq_r128_rm128)(); // Opcode f3 0f 5b - void SSEOP_D(cvtss2sd_r128_r128m32)(); // Opcode f3 0f 5a - void SSEOP_D(cvttss2si_r32_r128m32)(); // Opcode f3 0f 2c - void SSEOP_D(cvtss2si_r32_r128m32)(); // Opcode f3 0f 2d - void SSEOP_D(cvtsi2ss_r128_rm32)(); // Opcode f3 0f 2a - void SSEOP_D(cvtpi2ps_r128_rm64)(); // Opcode 0f 2a - void SSEOP_D(cvttps2pi_r64_r128m64)(); // Opcode 0f 2c - void SSEOP_D(cvtps2pi_r64_r128m64)(); // Opcode 0f 2d - void SSEOP_D(cvtps2pd_r128_r128m64)(); // Opcode 0f 5a - void SSEOP_D(cvtdq2ps_r128_rm128)(); // Opcode 0f 5b - void SSEOP_D(cvtdq2pd_r128_r128m64)(); // Opcode f3 0f e6 - void SSEOP_D(movss_r128_rm128)(); // Opcode f3 0f 10 - void SSEOP_D(movss_rm128_r128)(); // Opcode f3 0f 11 - void SSEOP_D(movsldup_r128_rm128)(); // Opcode f3 0f 12 - void SSEOP_D(movshdup_r128_rm128)(); // Opcode f3 0f 16 - void SSEOP_D(movaps_r128_rm128)(); // Opcode 0f 28 - void SSEOP_D(movaps_rm128_r128)(); // Opcode 0f 29 - void SSEOP_D(movups_r128_rm128)(); // Opcode 0f 10 - void SSEOP_D(movupd_r128_rm128)(); // Opcode 66 0f 10 - void SSEOP_D(movups_rm128_r128)(); // Opcode 0f 11 - void SSEOP_D(movupd_rm128_r128)(); // Opcode 66 0f 11 - void SSEOP_D(movlps_r128_m64)(); // Opcode 0f 12 - void SSEOP_D(movlpd_r128_m64)(); // Opcode 66 0f 12 - void SSEOP_D(movlps_m64_r128)(); // Opcode 0f 13 - void SSEOP_D(movlpd_m64_r128)(); // Opcode 66 0f 13 - void SSEOP_D(movhps_r128_m64)(); // Opcode 0f 16 - void SSEOP_D(movhpd_r128_m64)(); // Opcode 66 0f 16 - void SSEOP_D(movhps_m64_r128)(); // Opcode 0f 17 - void SSEOP_D(movhpd_m64_r128)(); // Opcode 66 0f 17 - void SSEOP_D(movntps_m128_r128)(); // Opcode 0f 2b - void SSEOP_D(movmskps_r16_r128)(); // Opcode 0f 50 - void SSEOP_D(movmskps_r32_r128)(); // Opcode 0f 50 - void SSEOP_D(movmskpd_r32_r128)(); // Opcode 66 0f 50 - void SSEOP_D(movq2dq_r128_r64)(); // Opcode f3 0f d6 - void SSEOP_D(movdqu_r128_rm128)(); // Opcode f3 0f 6f - void SSEOP_D(movdqu_rm128_r128)(); // Opcode f3 0f 7f - void SSEOP_D(movd_m128_rm32)(); // Opcode 66 0f 6e - void SSEOP_D(movdqa_m128_rm128)(); // Opcode 66 0f 6f - void SSEOP_D(movq_r128_r128m64)(); // Opcode f3 0f 7e - void SSEOP_D(movd_rm32_r128)(); // Opcode 66 0f 7e - void SSEOP_D(movdqa_rm128_r128)(); // Opcode 66 0f 7f - void SSEOP_D(pmovmskb_r16_r64)(); // Opcode 0f d7 - void SSEOP_D(pmovmskb_r32_r64)(); // Opcode 0f d7 - void SSEOP_D(pmovmskb_r32_r128)(); // Opcode 66 0f d7 - void SSEOP_D(xorps)(); // Opcode 0f 57 - void SSEOP_D(xorpd_r128_rm128)(); // Opcode 66 0f 57 - void SSEOP_D(addps)(); // Opcode 0f 58 - void SSEOP_D(sqrtps_r128_rm128)(); // Opcode 0f 51 - void SSEOP_D(rsqrtps_r128_rm128)(); // Opcode 0f 52 - void SSEOP_D(rcpps_r128_rm128)(); // Opcode 0f 53 - void SSEOP_D(andps_r128_rm128)(); // Opcode 0f 54 - void SSEOP_D(andpd_r128_rm128)(); // Opcode 66 0f 54 - void SSEOP_D(andnps_r128_rm128)(); // Opcode 0f 55 - void SSEOP_D(andnpd_r128_rm128)(); // Opcode 66 0f 55 - void SSEOP_D(orps_r128_rm128)(); // Opcode 0f 56 - void SSEOP_D(orpd_r128_rm128)(); // Opcode 66 0f 56 - void SSEOP_D(mulps)(); // Opcode 0f 59 ???? - void SSEOP_D(subps)(); // Opcode 0f 5c - void SSEOP_D(minps)(); // Opcode 0f 5d - void SSEOP_D(divps)(); // Opcode 0f 5e - void SSEOP_D(maxps)(); // Opcode 0f 5f - void SSEOP_D(maxss_r128_r128m32)(); // Opcode f3 0f 5f - void SSEOP_D(addss)(); // Opcode f3 0f 58 - void SSEOP_D(subss)(); // Opcode f3 0f 5c - void SSEOP_D(mulss)(); // Opcode f3 0f 5e - void SSEOP_D(divss)(); // Opcode 0f 59 - void SSEOP_D(rcpss_r128_r128m32)(); // Opcode f3 0f 53 - void SSEOP_D(sqrtss_r128_r128m32)(); // Opcode f3 0f 51 - void SSEOP_D(rsqrtss_r128_r128m32)(); // Opcode f3 0f 52 - void SSEOP_D(minss_r128_r128m32)(); // Opcode f3 0f 5d - void SSEOP_D(comiss_r128_r128m32)(); // Opcode 0f 2f - void SSEOP_D(comisd_r128_r128m64)(); // Opcode 66 0f 2f - void SSEOP_D(ucomiss_r128_r128m32)(); // Opcode 0f 2e - void SSEOP_D(ucomisd_r128_r128m64)(); // Opcode 66 0f 2e - void SSEOP_D(shufps)(); // Opcode 0f c6 - void SSEOP_D(shufpd_r128_rm128_i8)(); // Opcode 66 0f c6 - void SSEOP_D(unpcklps_r128_rm128)(); // Opcode 0f 14 - void SSEOP_D(unpcklpd_r128_rm128)(); // Opcode 66 0f 14 - void SSEOP_D(unpckhps_r128_rm128)(); // Opcode 0f 15 - void SSEOP_D(unpckhpd_r128_rm128)(); // Opcode 66 0f 15 - void SSEOP_D(predicate_compare_single)(UINT8 imm8, XMM_REG d, XMM_REG s); - void SSEOP_D(predicate_compare_double)(UINT8 imm8, XMM_REG d, XMM_REG s); - void SSEOP_D(predicate_compare_single_scalar)(UINT8 imm8, XMM_REG d, XMM_REG s); - void SSEOP_D(predicate_compare_double_scalar)(UINT8 imm8, XMM_REG d, XMM_REG s); - void SSEOP_D(cmpps_r128_rm128_i8)(); // Opcode 0f c2 - void SSEOP_D(cmppd_r128_rm128_i8)(); // Opcode 66 0f c2 - void SSEOP_D(cmpss_r128_r128m32_i8)(); // Opcode f3 0f c2 - void SSEOP_D(pinsrw_r64_r16m16_i8)(); // Opcode 0f c4, 16bit register - void SSEOP_D(pinsrw_r64_r32m16_i8)(); // Opcode 0f c4, 32bit register - void SSEOP_D(pinsrw_r128_r32m16_i8)(); // Opcode 66 0f c4 - void SSEOP_D(pextrw_r16_r64_i8)(); // Opcode 0f c5 - void SSEOP_D(pextrw_r32_r64_i8)(); // Opcode 0f c5 - void SSEOP_D(pextrw_reg_r128_i8)(); // Opcode 66 0f c5 - void SSEOP_D(pminub_r64_rm64)(); // Opcode 0f da - void SSEOP_D(pminub_r128_rm128)(); // Opcode 66 0f da - void SSEOP_D(pmaxub_r64_rm64)(); // Opcode 0f de - void SSEOP_D(pavgb_r64_rm64)(); // Opcode 0f e0 - void SSEOP_D(pavgw_r64_rm64)(); // Opcode 0f e3 - void SSEOP_D(pmulhuw_r64_rm64)(); // Opcode 0f e4 - void SSEOP_D(pminsw_r64_rm64)(); // Opcode 0f ea - void SSEOP_D(pmaxsw_r64_rm64)(); // Opcode 0f ee - void SSEOP_D(pmuludq_r64_rm64)(); // Opcode 0f f4 - void SSEOP_D(pmuludq_r128_rm128)(); // Opcode 66 0f f4 - void SSEOP_D(psadbw_r64_rm64)(); // Opcode 0f f6 - void SSEOP_D(psubq_r64_rm64)(); // Opcode 0f fb - void SSEOP_D(psubq_r128_rm128)(); // Opcode 66 0f fb - void SSEOP_D(pshufd_r128_rm128_i8)(); // Opcode 66 0f 70 - void SSEOP_D(pshuflw_r128_rm128_i8)(); // Opcode f2 0f 70 - void SSEOP_D(pshufhw_r128_rm128_i8)(); // Opcode f3 0f 70 - void SSEOP_D(packsswb_r128_rm128)(); // Opcode 66 0f 63 - void SSEOP_D(packssdw_r128_rm128)(); // Opcode 66 0f 6b - void SSEOP_D(pcmpgtb_r128_rm128)(); // Opcode 66 0f 64 - void SSEOP_D(pcmpgtw_r128_rm128)(); // Opcode 66 0f 65 - void SSEOP_D(pcmpgtd_r128_rm128)(); // Opcode 66 0f 66 - void SSEOP_D(packuswb_r128_rm128)(); // Opcode 66 0f 67 - void SSEOP_D(punpckhbw_r128_rm128)(); // Opcode 66 0f 68 - void SSEOP_D(punpckhwd_r128_rm128)(); // Opcode 66 0f 69 - void SSEOP_D(unpckhdq_r128_rm128)(); // Opcode 66 0f 6a - void SSEOP_D(punpckhqdq_r128_rm128)(); // Opcode 66 0f 6d - void SSEOP_D(pcmpeqb_r128_rm128)(); // Opcode 66 0f 74 - void SSEOP_D(pcmpeqw_r128_rm128)(); // Opcode 66 0f 75 - void SSEOP_D(pcmpeqd_r128_rm128)(); // Opcode 66 0f 76 - void SSEOP_D(paddq_r128_rm128)(); // Opcode 66 0f d4 - void SSEOP_D(pmullw_r128_rm128)(); // Opcode 66 0f d5 - void SSEOP_D(paddb_r128_rm128)(); // Opcode 66 0f fc - void SSEOP_D(paddw_r128_rm128)(); // Opcode 66 0f fd - void SSEOP_D(paddd_r128_rm128)(); // Opcode 66 0f fe - void SSEOP_D(psubusb_r128_rm128)(); // Opcode 66 0f d8 - void SSEOP_D(psubusw_r128_rm128)(); // Opcode 66 0f d9 - void SSEOP_D(pand_r128_rm128)(); // Opcode 66 0f db - void SSEOP_D(pandn_r128_rm128)(); // Opcode 66 0f df - void SSEOP_D(paddusb_r128_rm128)(); // Opcode 66 0f dc - void SSEOP_D(paddusw_r128_rm128)(); // Opcode 66 0f dd - void SSEOP_D(pmaxub_r128_rm128)(); // Opcode 66 0f de - void SSEOP_D(pmulhuw_r128_rm128)(); // Opcode 66 0f e4 - void SSEOP_D(pmulhw_r128_rm128)(); // Opcode 66 0f e5 - void SSEOP_D(psubsb_r128_rm128)(); // Opcode 66 0f e8 - void SSEOP_D(psubsw_r128_rm128)(); // Opcode 66 0f e9 - void SSEOP_D(pminsw_r128_rm128)(); // Opcode 66 0f ea - void SSEOP_D(pmaxsw_r128_rm128)(); // Opcode 66 0f ee - void SSEOP_D(paddsb_r128_rm128)(); // Opcode 66 0f ec - void SSEOP_D(paddsw_r128_rm128)(); // Opcode 66 0f ed - void SSEOP_D(por_r128_rm128)(); // Opcode 66 0f eb - void SSEOP_D(pxor_r128_rm128)(); // Opcode 66 0f ef - void SSEOP_D(pmaddwd_r128_rm128)(); // Opcode 66 0f f5 - void SSEOP_D(psubb_r128_rm128)(); // Opcode 66 0f f8 - void SSEOP_D(psubw_r128_rm128)(); // Opcode 66 0f f9 - void SSEOP_D(psubd_r128_rm128)(); // Opcode 66 0f fa - void SSEOP_D(psadbw_r128_rm128)(); // Opcode 66 0f f6 - void SSEOP_D(pavgb_r128_rm128)(); // Opcode 66 0f e0 - void SSEOP_D(pavgw_r128_rm128)(); // Opcode 66 0f e3 - void SSEOP_D(psrlw_r128_rm128)(); // Opcode 66 0f d1 - void SSEOP_D(psrld_r128_rm128)(); // Opcode 66 0f d2 - void SSEOP_D(psrlq_r128_rm128)(); // Opcode 66 0f d3 - void SSEOP_D(psllw_r128_rm128)(); // Opcode 66 0f f1 - void SSEOP_D(pslld_r128_rm128)(); // Opcode 66 0f f2 - void SSEOP_D(psllq_r128_rm128)(); // Opcode 66 0f f3 - void SSEOP_D(psraw_r128_rm128)(); // Opcode 66 0f e1 - void SSEOP_D(psrad_r128_rm128)(); // Opcode 66 0f e2 - void SSEOP_D(movntdq_m128_r128)(); // Opcode 66 0f e7 - void SSEOP_D(cvttpd2dq_r128_rm128)(); // Opcode 66 0f e6 - void SSEOP_D(movq_r128m64_r128)(); // Opcode 66 0f d6 - void SSEOP_D(addsubpd_r128_rm128)(); // Opcode 66 0f d0 - void SSEOP_D(haddpd_r128_rm128)(); // Opcode 66 0f 7c - void SSEOP_D(hsubpd_r128_rm128)(); // Opcode 66 0f 7d - void SSEOP_D(sqrtpd_r128_rm128)(); // Opcode 66 0f 51 - void SSEOP_D(cvtpi2pd_r128_rm64)(); // Opcode 66 0f 2a - void SSEOP_D(cvttpd2pi_r64_rm128)(); // Opcode 66 0f 2c - void SSEOP_D(cvtpd2pi_r64_rm128)(); // Opcode 66 0f 2d - void SSEOP_D(cvtpd2ps_r128_rm128)(); // Opcode 66 0f 5a - void SSEOP_D(cvtps2dq_r128_rm128)(); // Opcode 66 0f 5b - void SSEOP_D(addpd_r128_rm128)(); // Opcode 66 0f 58 - void SSEOP_D(mulpd_r128_rm128)(); // Opcode 66 0f 59 - void SSEOP_D(subpd_r128_rm128)(); // Opcode 66 0f 5c - void SSEOP_D(minpd_r128_rm128)(); // Opcode 66 0f 5d - void SSEOP_D(divpd_r128_rm128)(); // Opcode 66 0f 5e - void SSEOP_D(maxpd_r128_rm128)(); // Opcode 66 0f 5f - void SSEOP_D(movntpd_m128_r128)(); // Opcode 66 0f 2b - void SSEOP_D(movapd_r128_rm128)(); // Opcode 66 0f 28 - void SSEOP_D(movapd_rm128_r128)(); // Opcode 66 0f 29 - void SSEOP_D(movsd_r128_r128m64)(); // Opcode f2 0f 10 - void SSEOP_D(movsd_r128m64_r128)(); // Opcode f2 0f 11 - void SSEOP_D(movddup_r128_r128m64)(); // Opcode f2 0f 12 - void SSEOP_D(cvtsi2sd_r128_rm32)(); // Opcode f2 0f 2a - void SSEOP_D(cvttsd2si_r32_r128m64)(); // Opcode f2 0f 2c - void SSEOP_D(cvtsd2si_r32_r128m64)(); // Opcode f2 0f 2d - void SSEOP_D(sqrtsd_r128_r128m64)(); // Opcode f2 0f 51 - void SSEOP_D(addsd_r128_r128m64)(); // Opcode f2 0f 58 - void SSEOP_D(mulsd_r128_r128m64)(); // Opcode f2 0f 59 - void SSEOP_D(cvtsd2ss_r128_r128m64)(); // Opcode f2 0f 5a - void SSEOP_D(subsd_r128_r128m64)(); // Opcode f2 0f 5c - void SSEOP_D(minsd_r128_r128m64)(); // Opcode f2 0f 5d - void SSEOP_D(divsd_r128_r128m64)(); // Opcode f2 0f 5e - void SSEOP_D(maxsd_r128_r128m64)(); // Opcode f2 0f 5f - void SSEOP_D(haddps_r128_rm128)(); // Opcode f2 0f 7c - void SSEOP_D(hsubps_r128_rm128)(); // Opcode f2 0f 7d - void SSEOP_D(cmpsd_r128_r128m64_i8)(); // Opcode f2 0f c2 - void SSEOP_D(addsubps_r128_rm128)(); // Opcode f2 0f d0 - void SSEOP_D(movdq2q_r64_r128)(); // Opcode f2 0f d6 - void SSEOP_D(cvtpd2dq_r128_rm128)(); // Opcode f2 0f e6 - void SSEOP_D(lddqu_r128_m128)(); // Opcode f2 0f f0 - // x87 FPU - void x87_write_stack( int i, floatx80 value, int update_tag); - void x87_reset(); - void x87_fadd_m32real(UINT8 modrm); - void x87_fadd_m64real(UINT8 modrm); - void x87_fadd_st_sti(UINT8 modrm); - void x87_fadd_sti_st(UINT8 modrm); - void x87_faddp(UINT8 modrm); - void x87_fiadd_m32int(UINT8 modrm); - void x87_fiadd_m16int(UINT8 modrm); - void x87_fsub_m32real(UINT8 modrm); - void x87_fsub_m64real(UINT8 modrm); - void x87_fsub_st_sti(UINT8 modrm); - void x87_fsub_sti_st( UINT8 modrm); - void x87_fsubp(UINT8 modrm); - void x87_fisub_m32int(UINT8 modrm); - void x87_fisub_m16int(UINT8 modrm); - void x87_fsubr_m32real(UINT8 modrm); - void x87_fsubr_m64real(UINT8 modrm); - void x87_fsubr_st_sti(UINT8 modrm); - void x87_fsubr_sti_st(UINT8 modrm); - void x87_fsubrp(UINT8 modrm); - void x87_fisubr_m32int(UINT8 modrm); - void x87_fisubr_m16int(UINT8 modrm); - void x87_fdiv_m32real(UINT8 modrm); - void x87_fdiv_m64real(UINT8 modrm); - void x87_fdiv_st_sti(UINT8 modrm); - void x87_fdiv_sti_st(UINT8 modrm); - void x87_fdivp(UINT8 modrm); - void x87_fidiv_m32int(UINT8 modrm); - void x87_fidiv_m16int(UINT8 modrm); - void x87_fdivr_m32real(UINT8 modrm); - void x87_fdivr_m64real(UINT8 modrm); - void x87_fdivr_st_sti(UINT8 modrm); - void x87_fdivr_sti_st(UINT8 modrm); - void x87_fdivrp(UINT8 modrm); - void x87_fidivr_m32int( UINT8 modrm); - void x87_fidivr_m16int( UINT8 modrm); - void x87_fmul_m32real( UINT8 modrm); - void x87_fmul_m64real( UINT8 modrm); - void x87_fmul_st_sti( UINT8 modrm); - void x87_fmul_sti_st( UINT8 modrm); - void x87_fmulp( UINT8 modrm); - void x87_fimul_m32int( UINT8 modrm); - void x87_fimul_m16int( UINT8 modrm); - void x87_fcmovb_sti( UINT8 modrm); - void x87_fcmove_sti( UINT8 modrm); - void x87_fcmovbe_sti( UINT8 modrm); - void x87_fcmovu_sti( UINT8 modrm); - void x87_fcmovnb_sti( UINT8 modrm); - void x87_fcmovne_sti( UINT8 modrm); - void x87_fcmovnbe_sti( UINT8 modrm); - void x87_fcmovnu_sti( UINT8 modrm); - void x87_fprem( UINT8 modrm); - void x87_fprem1( UINT8 modrm); - void x87_fsqrt( UINT8 modrm); - void x87_f2xm1( UINT8 modrm); - void x87_fyl2x( UINT8 modrm); - void x87_fyl2xp1( UINT8 modrm); - void x87_fptan( UINT8 modrm); - void x87_fpatan( UINT8 modrm); - void x87_fsin( UINT8 modrm); - void x87_fcos( UINT8 modrm); - void x87_fsincos( UINT8 modrm); - void x87_fld_m32real( UINT8 modrm); - void x87_fld_m64real( UINT8 modrm); - void x87_fld_m80real( UINT8 modrm); - void x87_fld_sti( UINT8 modrm); - void x87_fild_m16int( UINT8 modrm); - void x87_fild_m32int( UINT8 modrm); - void x87_fild_m64int( UINT8 modrm); - void x87_fbld( UINT8 modrm); - void x87_fst_m32real( UINT8 modrm); - void x87_fst_m64real( UINT8 modrm); - void x87_fst_sti( UINT8 modrm); - void x87_fstp_m32real( UINT8 modrm); - void x87_fstp_m64real( UINT8 modrm); - void x87_fstp_m80real( UINT8 modrm); - void x87_fstp_sti( UINT8 modrm); - void x87_fist_m16int( UINT8 modrm); - void x87_fist_m32int( UINT8 modrm); - void x87_fistp_m16int( UINT8 modrm); - void x87_fistp_m32int( UINT8 modrm); - void x87_fistp_m64int( UINT8 modrm); - void x87_fbstp( UINT8 modrm); - void x87_fld1( UINT8 modrm); - void x87_fldl2t( UINT8 modrm); - void x87_fldl2e( UINT8 modrm); - void x87_fldpi( UINT8 modrm); - void x87_fldlg2( UINT8 modrm); - void x87_fldln2( UINT8 modrm); - void x87_fldz( UINT8 modrm); - void x87_fnop( UINT8 modrm); - void x87_fchs( UINT8 modrm); - void x87_fabs( UINT8 modrm); - void x87_fscale( UINT8 modrm); - void x87_frndint( UINT8 modrm); - void x87_fxtract( UINT8 modrm); - void x87_ftst( UINT8 modrm); - void x87_fxam( UINT8 modrm); - void x87_ficom_m16int( UINT8 modrm); - void x87_ficom_m32int( UINT8 modrm); - void x87_ficomp_m16int( UINT8 modrm); - void x87_ficomp_m32int( UINT8 modrm); - void x87_fcom_m32real( UINT8 modrm); - void x87_fcom_m64real( UINT8 modrm); - void x87_fcom_sti( UINT8 modrm); - void x87_fcomp_m32real( UINT8 modrm); - void x87_fcomp_m64real( UINT8 modrm); - void x87_fcomp_sti( UINT8 modrm); - void x87_fcomi_sti( UINT8 modrm); - void x87_fcomip_sti( UINT8 modrm); - void x87_fucomi_sti( UINT8 modrm); - void x87_fucomip_sti( UINT8 modrm); - void x87_fcompp( UINT8 modrm); - void x87_fucom_sti( UINT8 modrm); - void x87_fucomp_sti( UINT8 modrm); - void x87_fucompp( UINT8 modrm); - void x87_fdecstp( UINT8 modrm); - void x87_fincstp( UINT8 modrm); - void x87_fclex( UINT8 modrm); - void x87_feni( UINT8 modrm); - void x87_fdisi( UINT8 modrm); - void x87_ffree( UINT8 modrm); - void x87_finit( UINT8 modrm); - void x87_fldcw( UINT8 modrm); - void x87_fstcw( UINT8 modrm); - void x87_fldenv( UINT8 modrm); - void x87_fstenv( UINT8 modrm); - void x87_fsave( UINT8 modrm); - void x87_frstor( UINT8 modrm); - void x87_fxch( UINT8 modrm); - void x87_fxch_sti( UINT8 modrm); - void x87_fstsw_ax( UINT8 modrm); - void x87_fstsw_m2byte( UINT8 modrm); - void x87_invalid( UINT8 modrm); - void I386OP_D(x87_group_d8)(); - void I386OP_D(x87_group_d9)(); - void I386OP_D(x87_group_da)(); - void I386OP_D(x87_group_db)(); - void I386OP_D(x87_group_dc)(); - void I386OP_D(x87_group_dd)(); - void I386OP_D(x87_group_de)(); - void I386OP_D(x87_group_df)(); - void build_x87_opcode_table_d8(); - void build_x87_opcode_table_d9(); - void build_x87_opcode_table_da(); - void build_x87_opcode_table_db(); - void build_x87_opcode_table_dc(); - void build_x87_opcode_table_dd(); - void build_x87_opcode_table_de(); - void build_x87_opcode_table_df(); - void build_x87_opcode_table(); - - floatx80 x87_add( floatx80 a, floatx80 b); - floatx80 x87_sub( floatx80 a, floatx80 b); - floatx80 x87_mul( floatx80 a, floatx80 b); - floatx80 x87_div( floatx80 a, floatx80 b); - - void I386OP_D(decode_two_byte)(); - void I386OP_D(decode_three_byte38)(); - void I386OP_D(decode_three_byte3a)(); - void I386OP_D(decode_three_byte66)(); - void I386OP_D(decode_three_bytef2)(); - void I386OP_D(decode_three_bytef3)(); - void I386OP_D(decode_four_byte3866)(); - void I386OP_D(decode_four_byte3a66)(); - void I386OP_D(decode_four_byte3af2)(); - void I386OP_D(decode_four_byte38f2)(); - void I386OP_D(decode_four_byte38f3)(); -protected: - - // Inline Utilities. - INLINE INT8 SaturatedSignedWordToSignedByte(INT16 word); - INLINE UINT8 SaturatedSignedWordToUnsignedByte(INT16 word); - INLINE INT16 SaturatedSignedDwordToSignedWord(INT32 dword); - INLINE UINT16 SaturatedSignedDwordToUnsignedWord(INT32 dword); - // - INLINE vtlb_entry get_permissions(UINT32 pte, int wp); - INLINE int translate_address(int pl, int type, UINT32 *address, UINT32 *error); - INLINE UINT32 i386_translate(int segment, UINT32 ip, int rwn, UINT32 size); - - INLINE UINT8 FETCH(); - INLINE UINT16 FETCH16(); - INLINE UINT32 FETCH32(); - - INLINE UINT8 READ8(UINT32 ea); - INLINE UINT8 READ8PL0(UINT32 ea); - INLINE UINT16 READ16(UINT32 ea); - INLINE UINT16 READ16PL0(UINT32 ea); - INLINE UINT32 READ32(UINT32 ea); - INLINE UINT32 READ32PL0(UINT32 ea); - INLINE UINT64 READ64(UINT32 ea); - - INLINE void WRITE8(UINT32 ea, UINT8 value); - INLINE void WRITE16(UINT32 ea, UINT16 value); - INLINE void WRITE32(UINT32 ea, UINT32 value); - INLINE void WRITE64(UINT32 ea, UINT64 value); - INLINE void WRITE_TEST(UINT32 ea); - - INLINE void WRITEPORT8(offs_t port, UINT8 value); - INLINE void WRITEPORT16(offs_t port, UINT16 value); - INLINE void WRITEPORT32(offs_t port, UINT32 value); - INLINE UINT8 READPORT8( offs_t port); - INLINE UINT16 READPORT16( offs_t port); - INLINE UINT32 READPORT32( offs_t port); - - INLINE void PUSH8(UINT8 value); - INLINE UINT8 POP8(); - INLINE void PUSH16(UINT16 value); - INLINE UINT16 POP16(); - INLINE void PUSH32(UINT32 value); - INLINE void PUSH32SEG(UINT32 value); - INLINE UINT32 POP32(); - - INLINE UINT8 OR8(UINT8 dst, UINT8 src); - INLINE UINT8 AND8(UINT8 dst, UINT8 src); - INLINE UINT8 XOR8(UINT8 dst, UINT8 src); - INLINE UINT8 SBB8(UINT8 dst, UINT8 src, UINT8 b); - INLINE UINT8 ADC8(UINT8 dst, UINT8 src, UINT8 c); - INLINE UINT8 INC8(UINT8 dst); - INLINE UINT8 DEC8(UINT8 dst); - - INLINE UINT16 OR16(UINT16 dst, UINT16 src); - INLINE UINT16 AND16(UINT16 dst, UINT16 src); - INLINE UINT16 XOR16(UINT16 dst, UINT16 src); - INLINE UINT16 SBB16(UINT16 dst, UINT16 src, UINT16 b); - INLINE UINT16 ADC16(UINT16 dst, UINT16 src, UINT8 c); - INLINE UINT16 INC16(UINT16 dst); - INLINE UINT16 DEC16(UINT16 dst); - - INLINE UINT32 OR32(UINT32 dst, UINT32 src); - INLINE UINT32 AND32(UINT32 dst, UINT32 src); - INLINE UINT32 XOR32(UINT32 dst, UINT32 src); - INLINE UINT32 SBB32(UINT32 dst, UINT32 src, UINT32 b); - INLINE UINT32 ADC32(UINT32 dst, UINT32 src, UINT32 c); - INLINE UINT32 INC32(UINT32 dst); - INLINE UINT32 DEC32(UINT32 dst); - - INLINE UINT64 MSR_READ(UINT32 offset,UINT8 *valid_msr); - INLINE void MSR_WRITE(UINT32 offset, UINT64 data, UINT8 *valid_msr); - - INLINE void CHANGE_PC(UINT32 pc); - INLINE void NEAR_BRANCH(INT32 offs); - INLINE void BUMP_SI(int adjustment); - INLINE void BUMP_DI(int adjustment); - INLINE void CYCLES(int x); - INLINE void CYCLES_RM(int modrm, int r, int m); - - INLINE void MMXPROLOG(); - INLINE void READMMX(UINT32 ea,MMX_REG &r); - INLINE void WRITEMMX(UINT32 ea,MMX_REG &r); - INLINE void READXMM(UINT32 ea,XMM_REG &r); - INLINE void WRITEXMM(UINT32 ea,XMM_REG &r); - INLINE void READXMM_LO64(UINT32 ea,XMM_REG &r); - INLINE void WRITEXMM_LO64(UINT32 ea,XMM_REG &r); - INLINE void READXMM_HI64(UINT32 ea,XMM_REG &r); - INLINE void WRITEXMM_HI64(UINT32 ea,XMM_REG &r); - - INLINE flag floatx80_is_quiet_nan(floatx80 a); - INLINE int floatx80_is_zero(floatx80 fx); - INLINE int floatx80_is_inf(floatx80 fx); - INLINE int floatx80_is_denormal(floatx80 fx); - INLINE floatx80 floatx80_abs(floatx80 fx); - - INLINE UINT64 __SWAP64(UINT64 in); - INLINE double fx80_to_double(floatx80 fx); - INLINE floatx80 double_to_fx80(double in); - INLINE floatx80 READ80( UINT32 ea); - INLINE void WRITE80( UINT32 ea, floatx80 t); - INLINE void x87_set_stack_top(int top); - INLINE void x87_set_tag(int reg, int tag); - INLINE void x87_set_stack_underflow(); - INLINE void x87_set_stack_overflow(); - INLINE void x87_write_cw( UINT16 cw); - - UINT32 I386OP_D(shift_rotate32)(UINT8 modrm, UINT32 value, UINT8 shift); - - UINT64 pentium_msr_read(UINT32 offset,UINT8 *valid_msr);; - void pentium_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr); - UINT64 p6_msr_read(UINT32 offset,UINT8 *valid_msr);; - void p6_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr); - UINT64 piv_msr_read(UINT32 offset,UINT8 *valid_msr);; - void piv_msr_write(UINT32 offset, UINT64 data, UINT8 *valid_msr); - - int x87_inc_stack(); - int x87_dec_stack(); - int x87_check_exceptions(); -public: - -}; -extern const X86_OPCODE x86_opcode_table[]; -extern const X86_CYCLE_TABLE x86_cycle_table[]; - -/***********************************************************************************/ - -#define CYCLES_NUM(x) (cpustate->cycles -= (x)) - -INLINE void I386_OPS_BASE::CYCLES(int x) -{ - if (PROTECTED_MODE) - { - cpustate->cycles -= cpustate->cycle_table_pm[x]; - } - else - { - cpustate->cycles -= cpustate->cycle_table_rm[x]; - } -} - -INLINE void I386_OPS_BASE::CYCLES_RM(int modrm, int r, int m) -{ - if (modrm >= 0xc0) - { - if (PROTECTED_MODE) - { - cpustate->cycles -= cpustate->cycle_table_pm[r]; - } - else - { - cpustate->cycles -= cpustate->cycle_table_rm[r]; - } - } - else - { - if (PROTECTED_MODE) - { - cpustate->cycles -= cpustate->cycle_table_pm[m]; - } - else - { - cpustate->cycles -= cpustate->cycle_table_rm[m]; - } - } -} - - -INLINE UINT32 I386_OPS_BASE::i386_translate(int segment, UINT32 ip, int rwn, UINT32 size) -{ - // TODO: segment limit access size, execution permission, handle exception thrown from exception handler - if(PROTECTED_MODE && !V8086_MODE && (rwn != -1)) - { - if(!(cpustate->sreg[segment].valid)) - FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0); - if(i386_limit_check(segment, ip, size)) - FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0); - if((rwn == 0) && ((cpustate->sreg[segment].flags & 8) && !(cpustate->sreg[segment].flags & 2))) - FAULT_THROW(FAULT_GP, 0); - if((rwn == 1) && ((cpustate->sreg[segment].flags & 8) || !(cpustate->sreg[segment].flags & 2))) - FAULT_THROW(FAULT_GP, 0); - } - return cpustate->sreg[segment].base + ip; -} - -#define VTLB_FLAG_DIRTY 0x100 - -INLINE vtlb_entry I386_OPS_BASE::get_permissions(UINT32 pte, int wp) -{ - vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0); - if(!wp) - ret |= VTLB_WRITE_ALLOWED; - if(pte & 2) - ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0); - return ret; -} - -//#define TEST_TLB - -INLINE int I386_OPS_BASE::translate_address(int pl, int type, UINT32 *address, UINT32 *error) -{ - if(!(cpustate->cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this - return TRUE; - - const vtlb_entry *table = vtlb_table(cpustate->vtlb); - UINT32 index = *address >> 12; - vtlb_entry entry = table[index]; - if(type == TRANSLATE_FETCH) - type = TRANSLATE_READ; - if(pl == 3) - type |= TRANSLATE_USER_MASK; -#ifdef TEST_TLB - UINT32 test_addr = *address; -#endif - - if(!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY))) - { - if(!i386_translate_address( type, address, &entry)) - { - *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0); - if(entry) - *error |= 1; - return FALSE; - } - vtlb_dynload(cpustate->vtlb, index, *address, entry); - return TRUE; - } - if(!(entry & (1 << type))) - { - *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0) | 1; - return FALSE; - } - *address = (entry & 0xfffff000) | (*address & 0xfff); -#ifdef TEST_TLB - int test_ret = i386_translate_address( type | TRANSLATE_DEBUG_MASK, &test_addr, NULL); - if(!test_ret || (test_addr != *address)) - logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, cpustate->pc); -#endif - return TRUE; -} - -INLINE void I386_OPS_BASE::CHANGE_PC(UINT32 pc) -{ - cpustate->pc = i386_translate(CS, pc, -1, 1 ); -} - -INLINE void I386_OPS_BASE::NEAR_BRANCH(INT32 offs) -{ - /* TODO: limit */ - cpustate->eip += offs; - cpustate->pc += offs; -} - -INLINE UINT8 I386_OPS_BASE::FETCH() -{ - UINT8 value; - UINT32 address = cpustate->pc, error; - - if(!translate_address(cpustate->CPL,TRANSLATE_FETCH,&address,&error)) - PF_THROW(error); - - value = cpustate->program->read_data8(address & cpustate->a20_mask); -#ifdef DEBUG_MISSING_OPCODE - cpustate->opcode_bytes[cpustate->opcode_bytes_length] = value; - cpustate->opcode_bytes_length = (cpustate->opcode_bytes_length + 1) & 15; -#endif - cpustate->eip++; - cpustate->pc++; - return value; -} - -INLINE UINT16 I386_OPS_BASE::FETCH16() -{ - UINT16 value; - UINT32 address = cpustate->pc, error; - - if( !WORD_ALIGNED(address) ) { /* Unaligned read */ - value = (FETCH() << 0); - value |= (FETCH() << 8); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_FETCH,&address,&error)) - PF_THROW(error); - address &= cpustate->a20_mask; - value = cpustate->program->read_data16(address); - cpustate->eip += 2; - cpustate->pc += 2; - } - return value; -} -INLINE UINT32 I386_OPS_BASE::FETCH32() -{ - UINT32 value; - UINT32 address = cpustate->pc, error; - - if( !DWORD_ALIGNED(cpustate->pc) ) { /* Unaligned read */ - value = (FETCH() << 0); - value |= (FETCH() << 8); - value |= (FETCH() << 16); - value |= (FETCH() << 24); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_FETCH,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - value = cpustate->program->read_data32(address); - cpustate->eip += 4; - cpustate->pc += 4; - } - return value; -} - -INLINE UINT8 I386_OPS_BASE::READ8(UINT32 ea) -{ - UINT32 address = ea, error; - - if(!translate_address(cpustate->CPL,TRANSLATE_READ,&address, &error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - return cpustate->program->read_data8(address); -} - -INLINE UINT16 I386_OPS_BASE::READ16(UINT32 ea) -{ - UINT16 value; - UINT32 address = ea, error; - - if( !WORD_ALIGNED(ea) ) { /* Unaligned read */ - value = (READ8(address+0) << 0); - value |= (READ8(address+1) << 8); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_READ,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - value = cpustate->program->read_data16( address ); - } - return value; -} -INLINE UINT32 I386_OPS_BASE::READ32(UINT32 ea) -{ - UINT32 value; - UINT32 address = ea, error; - - if( !DWORD_ALIGNED(ea) ) { /* Unaligned read */ - value = (READ8(address+0) << 0); - value |= (READ8(address+1) << 8); - value |= (READ8(address+2) << 16), - value |= (READ8(address+3) << 24); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_READ,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - value = cpustate->program->read_data32( address ); - } - return value; -} - -INLINE UINT64 I386_OPS_BASE::READ64(UINT32 ea) -{ - UINT64 value; - UINT32 address = ea, error; - - if( !QWORD_ALIGNED(ea) ) { /* Unaligned read */ - value = (((UINT64) READ8( address+0 )) << 0); - value |= (((UINT64) READ8( address+1 )) << 8); - value |= (((UINT64) READ8( address+2 )) << 16); - value |= (((UINT64) READ8( address+3 )) << 24); - value |= (((UINT64) READ8( address+4 )) << 32); - value |= (((UINT64) READ8( address+5 )) << 40); - value |= (((UINT64) READ8( address+6 )) << 48); - value |= (((UINT64) READ8( address+7 )) << 56); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_READ,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - value = (((UINT64) cpustate->program->read_data32( address+0 )) << 0); - value |= (((UINT64) cpustate->program->read_data32( address+4 )) << 32); - } - return value; -} - -INLINE UINT8 I386_OPS_BASE::READ8PL0(UINT32 ea) -{ - UINT32 address = ea, error; - - if(!translate_address(0,TRANSLATE_READ,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - return cpustate->program->read_data8(address); -} - -INLINE UINT16 I386_OPS_BASE::READ16PL0(UINT32 ea) -{ - UINT16 value; - UINT32 address = ea, error; - - if( !WORD_ALIGNED(ea) ) { /* Unaligned read */ - value = (READ8PL0( address+0 ) << 0); - value |= (READ8PL0( address+1 ) << 8); - } else { - if(!translate_address(0,TRANSLATE_READ,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - value = cpustate->program->read_data16( address ); - } - return value; -} - -INLINE UINT32 I386_OPS_BASE::READ32PL0(UINT32 ea) -{ - UINT32 value; - UINT32 address = ea, error; - - if( !DWORD_ALIGNED(ea) ) { /* Unaligned read */ - value = (READ8PL0( address+0 ) << 0); - value |= (READ8PL0( address+1 ) << 8); - value |= (READ8PL0( address+2 ) << 16); - value |= (READ8PL0( address+3 ) << 24); - } else { - if(!translate_address(0,TRANSLATE_READ,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - value = cpustate->program->read_data32( address ); - } - return value; -} - -INLINE void I386_OPS_BASE::WRITE_TEST(UINT32 ea) -{ - UINT32 address = ea, error; - if(!translate_address(cpustate->CPL,TRANSLATE_WRITE,&address,&error)) - PF_THROW(error); -} - -INLINE void I386_OPS_BASE::WRITE8(UINT32 ea, UINT8 value) -{ - UINT32 address = ea, error; - - if(!translate_address(cpustate->CPL,TRANSLATE_WRITE,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - cpustate->program->write_data8(address, value); -} - -INLINE void I386_OPS_BASE::WRITE16(UINT32 ea, UINT16 value) -{ - UINT32 address = ea, error; - - if( !WORD_ALIGNED(ea) ) { /* Unaligned write */ - WRITE8( address+0, value & 0xff ); - WRITE8( address+1, (value >> 8) & 0xff ); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_WRITE,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - cpustate->program->write_data16(address, value); - } -} - -INLINE void I386_OPS_BASE::WRITE32(UINT32 ea, UINT32 value) -{ - UINT32 address = ea, error; - - if( !DWORD_ALIGNED(ea) ) { /* Unaligned write */ - WRITE8( address+0, value & 0xff ); - WRITE8( address+1, (value >> 8) & 0xff ); - WRITE8( address+2, (value >> 16) & 0xff ); - WRITE8( address+3, (value >> 24) & 0xff ); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_WRITE,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - cpustate->program->write_data32(address, value); - } -} - -INLINE void I386_OPS_BASE::WRITE64(UINT32 ea, UINT64 value) -{ - UINT32 address = ea, error; - - if( !QWORD_ALIGNED(ea) ) { /* Unaligned write */ - WRITE8( address+0, value & 0xff ); - WRITE8( address+1, (value >> 8) & 0xff ); - WRITE8( address+2, (value >> 16) & 0xff ); - WRITE8( address+3, (value >> 24) & 0xff ); - WRITE8( address+4, (value >> 32) & 0xff ); - WRITE8( address+5, (value >> 40) & 0xff ); - WRITE8( address+6, (value >> 48) & 0xff ); - WRITE8( address+7, (value >> 56) & 0xff ); - } else { - if(!translate_address(cpustate->CPL,TRANSLATE_WRITE,&address,&error)) - PF_THROW(error); - - address &= cpustate->a20_mask; - cpustate->program->write_data32(address+0, value & 0xffffffff); - cpustate->program->write_data32(address+4, (value >> 32) & 0xffffffff); - } -} - -/***********************************************************************************/ - -INLINE UINT8 I386_OPS_BASE::OR8(UINT8 dst, UINT8 src) -{ - UINT8 res = dst | src; - cpustate->CF = cpustate->OF = 0; - SetSZPF8(res); - return res; -} - -INLINE UINT16 I386_OPS_BASE::OR16(UINT16 dst, UINT16 src) -{ - UINT16 res = dst | src; - cpustate->CF = cpustate->OF = 0; - SetSZPF16(res); - return res; -} - -INLINE UINT32 I386_OPS_BASE::OR32(UINT32 dst, UINT32 src) -{ - UINT32 res = dst | src; - cpustate->CF = cpustate->OF = 0; - SetSZPF32(res); - return res; -} - -INLINE UINT8 I386_OPS_BASE::AND8(UINT8 dst, UINT8 src) -{ - UINT8 res = dst & src; - cpustate->CF = cpustate->OF = 0; - SetSZPF8(res); - return res; -} -INLINE UINT16 I386_OPS_BASE::AND16(UINT16 dst, UINT16 src) -{ - UINT16 res = dst & src; - cpustate->CF = cpustate->OF = 0; - SetSZPF16(res); - return res; -} -INLINE UINT32 I386_OPS_BASE::AND32(UINT32 dst, UINT32 src) -{ - UINT32 res = dst & src; - cpustate->CF = cpustate->OF = 0; - SetSZPF32(res); - return res; -} - -INLINE UINT8 I386_OPS_BASE::XOR8(UINT8 dst, UINT8 src) -{ - UINT8 res = dst ^ src; - cpustate->CF = cpustate->OF = 0; - SetSZPF8(res); - return res; -} -INLINE UINT16 I386_OPS_BASE::XOR16(UINT16 dst, UINT16 src) -{ - UINT16 res = dst ^ src; - cpustate->CF = cpustate->OF = 0; - SetSZPF16(res); - return res; -} -INLINE UINT32 I386_OPS_BASE::XOR32(UINT32 dst, UINT32 src) -{ - UINT32 res = dst ^ src; - cpustate->CF = cpustate->OF = 0; - SetSZPF32(res); - return res; -} - -#define SUB8(dst, src) SBB8(dst, src, 0) -INLINE UINT8 I386_OPS_BASE::SBB8(UINT8 dst, UINT8 src, UINT8 b) -{ - UINT16 res = (UINT16)dst - (UINT16)src - (UINT8)b; - SetCF8(res); - SetOF_Sub8(res,src,dst); - SetAF(res,src,dst); - SetSZPF8(res); - return (UINT8)res; -} - -#define SUB16(dst, src) SBB16(dst, src, 0) -INLINE UINT16 I386_OPS_BASE::SBB16(UINT16 dst, UINT16 src, UINT16 b) -{ - UINT32 res = (UINT32)dst - (UINT32)src - (UINT32)b; - SetCF16(res); - SetOF_Sub16(res,src,dst); - SetAF(res,src,dst); - SetSZPF16(res); - return (UINT16)res; -} - -#define SUB32(dst, src) SBB32(dst, src, 0) -INLINE UINT32 I386_OPS_BASE::SBB32(UINT32 dst, UINT32 src, UINT32 b) -{ - UINT64 res = (UINT64)dst - (UINT64)src - (UINT64) b; - SetCF32(res); - SetOF_Sub32(res,src,dst); - SetAF(res,src,dst); - SetSZPF32(res); - return (UINT32)res; -} - -#define ADD8(dst, src) ADC8(dst, src, 0) -INLINE UINT8 I386_OPS_BASE::ADC8(UINT8 dst, UINT8 src, UINT8 c) -{ - UINT16 res = (UINT16)dst + (UINT16)src + (UINT16)c; - SetCF8(res); - SetOF_Add8(res,src,dst); - SetAF(res,src,dst); - SetSZPF8(res); - return (UINT8)res; -} - -#define ADD16(dst, src) ADC16(dst, src, 0) -INLINE UINT16 I386_OPS_BASE::ADC16(UINT16 dst, UINT16 src, UINT8 c) -{ - UINT32 res = (UINT32)dst + (UINT32)src + (UINT32)c; - SetCF16(res); - SetOF_Add16(res,src,dst); - SetAF(res,src,dst); - SetSZPF16(res); - return (UINT16)res; -} - -#define ADD32(dst, src) ADC32(dst, src, 0) -INLINE UINT32 I386_OPS_BASE::ADC32(UINT32 dst, UINT32 src, UINT32 c) -{ - UINT64 res = (UINT64)dst + (UINT64)src + (UINT64) c; - SetCF32(res); - SetOF_Add32(res,src,dst); - SetAF(res,src,dst); - SetSZPF32(res); - return (UINT32)res; -} - -INLINE UINT8 I386_OPS_BASE::INC8(UINT8 dst) -{ - UINT16 res = (UINT16)dst + 1; - SetOF_Add8(res,1,dst); - SetAF(res,1,dst); - SetSZPF8(res); - return (UINT8)res; -} -INLINE UINT16 I386_OPS_BASE::INC16(UINT16 dst) -{ - UINT32 res = (UINT32)dst + 1; - SetOF_Add16(res,1,dst); - SetAF(res,1,dst); - SetSZPF16(res); - return (UINT16)res; -} -INLINE UINT32 I386_OPS_BASE::INC32(UINT32 dst) -{ - UINT64 res = (UINT64)dst + 1; - SetOF_Add32(res,1,dst); - SetAF(res,1,dst); - SetSZPF32(res); - return (UINT32)res; -} - -INLINE UINT8 I386_OPS_BASE::DEC8(UINT8 dst) -{ - UINT16 res = (UINT16)dst - 1; - SetOF_Sub8(res,1,dst); - SetAF(res,1,dst); - SetSZPF8(res); - return (UINT8)res; -} -INLINE UINT16 I386_OPS_BASE::DEC16(UINT16 dst) -{ - UINT32 res = (UINT32)dst - 1; - SetOF_Sub16(res,1,dst); - SetAF(res,1,dst); - SetSZPF16(res); - return (UINT16)res; -} -INLINE UINT32 I386_OPS_BASE::DEC32(UINT32 dst) -{ - UINT64 res = (UINT64)dst - 1; - SetOF_Sub32(res,1,dst); - SetAF(res,1,dst); - SetSZPF32(res); - return (UINT32)res; -} - - - -INLINE void I386_OPS_BASE::PUSH16(UINT16 value) -{ - UINT32 ea, new_esp; - if( STACK_32BIT ) { - new_esp = REG32(ESP) - 2; - ea = i386_translate( SS, new_esp, 1, 2); - WRITE16( ea, value ); - REG32(ESP) = new_esp; - } else { - new_esp = (REG16(SP) - 2) & 0xffff; - ea = i386_translate( SS, new_esp, 1, 2); - WRITE16( ea, value ); - REG16(SP) = new_esp; - } -} -INLINE void I386_OPS_BASE::PUSH32(UINT32 value) -{ - UINT32 ea, new_esp; - if( STACK_32BIT ) { - new_esp = REG32(ESP) - 4; - ea = i386_translate( SS, new_esp, 1, 4); - WRITE32( ea, value ); - REG32(ESP) = new_esp; - } else { - new_esp = (REG16(SP) - 4) & 0xffff; - ea = i386_translate( SS, new_esp, 1, 4); - WRITE32( ea, value ); - REG16(SP) = new_esp; - } -} - -INLINE void I386_OPS_BASE::PUSH32SEG(UINT32 value) -{ - UINT32 ea, new_esp; - if( STACK_32BIT ) { - new_esp = REG32(ESP) - 4; - if( (cpustate->cpu_version & 0xf00) == 0x300 ) { - ea = i386_translate(SS, new_esp, 1, 2); - WRITE16(ea, value); // 486 also? - } else { - ea = i386_translate(SS, new_esp, 1, 4); - WRITE32(ea, value ); // 486 also? - } - REG32(ESP) = new_esp; - } else { - new_esp = (REG16(SP) - 4) & 0xffff; - if( (cpustate->cpu_version & 0xf00) == 0x300 ) { - ea = i386_translate(SS, new_esp, 1, 2); - WRITE16(ea, value); - } else { - ea = i386_translate(SS, new_esp, 1, 4); - WRITE32(ea, value ); - } - REG16(SP) = new_esp; - } -} - -INLINE void I386_OPS_BASE::PUSH8(UINT8 value) -{ - if( cpustate->operand_size ) { - PUSH32((INT32)(INT8)value); - } else { - PUSH16((INT16)(INT8)value); - } -} - -INLINE UINT8 I386_OPS_BASE::POP8() -{ - UINT8 value; - UINT32 ea, new_esp; - if( STACK_32BIT ) { - new_esp = REG32(ESP) + 1; - ea = i386_translate( SS, new_esp - 1, 0, 1); - value = READ8( ea ); - REG32(ESP) = new_esp; - } else { - new_esp = REG16(SP) + 1; - ea = i386_translate( SS, (new_esp - 1) & 0xffff, 0, 1); - value = READ8( ea ); - REG16(SP) = new_esp; - } - return value; -} - -INLINE UINT16 I386_OPS_BASE::POP16() -{ - UINT16 value; - UINT32 ea, new_esp; - if( STACK_32BIT ) { - new_esp = REG32(ESP) + 2; - ea = i386_translate( SS, new_esp - 2, 0, 2); - value = READ16( ea ); - REG32(ESP) = new_esp; - } else { - new_esp = REG16(SP) + 2; - ea = i386_translate( SS, (new_esp - 2) & 0xffff, 0, 2); - value = READ16( ea ); - REG16(SP) = new_esp; - } - return value; -} -INLINE UINT32 I386_OPS_BASE::POP32() -{ - UINT32 value; - UINT32 ea, new_esp; - if( STACK_32BIT ) { - new_esp = REG32(ESP) + 4; - ea = i386_translate( SS, new_esp - 4, 0, 4); - value = READ32( ea ); - REG32(ESP) = new_esp; - } else { - new_esp = REG16(SP) + 4; - ea = i386_translate( SS, (new_esp - 4) & 0xffff, 0, 4); - value = READ32( ea ); - REG16(SP) = new_esp; - } - return value; -} - -INLINE void I386_OPS_BASE::BUMP_SI(int adjustment) -{ - if ( cpustate->address_size ) - REG32(ESI) += ((cpustate->DF) ? -adjustment : +adjustment); - else - REG16(SI) += ((cpustate->DF) ? -adjustment : +adjustment); -} - -INLINE void I386_OPS_BASE::BUMP_DI(int adjustment) -{ - if ( cpustate->address_size ) - REG32(EDI) += ((cpustate->DF) ? -adjustment : +adjustment); - else - REG16(DI) += ((cpustate->DF) ? -adjustment : +adjustment); -} - - - -/*********************************************************************************** - I/O ACCESS -***********************************************************************************/ - -INLINE void I386_OPS_BASE::check_ioperm( offs_t port, UINT8 mask) -{ - UINT8 IOPL, map; - UINT16 IOPB; - UINT32 address; - - if(!PROTECTED_MODE) - return; - - IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); - if(!V8086_MODE && (cpustate->CPL <= IOPL)) - return; - - if((cpustate->task.limit < 0x67) || ((cpustate->task.flags & 0xd) != 9)) - FAULT_THROW(FAULT_GP,0); - - address = cpustate->task.base; - IOPB = READ16PL0( address+0x66); - if((IOPB+(port/8)) > cpustate->task.limit) - FAULT_THROW(FAULT_GP,0); - - map = READ8PL0( address+IOPB+(port/8)); - map >>= (port%8); - if(map & mask) - FAULT_THROW(FAULT_GP,0); -} - -INLINE UINT8 I386_OPS_BASE::READPORT8( offs_t port) -{ - check_ioperm( port, 1); - return cpustate->io->read_io8(port); -} - -INLINE void I386_OPS_BASE::WRITEPORT8( offs_t port, UINT8 value) -{ - check_ioperm( port, 1); - cpustate->io->write_io8(port, value); -} - -INLINE UINT16 I386_OPS_BASE::READPORT16( offs_t port) -{ - if (port & 1) - { - UINT16 value = READPORT8( port); - value |= (READPORT8( port + 1) << 8); - return value; - } - else - { - check_ioperm( port, 3); - return cpustate->io->read_io16(port); - } -} - -INLINE void I386_OPS_BASE::WRITEPORT16( offs_t port, UINT16 value) -{ - if (port & 1) - { - WRITEPORT8( port, value & 0xff); - WRITEPORT8( port + 1, (value >> 8) & 0xff); - } - else - { - check_ioperm( port, 3); - cpustate->io->write_io16(port, value); - } -} - -INLINE UINT32 I386_OPS_BASE::READPORT32( offs_t port) -{ - if (port & 3) - { - UINT32 value = READPORT8( port); - value |= (READPORT8( port + 1) << 8); - value |= (READPORT8( port + 2) << 16); - value |= (READPORT8( port + 3) << 24); - return value; - } - else - { - check_ioperm( port, 0xf); - return cpustate->io->read_io32(port); - } -} - -INLINE void I386_OPS_BASE::WRITEPORT32( offs_t port, UINT32 value) -{ - if (port & 3) - { - WRITEPORT8( port, value & 0xff); - WRITEPORT8( port + 1, (value >> 8) & 0xff); - WRITEPORT8( port + 2, (value >> 16) & 0xff); - WRITEPORT8( port + 3, (value >> 24) & 0xff); - } - else - { - check_ioperm( port, 0xf); - cpustate->io->write_io32(port, value); - } -} - - -INLINE UINT64 I386_OPS_BASE::MSR_READ(UINT32 offset,UINT8 *valid_msr) -{ - UINT64 res; - UINT8 cpu_type = (cpustate->cpu_version >> 8) & 0x0f; - - *valid_msr = 0; - - switch(cpu_type) - { - case 5: // Pentium - res = pentium_msr_read(offset,valid_msr); - break; - case 6: // Pentium Pro, Pentium II, Pentium III - res = p6_msr_read(offset,valid_msr); - break; - case 15: // Pentium 4+ - res = piv_msr_read(offset,valid_msr); - break; - default: - res = 0; - break; - } - - return res; -} - -INLINE void I386_OPS_BASE::MSR_WRITE(UINT32 offset, UINT64 data, UINT8 *valid_msr) -{ - *valid_msr = 0; - UINT8 cpu_type = (cpustate->cpu_version >> 8) & 0x0f; - - switch(cpu_type) - { - case 5: // Pentium - pentium_msr_write(offset,data,valid_msr); - break; - case 6: // Pentium Pro, Pentium II, Pentium III - p6_msr_write(offset,data,valid_msr); - break; - case 15: // Pentium 4+ - piv_msr_write(offset,data,valid_msr); - break; - } -} - -INLINE INT8 I386_OPS_BASE::SaturatedSignedWordToSignedByte(INT16 word) -{ - if (word > 127) - return 127; - if (word < -128) - return -128; - return (INT8)word; -} - -INLINE UINT8 I386_OPS_BASE::SaturatedSignedWordToUnsignedByte(INT16 word) -{ - if (word > 255) - return 255; - if (word < 0) - return 0; - return (UINT8)word; -} - -INLINE INT16 I386_OPS_BASE::SaturatedSignedDwordToSignedWord(INT32 dword) -{ - if (dword > 32767) - return 32767; - if (dword < -32768) - return -32768; - return (INT16)dword; -} - -INLINE UINT16 I386_OPS_BASE::SaturatedSignedDwordToUnsignedWord(INT32 dword) -{ - if (dword > 65535) - return 65535; - if (dword < 0) - return 0; - return (UINT16)dword; -} - -INLINE void I386_OPS_BASE::MMXPROLOG() -{ - //cpustate->x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); // top = 0 - cpustate->x87_tw = 0; // tag word = 0 -} - -INLINE void I386_OPS_BASE::READMMX(UINT32 ea,MMX_REG &r) -{ - r.q=READ64( ea); -} - -INLINE void I386_OPS_BASE::WRITEMMX(UINT32 ea,MMX_REG &r) -{ - WRITE64( ea, r.q); -} - -INLINE void I386_OPS_BASE::READXMM(UINT32 ea,XMM_REG &r) -{ - r.q[0]=READ64( ea); - r.q[1]=READ64( ea+8); -} - -INLINE void I386_OPS_BASE::WRITEXMM(UINT32 ea,XMM_REG &r) -{ - WRITE64( ea, r.q[0]); - WRITE64( ea+8, r.q[1]); -} - -INLINE void I386_OPS_BASE::READXMM_LO64(UINT32 ea,XMM_REG &r) -{ - r.q[0]=READ64( ea); -} - -INLINE void I386_OPS_BASE::WRITEXMM_LO64(UINT32 ea,XMM_REG &r) -{ - WRITE64( ea, r.q[0]); -} - -INLINE void I386_OPS_BASE::READXMM_HI64(UINT32 ea,XMM_REG &r) -{ - r.q[1]=READ64( ea); -} - -INLINE void I386_OPS_BASE::WRITEXMM_HI64(UINT32 ea,XMM_REG &r) -{ - WRITE64( ea, r.q[1]); -} - -INLINE flag I386_OPS_BASE::floatx80_is_quiet_nan(floatx80 a) -{ - bits64 aLow; - - aLow = a.low & ~LIT64(0x4000000000000000); - return - ((a.high & 0x7FFF) == 0x7FFF) - && (bits64)(aLow << 1) - && (a.low != aLow); -} - -INLINE int I386_OPS_BASE::floatx80_is_zero(floatx80 fx) -{ - return (((fx.high & 0x7fff) == 0) && ((fx.low << 1) == 0)); -} - -INLINE int I386_OPS_BASE::floatx80_is_inf(floatx80 fx) -{ - return (((fx.high & 0x7fff) == 0x7fff) && ((fx.low << 1) == 0)); -} - -INLINE int I386_OPS_BASE::floatx80_is_denormal(floatx80 fx) -{ - return (((fx.high & 0x7fff) == 0) && - ((fx.low & U64(0x8000000000000000)) == 0) && - ((fx.low << 1) != 0)); -} - -INLINE floatx80 I386_OPS_BASE::floatx80_abs(floatx80 fx) -{ - fx.high &= 0x7fff; - return fx; -} - -inline UINT64 I386_OPS_BASE::__SWAP64(UINT64 in) -{ - typedef union { - struct { - uint8_t h7, h6, h5, h4, h3, h2, h, l; - } b; - UINT64 ld; - } d1_t; - - d1_t id, od; - id.ld = in; - od.b.h7 = id.b.l; - od.b.h6 = id.b.h; - od.b.h5 = id.b.h2; - od.b.h4 = id.b.h3; - od.b.h3 = id.b.h4; - od.b.h2 = id.b.h5; - od.b.h = id.b.h6; - od.b.l = id.b.h7; - - return od.ld; -} - -INLINE double I386_OPS_BASE::fx80_to_double(floatx80 fx) -{ - union { - UINT64 ld; - double fd; // WIP: If sizeof(double) != sizeof(UINT64).(or IEEE 754 format has changed). - } d; - UINT64 nd; - nd = floatx80_to_float64(fx); -#if __FLOAT_WORD_ORDER != __BYTE_ORDER - nd = __SWAP64(nd); -#endif - d.ld = nd; - return d.fd; -} - -INLINE floatx80 I386_OPS_BASE::double_to_fx80(double in) -{ - union { - UINT64 ld; - double fd; // WIP: If sizeof(double) != sizeof(UINT64).(or IEEE 754 format has changed). - } d; - UINT64 nd; - d.fd = in; - nd = d.ld; -#if __FLOAT_WORD_ORDER != __BYTE_ORDER - nd = __SWAP64(nd); -#endif - return float64_to_floatx80(nd); -} - -INLINE floatx80 I386_OPS_BASE::READ80( UINT32 ea) -{ - floatx80 t; - - t.low = READ64( ea); - t.high = READ16( ea + 8); - - return t; -} - -INLINE void I386_OPS_BASE::WRITE80( UINT32 ea, floatx80 t) -{ - WRITE64( ea, t.low); - WRITE16( ea + 8, t.high); -} - -/************************************* - * - * x87 stack handling - * - *************************************/ - -INLINE void I386_OPS_BASE::x87_set_stack_top(int top) -{ - cpustate->x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); - cpustate->x87_sw |= (top << X87_SW_TOP_SHIFT); -} - -INLINE void I386_OPS_BASE::x87_set_tag(int reg, int tag) -{ - int shift = X87_TW_FIELD_SHIFT(reg); - - cpustate->x87_tw &= ~(X87_TW_MASK << shift); - cpustate->x87_tw |= (tag << shift); -} - -INLINE void I386_OPS_BASE::x87_set_stack_underflow() -{ - cpustate->x87_sw &= ~X87_SW_C1; - cpustate->x87_sw |= X87_SW_IE | X87_SW_SF; -} - -INLINE void I386_OPS_BASE::x87_set_stack_overflow() -{ - cpustate->x87_sw |= X87_SW_C1 | X87_SW_IE | X87_SW_SF; -} - -INLINE void I386_OPS_BASE::x87_write_cw( UINT16 cw) -{ - cpustate->x87_cw = cw; - - /* Update the SoftFloat rounding mode */ - float_rounding_mode = x87_to_sf_rc[(cpustate->x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK]; -} - -#endif diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386_ops_table.h b/source/src/vm/libcpu_newdev/libcpu_i386/i386_ops_table.h deleted file mode 100644 index 886baa52f..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386_ops_table.h +++ /dev/null @@ -1,864 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett - -#ifndef __LIB_I386_OPS_TABLE_H__ -#define __LIB_I386_OPS_TABLE_H__ -//#include "../../../common.h" -//#include "./i386ops.h" -//#include "./i386_opdef.h" - -//static const X86_OPCODE _x86_opcode_table_fake[] = -const X86_OPCODE x86_opcode_table[] = -{ -// Opcode Flags 16-bit handler 32-bit handler - { 0x00, OP_I386, &I386_OPS_BASE::i386_add_rm8_r8, &I386_OPS_BASE::i386_add_rm8_r8, true }, - { 0x01, OP_I386, &I386_OPS_BASE::i386_add_rm16_r16, &I386_OPS_BASE::i386_add_rm32_r32, true }, - { 0x02, OP_I386, &I386_OPS_BASE::i386_add_r8_rm8, &I386_OPS_BASE::i386_add_r8_rm8, false}, - { 0x03, OP_I386, &I386_OPS_BASE::i386_add_r16_rm16, &I386_OPS_BASE::i386_add_r32_rm32, false}, - { 0x04, OP_I386, &I386_OPS_BASE::i386_add_al_i8, &I386_OPS_BASE::i386_add_al_i8, false}, - { 0x05, OP_I386, &I386_OPS_BASE::i386_add_ax_i16, &I386_OPS_BASE::i386_add_eax_i32, false}, - { 0x06, OP_I386, &I386_OPS_BASE::i386_push_es16, &I386_OPS_BASE::i386_push_es32, false}, - { 0x07, OP_I386, &I386_OPS_BASE::i386_pop_es16, &I386_OPS_BASE::i386_pop_es32, false}, - { 0x08, OP_I386, &I386_OPS_BASE::i386_or_rm8_r8, &I386_OPS_BASE::i386_or_rm8_r8, true }, - { 0x09, OP_I386, &I386_OPS_BASE::i386_or_rm16_r16, &I386_OPS_BASE::i386_or_rm32_r32, true }, - { 0x0A, OP_I386, &I386_OPS_BASE::i386_or_r8_rm8, &I386_OPS_BASE::i386_or_r8_rm8, false}, - { 0x0B, OP_I386, &I386_OPS_BASE::i386_or_r16_rm16, &I386_OPS_BASE::i386_or_r32_rm32, false}, - { 0x0C, OP_I386, &I386_OPS_BASE::i386_or_al_i8, &I386_OPS_BASE::i386_or_al_i8, false}, - { 0x0D, OP_I386, &I386_OPS_BASE::i386_or_ax_i16, &I386_OPS_BASE::i386_or_eax_i32, false}, - { 0x0E, OP_I386, &I386_OPS_BASE::i386_push_cs16, &I386_OPS_BASE::i386_push_cs32, false}, - { 0x0F, OP_I386, &I386_OPS_BASE::i386_decode_two_byte, &I386_OPS_BASE::i386_decode_two_byte, true }, - { 0x10, OP_I386, &I386_OPS_BASE::i386_adc_rm8_r8, &I386_OPS_BASE::i386_adc_rm8_r8, true }, - { 0x11, OP_I386, &I386_OPS_BASE::i386_adc_rm16_r16, &I386_OPS_BASE::i386_adc_rm32_r32, true }, - { 0x12, OP_I386, &I386_OPS_BASE::i386_adc_r8_rm8, &I386_OPS_BASE::i386_adc_r8_rm8, false}, - { 0x13, OP_I386, &I386_OPS_BASE::i386_adc_r16_rm16, &I386_OPS_BASE::i386_adc_r32_rm32, false}, - { 0x14, OP_I386, &I386_OPS_BASE::i386_adc_al_i8, &I386_OPS_BASE::i386_adc_al_i8, false}, - { 0x15, OP_I386, &I386_OPS_BASE::i386_adc_ax_i16, &I386_OPS_BASE::i386_adc_eax_i32, false}, - { 0x16, OP_I386, &I386_OPS_BASE::i386_push_ss16, &I386_OPS_BASE::i386_push_ss32, false}, - { 0x17, OP_I386, &I386_OPS_BASE::i386_pop_ss16, &I386_OPS_BASE::i386_pop_ss32, false}, - { 0x18, OP_I386, &I386_OPS_BASE::i386_sbb_rm8_r8, &I386_OPS_BASE::i386_sbb_rm8_r8, true }, - { 0x19, OP_I386, &I386_OPS_BASE::i386_sbb_rm16_r16, &I386_OPS_BASE::i386_sbb_rm32_r32, true }, - { 0x1A, OP_I386, &I386_OPS_BASE::i386_sbb_r8_rm8, &I386_OPS_BASE::i386_sbb_r8_rm8, false}, - { 0x1B, OP_I386, &I386_OPS_BASE::i386_sbb_r16_rm16, &I386_OPS_BASE::i386_sbb_r32_rm32, false}, - { 0x1C, OP_I386, &I386_OPS_BASE::i386_sbb_al_i8, &I386_OPS_BASE::i386_sbb_al_i8, false}, - { 0x1D, OP_I386, &I386_OPS_BASE::i386_sbb_ax_i16, &I386_OPS_BASE::i386_sbb_eax_i32, false}, - { 0x1E, OP_I386, &I386_OPS_BASE::i386_push_ds16, &I386_OPS_BASE::i386_push_ds32, false}, - { 0x1F, OP_I386, &I386_OPS_BASE::i386_pop_ds16, &I386_OPS_BASE::i386_pop_ds32, false}, - { 0x20, OP_I386, &I386_OPS_BASE::i386_and_rm8_r8, &I386_OPS_BASE::i386_and_rm8_r8, true }, - { 0x21, OP_I386, &I386_OPS_BASE::i386_and_rm16_r16, &I386_OPS_BASE::i386_and_rm32_r32, true }, - { 0x22, OP_I386, &I386_OPS_BASE::i386_and_r8_rm8, &I386_OPS_BASE::i386_and_r8_rm8, false}, - { 0x23, OP_I386, &I386_OPS_BASE::i386_and_r16_rm16, &I386_OPS_BASE::i386_and_r32_rm32, false}, - { 0x24, OP_I386, &I386_OPS_BASE::i386_and_al_i8, &I386_OPS_BASE::i386_and_al_i8, false}, - { 0x25, OP_I386, &I386_OPS_BASE::i386_and_ax_i16, &I386_OPS_BASE::i386_and_eax_i32, false}, - { 0x26, OP_I386, &I386_OPS_BASE::i386_segment_ES, &I386_OPS_BASE::i386_segment_ES, true}, - { 0x27, OP_I386, &I386_OPS_BASE::i386_daa, &I386_OPS_BASE::i386_daa, false}, - { 0x28, OP_I386, &I386_OPS_BASE::i386_sub_rm8_r8, &I386_OPS_BASE::i386_sub_rm8_r8, true }, - { 0x29, OP_I386, &I386_OPS_BASE::i386_sub_rm16_r16, &I386_OPS_BASE::i386_sub_rm32_r32, true }, - { 0x2A, OP_I386, &I386_OPS_BASE::i386_sub_r8_rm8, &I386_OPS_BASE::i386_sub_r8_rm8, false}, - { 0x2B, OP_I386, &I386_OPS_BASE::i386_sub_r16_rm16, &I386_OPS_BASE::i386_sub_r32_rm32, false}, - { 0x2C, OP_I386, &I386_OPS_BASE::i386_sub_al_i8, &I386_OPS_BASE::i386_sub_al_i8, false}, - { 0x2D, OP_I386, &I386_OPS_BASE::i386_sub_ax_i16, &I386_OPS_BASE::i386_sub_eax_i32, false}, - { 0x2E, OP_I386, &I386_OPS_BASE::i386_segment_CS, &I386_OPS_BASE::i386_segment_CS, true}, - { 0x2F, OP_I386, &I386_OPS_BASE::i386_das, &I386_OPS_BASE::i386_das, false}, - { 0x30, OP_I386, &I386_OPS_BASE::i386_xor_rm8_r8, &I386_OPS_BASE::i386_xor_rm8_r8, true }, - { 0x31, OP_I386, &I386_OPS_BASE::i386_xor_rm16_r16, &I386_OPS_BASE::i386_xor_rm32_r32, true }, - { 0x32, OP_I386, &I386_OPS_BASE::i386_xor_r8_rm8, &I386_OPS_BASE::i386_xor_r8_rm8, false}, - { 0x33, OP_I386, &I386_OPS_BASE::i386_xor_r16_rm16, &I386_OPS_BASE::i386_xor_r32_rm32, false}, - { 0x34, OP_I386, &I386_OPS_BASE::i386_xor_al_i8, &I386_OPS_BASE::i386_xor_al_i8, false}, - { 0x35, OP_I386, &I386_OPS_BASE::i386_xor_ax_i16, &I386_OPS_BASE::i386_xor_eax_i32, false}, - { 0x36, OP_I386, &I386_OPS_BASE::i386_segment_SS, &I386_OPS_BASE::i386_segment_SS, true}, - { 0x37, OP_I386, &I386_OPS_BASE::i386_aaa, &I386_OPS_BASE::i386_aaa, false}, - { 0x38, OP_I386, &I386_OPS_BASE::i386_cmp_rm8_r8, &I386_OPS_BASE::i386_cmp_rm8_r8, false}, - { 0x39, OP_I386, &I386_OPS_BASE::i386_cmp_rm16_r16, &I386_OPS_BASE::i386_cmp_rm32_r32, false}, - { 0x3A, OP_I386, &I386_OPS_BASE::i386_cmp_r8_rm8, &I386_OPS_BASE::i386_cmp_r8_rm8, false}, - { 0x3B, OP_I386, &I386_OPS_BASE::i386_cmp_r16_rm16, &I386_OPS_BASE::i386_cmp_r32_rm32, false}, - { 0x3C, OP_I386, &I386_OPS_BASE::i386_cmp_al_i8, &I386_OPS_BASE::i386_cmp_al_i8, false}, - { 0x3D, OP_I386, &I386_OPS_BASE::i386_cmp_ax_i16, &I386_OPS_BASE::i386_cmp_eax_i32, false}, - { 0x3E, OP_I386, &I386_OPS_BASE::i386_segment_DS, &I386_OPS_BASE::i386_segment_DS, true}, - { 0x3F, OP_I386, &I386_OPS_BASE::i386_aas, &I386_OPS_BASE::i386_aas, false}, - { 0x40, OP_I386, &I386_OPS_BASE::i386_inc_ax, &I386_OPS_BASE::i386_inc_eax, false}, - { 0x41, OP_I386, &I386_OPS_BASE::i386_inc_cx, &I386_OPS_BASE::i386_inc_ecx, false}, - { 0x42, OP_I386, &I386_OPS_BASE::i386_inc_dx, &I386_OPS_BASE::i386_inc_edx, false}, - { 0x43, OP_I386, &I386_OPS_BASE::i386_inc_bx, &I386_OPS_BASE::i386_inc_ebx, false}, - { 0x44, OP_I386, &I386_OPS_BASE::i386_inc_sp, &I386_OPS_BASE::i386_inc_esp, false}, - { 0x45, OP_I386, &I386_OPS_BASE::i386_inc_bp, &I386_OPS_BASE::i386_inc_ebp, false}, - { 0x46, OP_I386, &I386_OPS_BASE::i386_inc_si, &I386_OPS_BASE::i386_inc_esi, false}, - { 0x47, OP_I386, &I386_OPS_BASE::i386_inc_di, &I386_OPS_BASE::i386_inc_edi, false}, - { 0x48, OP_I386, &I386_OPS_BASE::i386_dec_ax, &I386_OPS_BASE::i386_dec_eax, false}, - { 0x49, OP_I386, &I386_OPS_BASE::i386_dec_cx, &I386_OPS_BASE::i386_dec_ecx, false}, - { 0x4A, OP_I386, &I386_OPS_BASE::i386_dec_dx, &I386_OPS_BASE::i386_dec_edx, false}, - { 0x4B, OP_I386, &I386_OPS_BASE::i386_dec_bx, &I386_OPS_BASE::i386_dec_ebx, false}, - { 0x4C, OP_I386, &I386_OPS_BASE::i386_dec_sp, &I386_OPS_BASE::i386_dec_esp, false}, - { 0x4D, OP_I386, &I386_OPS_BASE::i386_dec_bp, &I386_OPS_BASE::i386_dec_ebp, false}, - { 0x4E, OP_I386, &I386_OPS_BASE::i386_dec_si, &I386_OPS_BASE::i386_dec_esi, false}, - { 0x4F, OP_I386, &I386_OPS_BASE::i386_dec_di, &I386_OPS_BASE::i386_dec_edi, false}, - { 0x50, OP_I386, &I386_OPS_BASE::i386_push_ax, &I386_OPS_BASE::i386_push_eax, false}, - { 0x51, OP_I386, &I386_OPS_BASE::i386_push_cx, &I386_OPS_BASE::i386_push_ecx, false}, - { 0x52, OP_I386, &I386_OPS_BASE::i386_push_dx, &I386_OPS_BASE::i386_push_edx, false}, - { 0x53, OP_I386, &I386_OPS_BASE::i386_push_bx, &I386_OPS_BASE::i386_push_ebx, false}, - { 0x54, OP_I386, &I386_OPS_BASE::i386_push_sp, &I386_OPS_BASE::i386_push_esp, false}, - { 0x55, OP_I386, &I386_OPS_BASE::i386_push_bp, &I386_OPS_BASE::i386_push_ebp, false}, - { 0x56, OP_I386, &I386_OPS_BASE::i386_push_si, &I386_OPS_BASE::i386_push_esi, false}, - { 0x57, OP_I386, &I386_OPS_BASE::i386_push_di, &I386_OPS_BASE::i386_push_edi, false}, - { 0x58, OP_I386, &I386_OPS_BASE::i386_pop_ax, &I386_OPS_BASE::i386_pop_eax, false}, - { 0x59, OP_I386, &I386_OPS_BASE::i386_pop_cx, &I386_OPS_BASE::i386_pop_ecx, false}, - { 0x5A, OP_I386, &I386_OPS_BASE::i386_pop_dx, &I386_OPS_BASE::i386_pop_edx, false}, - { 0x5B, OP_I386, &I386_OPS_BASE::i386_pop_bx, &I386_OPS_BASE::i386_pop_ebx, false}, - { 0x5C, OP_I386, &I386_OPS_BASE::i386_pop_sp, &I386_OPS_BASE::i386_pop_esp, false}, - { 0x5D, OP_I386, &I386_OPS_BASE::i386_pop_bp, &I386_OPS_BASE::i386_pop_ebp, false}, - { 0x5E, OP_I386, &I386_OPS_BASE::i386_pop_si, &I386_OPS_BASE::i386_pop_esi, false}, - { 0x5F, OP_I386, &I386_OPS_BASE::i386_pop_di, &I386_OPS_BASE::i386_pop_edi, false}, - { 0x60, OP_I386, &I386_OPS_BASE::i386_pusha, &I386_OPS_BASE::i386_pushad, false}, - { 0x61, OP_I386, &I386_OPS_BASE::i386_popa, &I386_OPS_BASE::i386_popad, false}, - { 0x62, OP_I386, &I386_OPS_BASE::i386_bound_r16_m16_m16, &I386_OPS_BASE::i386_bound_r32_m32_m32, false}, - { 0x63, OP_I386, &I386_OPS_BASE::i386_arpl, &I386_OPS_BASE::i386_arpl, false}, - { 0x64, OP_I386, &I386_OPS_BASE::i386_segment_FS, &I386_OPS_BASE::i386_segment_FS, true}, - { 0x65, OP_I386, &I386_OPS_BASE::i386_segment_GS, &I386_OPS_BASE::i386_segment_GS, true}, - { 0x66, OP_I386, &I386_OPS_BASE::i386_operand_size, &I386_OPS_BASE::i386_operand_size, true}, - { 0x67, OP_I386, &I386_OPS_BASE::i386_address_size, &I386_OPS_BASE::i386_address_size, true}, - { 0x68, OP_I386, &I386_OPS_BASE::i386_push_i16, &I386_OPS_BASE::i386_push_i32, false}, - { 0x69, OP_I386, &I386_OPS_BASE::i386_imul_r16_rm16_i16, &I386_OPS_BASE::i386_imul_r32_rm32_i32, false}, - { 0x6A, OP_I386, &I386_OPS_BASE::i386_push_i8, &I386_OPS_BASE::i386_push_i8, false}, - { 0x6B, OP_I386, &I386_OPS_BASE::i386_imul_r16_rm16_i8, &I386_OPS_BASE::i386_imul_r32_rm32_i8, false}, - { 0x6C, OP_I386, &I386_OPS_BASE::i386_insb, &I386_OPS_BASE::i386_insb, false}, - { 0x6D, OP_I386, &I386_OPS_BASE::i386_insw, &I386_OPS_BASE::i386_insd, false}, - { 0x6E, OP_I386, &I386_OPS_BASE::i386_outsb, &I386_OPS_BASE::i386_outsb, false}, - { 0x6F, OP_I386, &I386_OPS_BASE::i386_outsw, &I386_OPS_BASE::i386_outsd, false}, - { 0x70, OP_I386, &I386_OPS_BASE::i386_jo_rel8, &I386_OPS_BASE::i386_jo_rel8, false}, - { 0x71, OP_I386, &I386_OPS_BASE::i386_jno_rel8, &I386_OPS_BASE::i386_jno_rel8, false}, - { 0x72, OP_I386, &I386_OPS_BASE::i386_jc_rel8, &I386_OPS_BASE::i386_jc_rel8, false}, - { 0x73, OP_I386, &I386_OPS_BASE::i386_jnc_rel8, &I386_OPS_BASE::i386_jnc_rel8, false}, - { 0x74, OP_I386, &I386_OPS_BASE::i386_jz_rel8, &I386_OPS_BASE::i386_jz_rel8, false}, - { 0x75, OP_I386, &I386_OPS_BASE::i386_jnz_rel8, &I386_OPS_BASE::i386_jnz_rel8, false}, - { 0x76, OP_I386, &I386_OPS_BASE::i386_jbe_rel8, &I386_OPS_BASE::i386_jbe_rel8, false}, - { 0x77, OP_I386, &I386_OPS_BASE::i386_ja_rel8, &I386_OPS_BASE::i386_ja_rel8, false}, - { 0x78, OP_I386, &I386_OPS_BASE::i386_js_rel8, &I386_OPS_BASE::i386_js_rel8, false}, - { 0x79, OP_I386, &I386_OPS_BASE::i386_jns_rel8, &I386_OPS_BASE::i386_jns_rel8, false}, - { 0x7A, OP_I386, &I386_OPS_BASE::i386_jp_rel8, &I386_OPS_BASE::i386_jp_rel8, false}, - { 0x7B, OP_I386, &I386_OPS_BASE::i386_jnp_rel8, &I386_OPS_BASE::i386_jnp_rel8, false}, - { 0x7C, OP_I386, &I386_OPS_BASE::i386_jl_rel8, &I386_OPS_BASE::i386_jl_rel8, false}, - { 0x7D, OP_I386, &I386_OPS_BASE::i386_jge_rel8, &I386_OPS_BASE::i386_jge_rel8, false}, - { 0x7E, OP_I386, &I386_OPS_BASE::i386_jle_rel8, &I386_OPS_BASE::i386_jle_rel8, false}, - { 0x7F, OP_I386, &I386_OPS_BASE::i386_jg_rel8, &I386_OPS_BASE::i386_jg_rel8, false}, - { 0x80, OP_I386, &I386_OPS_BASE::i386_group80_8, &I386_OPS_BASE::i386_group80_8, true }, - { 0x81, OP_I386, &I386_OPS_BASE::i386_group81_16, &I386_OPS_BASE::i386_group81_32, true }, - { 0x82, OP_I386, &I386_OPS_BASE::i386_group80_8, &I386_OPS_BASE::i386_group80_8, true }, - { 0x83, OP_I386, &I386_OPS_BASE::i386_group83_16, &I386_OPS_BASE::i386_group83_32, true }, - { 0x84, OP_I386, &I386_OPS_BASE::i386_test_rm8_r8, &I386_OPS_BASE::i386_test_rm8_r8, false}, - { 0x85, OP_I386, &I386_OPS_BASE::i386_test_rm16_r16, &I386_OPS_BASE::i386_test_rm32_r32, false}, - { 0x86, OP_I386, &I386_OPS_BASE::i386_xchg_r8_rm8, &I386_OPS_BASE::i386_xchg_r8_rm8, true }, - { 0x87, OP_I386, &I386_OPS_BASE::i386_xchg_r16_rm16, &I386_OPS_BASE::i386_xchg_r32_rm32, true }, - { 0x88, OP_I386, &I386_OPS_BASE::i386_mov_rm8_r8, &I386_OPS_BASE::i386_mov_rm8_r8, false}, - { 0x89, OP_I386, &I386_OPS_BASE::i386_mov_rm16_r16, &I386_OPS_BASE::i386_mov_rm32_r32, false}, - { 0x8A, OP_I386, &I386_OPS_BASE::i386_mov_r8_rm8, &I386_OPS_BASE::i386_mov_r8_rm8, false}, - { 0x8B, OP_I386, &I386_OPS_BASE::i386_mov_r16_rm16, &I386_OPS_BASE::i386_mov_r32_rm32, false}, - { 0x8C, OP_I386, &I386_OPS_BASE::i386_mov_rm16_sreg, &I386_OPS_BASE::i386_mov_rm16_sreg, false}, - { 0x8D, OP_I386, &I386_OPS_BASE::i386_lea16, &I386_OPS_BASE::i386_lea32, false}, - { 0x8E, OP_I386, &I386_OPS_BASE::i386_mov_sreg_rm16, &I386_OPS_BASE::i386_mov_sreg_rm16, false}, - { 0x8F, OP_I386, &I386_OPS_BASE::i386_pop_rm16, &I386_OPS_BASE::i386_pop_rm32, false}, - { 0x90, OP_I386, &I386_OPS_BASE::i386_nop, &I386_OPS_BASE::i386_nop, false}, - { 0x91, OP_I386, &I386_OPS_BASE::i386_xchg_ax_cx, &I386_OPS_BASE::i386_xchg_eax_ecx, false}, - { 0x92, OP_I386, &I386_OPS_BASE::i386_xchg_ax_dx, &I386_OPS_BASE::i386_xchg_eax_edx, false}, - { 0x93, OP_I386, &I386_OPS_BASE::i386_xchg_ax_bx, &I386_OPS_BASE::i386_xchg_eax_ebx, false}, - { 0x94, OP_I386, &I386_OPS_BASE::i386_xchg_ax_sp, &I386_OPS_BASE::i386_xchg_eax_esp, false}, - { 0x95, OP_I386, &I386_OPS_BASE::i386_xchg_ax_bp, &I386_OPS_BASE::i386_xchg_eax_ebp, false}, - { 0x96, OP_I386, &I386_OPS_BASE::i386_xchg_ax_si, &I386_OPS_BASE::i386_xchg_eax_esi, false}, - { 0x97, OP_I386, &I386_OPS_BASE::i386_xchg_ax_di, &I386_OPS_BASE::i386_xchg_eax_edi, false}, - { 0x98, OP_I386, &I386_OPS_BASE::i386_cbw, &I386_OPS_BASE::i386_cwde, false}, - { 0x99, OP_I386, &I386_OPS_BASE::i386_cwd, &I386_OPS_BASE::i386_cdq, false}, - { 0x9A, OP_I386, &I386_OPS_BASE::i386_call_abs16, &I386_OPS_BASE::i386_call_abs32, false}, - { 0x9B, OP_I386, &I386_OPS_BASE::i386_wait, &I386_OPS_BASE::i386_wait, false}, - { 0x9C, OP_I386, &I386_OPS_BASE::i386_pushf, &I386_OPS_BASE::i386_pushfd, false}, - { 0x9D, OP_I386, &I386_OPS_BASE::i386_popf, &I386_OPS_BASE::i386_popfd, false}, - { 0x9E, OP_I386, &I386_OPS_BASE::i386_sahf, &I386_OPS_BASE::i386_sahf, false}, - { 0x9F, OP_I386, &I386_OPS_BASE::i386_lahf, &I386_OPS_BASE::i386_lahf, false}, - { 0xA0, OP_I386, &I386_OPS_BASE::i386_mov_al_m8, &I386_OPS_BASE::i386_mov_al_m8, false}, - { 0xA1, OP_I386, &I386_OPS_BASE::i386_mov_ax_m16, &I386_OPS_BASE::i386_mov_eax_m32, false}, - { 0xA2, OP_I386, &I386_OPS_BASE::i386_mov_m8_al, &I386_OPS_BASE::i386_mov_m8_al, false}, - { 0xA3, OP_I386, &I386_OPS_BASE::i386_mov_m16_ax, &I386_OPS_BASE::i386_mov_m32_eax, false}, - { 0xA4, OP_I386, &I386_OPS_BASE::i386_movsb, &I386_OPS_BASE::i386_movsb, false}, - { 0xA5, OP_I386, &I386_OPS_BASE::i386_movsw, &I386_OPS_BASE::i386_movsd, false}, - { 0xA6, OP_I386, &I386_OPS_BASE::i386_cmpsb, &I386_OPS_BASE::i386_cmpsb, false}, - { 0xA7, OP_I386, &I386_OPS_BASE::i386_cmpsw, &I386_OPS_BASE::i386_cmpsd, false}, - { 0xA8, OP_I386, &I386_OPS_BASE::i386_test_al_i8, &I386_OPS_BASE::i386_test_al_i8, false}, - { 0xA9, OP_I386, &I386_OPS_BASE::i386_test_ax_i16, &I386_OPS_BASE::i386_test_eax_i32, false}, - { 0xAA, OP_I386, &I386_OPS_BASE::i386_stosb, &I386_OPS_BASE::i386_stosb, false}, - { 0xAB, OP_I386, &I386_OPS_BASE::i386_stosw, &I386_OPS_BASE::i386_stosd, false}, - { 0xAC, OP_I386, &I386_OPS_BASE::i386_lodsb, &I386_OPS_BASE::i386_lodsb, false}, - { 0xAD, OP_I386, &I386_OPS_BASE::i386_lodsw, &I386_OPS_BASE::i386_lodsd, false}, - { 0xAE, OP_I386, &I386_OPS_BASE::i386_scasb, &I386_OPS_BASE::i386_scasb, false}, - { 0xAF, OP_I386, &I386_OPS_BASE::i386_scasw, &I386_OPS_BASE::i386_scasd, false}, - { 0xB0, OP_I386, &I386_OPS_BASE::i386_mov_al_i8, &I386_OPS_BASE::i386_mov_al_i8, false}, - { 0xB1, OP_I386, &I386_OPS_BASE::i386_mov_cl_i8, &I386_OPS_BASE::i386_mov_cl_i8, false}, - { 0xB2, OP_I386, &I386_OPS_BASE::i386_mov_dl_i8, &I386_OPS_BASE::i386_mov_dl_i8, false}, - { 0xB3, OP_I386, &I386_OPS_BASE::i386_mov_bl_i8, &I386_OPS_BASE::i386_mov_bl_i8, false}, - { 0xB4, OP_I386, &I386_OPS_BASE::i386_mov_ah_i8, &I386_OPS_BASE::i386_mov_ah_i8, false}, - { 0xB5, OP_I386, &I386_OPS_BASE::i386_mov_ch_i8, &I386_OPS_BASE::i386_mov_ch_i8, false}, - { 0xB6, OP_I386, &I386_OPS_BASE::i386_mov_dh_i8, &I386_OPS_BASE::i386_mov_dh_i8, false}, - { 0xB7, OP_I386, &I386_OPS_BASE::i386_mov_bh_i8, &I386_OPS_BASE::i386_mov_bh_i8, false}, - { 0xB8, OP_I386, &I386_OPS_BASE::i386_mov_ax_i16, &I386_OPS_BASE::i386_mov_eax_i32, false}, - { 0xB9, OP_I386, &I386_OPS_BASE::i386_mov_cx_i16, &I386_OPS_BASE::i386_mov_ecx_i32, false}, - { 0xBA, OP_I386, &I386_OPS_BASE::i386_mov_dx_i16, &I386_OPS_BASE::i386_mov_edx_i32, false}, - { 0xBB, OP_I386, &I386_OPS_BASE::i386_mov_bx_i16, &I386_OPS_BASE::i386_mov_ebx_i32, false}, - { 0xBC, OP_I386, &I386_OPS_BASE::i386_mov_sp_i16, &I386_OPS_BASE::i386_mov_esp_i32, false}, - { 0xBD, OP_I386, &I386_OPS_BASE::i386_mov_bp_i16, &I386_OPS_BASE::i386_mov_ebp_i32, false}, - { 0xBE, OP_I386, &I386_OPS_BASE::i386_mov_si_i16, &I386_OPS_BASE::i386_mov_esi_i32, false}, - { 0xBF, OP_I386, &I386_OPS_BASE::i386_mov_di_i16, &I386_OPS_BASE::i386_mov_edi_i32, false}, - { 0xC0, OP_I386, &I386_OPS_BASE::i386_groupC0_8, &I386_OPS_BASE::i386_groupC0_8, false}, - { 0xC1, OP_I386, &I386_OPS_BASE::i386_groupC1_16, &I386_OPS_BASE::i386_groupC1_32, false}, - { 0xC2, OP_I386, &I386_OPS_BASE::i386_ret_near16_i16, &I386_OPS_BASE::i386_ret_near32_i16, false}, - { 0xC3, OP_I386, &I386_OPS_BASE::i386_ret_near16, &I386_OPS_BASE::i386_ret_near32, false}, - { 0xC4, OP_I386, &I386_OPS_BASE::i386_les16, &I386_OPS_BASE::i386_les32, false}, - { 0xC5, OP_I386, &I386_OPS_BASE::i386_lds16, &I386_OPS_BASE::i386_lds32, false}, - { 0xC6, OP_I386, &I386_OPS_BASE::i386_mov_rm8_i8, &I386_OPS_BASE::i386_mov_rm8_i8, false}, - { 0xC7, OP_I386, &I386_OPS_BASE::i386_mov_rm16_i16, &I386_OPS_BASE::i386_mov_rm32_i32, false}, - { 0xC8, OP_I386, &I386_OPS_BASE::i386_enter16, &I386_OPS_BASE::i386_enter32, false}, - { 0xC9, OP_I386, &I386_OPS_BASE::i386_leave16, &I386_OPS_BASE::i386_leave32, false}, - { 0xCA, OP_I386, &I386_OPS_BASE::i386_retf_i16, &I386_OPS_BASE::i386_retf_i32, false}, - { 0xCB, OP_I386, &I386_OPS_BASE::i386_retf16, &I386_OPS_BASE::i386_retf32, false}, - { 0xCC, OP_I386, &I386_OPS_BASE::i386_int3, &I386_OPS_BASE::i386_int3, false}, - { 0xCD, OP_I386, &I386_OPS_BASE::i386__int, &I386_OPS_BASE::i386__int, false}, - { 0xCE, OP_I386, &I386_OPS_BASE::i386_into, &I386_OPS_BASE::i386_into, false}, - { 0xCF, OP_I386, &I386_OPS_BASE::i386_iret16, &I386_OPS_BASE::i386_iret32, false}, - { 0xD0, OP_I386, &I386_OPS_BASE::i386_groupD0_8, &I386_OPS_BASE::i386_groupD0_8, false}, - { 0xD1, OP_I386, &I386_OPS_BASE::i386_groupD1_16, &I386_OPS_BASE::i386_groupD1_32, false}, - { 0xD2, OP_I386, &I386_OPS_BASE::i386_groupD2_8, &I386_OPS_BASE::i386_groupD2_8, false}, - { 0xD3, OP_I386, &I386_OPS_BASE::i386_groupD3_16, &I386_OPS_BASE::i386_groupD3_32, false}, - { 0xD4, OP_I386, &I386_OPS_BASE::i386_aam, &I386_OPS_BASE::i386_aam, false}, - { 0xD5, OP_I386, &I386_OPS_BASE::i386_aad, &I386_OPS_BASE::i386_aad, false}, - { 0xD6, OP_I386, &I386_OPS_BASE::i386_setalc, &I386_OPS_BASE::i386_setalc, false}, - { 0xD7, OP_I386, &I386_OPS_BASE::i386_xlat, &I386_OPS_BASE::i386_xlat, false}, - { 0xD8, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xD9, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xDA, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xDB, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xDC, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xDD, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xDE, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xDF, OP_I386, &I386_OPS_BASE::i386_escape, &I386_OPS_BASE::i386_escape, false}, - { 0xD8, OP_FPU, &I386_OPS_BASE::i386_x87_group_d8, &I386_OPS_BASE::i386_x87_group_d8, false}, - { 0xD9, OP_FPU, &I386_OPS_BASE::i386_x87_group_d9, &I386_OPS_BASE::i386_x87_group_d9, false}, - { 0xDA, OP_FPU, &I386_OPS_BASE::i386_x87_group_da, &I386_OPS_BASE::i386_x87_group_da, false}, - { 0xDB, OP_FPU, &I386_OPS_BASE::i386_x87_group_db, &I386_OPS_BASE::i386_x87_group_db, false}, - { 0xDC, OP_FPU, &I386_OPS_BASE::i386_x87_group_dc, &I386_OPS_BASE::i386_x87_group_dc, false}, - { 0xDD, OP_FPU, &I386_OPS_BASE::i386_x87_group_dd, &I386_OPS_BASE::i386_x87_group_dd, false}, - { 0xDE, OP_FPU, &I386_OPS_BASE::i386_x87_group_de, &I386_OPS_BASE::i386_x87_group_de, false}, - { 0xDF, OP_FPU, &I386_OPS_BASE::i386_x87_group_df, &I386_OPS_BASE::i386_x87_group_df, false}, - { 0xE0, OP_I386, &I386_OPS_BASE::i386_loopne16, &I386_OPS_BASE::i386_loopne32, false}, - { 0xE1, OP_I386, &I386_OPS_BASE::i386_loopz16, &I386_OPS_BASE::i386_loopz32, false}, - { 0xE2, OP_I386, &I386_OPS_BASE::i386_loop16, &I386_OPS_BASE::i386_loop32, false}, - { 0xE3, OP_I386, &I386_OPS_BASE::i386_jcxz16, &I386_OPS_BASE::i386_jcxz32, false}, - { 0xE4, OP_I386, &I386_OPS_BASE::i386_in_al_i8, &I386_OPS_BASE::i386_in_al_i8, false}, - { 0xE5, OP_I386, &I386_OPS_BASE::i386_in_ax_i8, &I386_OPS_BASE::i386_in_eax_i8, false}, - { 0xE6, OP_I386, &I386_OPS_BASE::i386_out_al_i8, &I386_OPS_BASE::i386_out_al_i8, false}, - { 0xE7, OP_I386, &I386_OPS_BASE::i386_out_ax_i8, &I386_OPS_BASE::i386_out_eax_i8, false}, - { 0xE8, OP_I386, &I386_OPS_BASE::i386_call_rel16, &I386_OPS_BASE::i386_call_rel32, false}, - { 0xE9, OP_I386, &I386_OPS_BASE::i386_jmp_rel16, &I386_OPS_BASE::i386_jmp_rel32, false}, - { 0xEA, OP_I386, &I386_OPS_BASE::i386_jmp_abs16, &I386_OPS_BASE::i386_jmp_abs32, false}, - { 0xEB, OP_I386, &I386_OPS_BASE::i386_jmp_rel8, &I386_OPS_BASE::i386_jmp_rel8, false}, - { 0xEC, OP_I386, &I386_OPS_BASE::i386_in_al_dx, &I386_OPS_BASE::i386_in_al_dx, false}, - { 0xED, OP_I386, &I386_OPS_BASE::i386_in_ax_dx, &I386_OPS_BASE::i386_in_eax_dx, false}, - { 0xEE, OP_I386, &I386_OPS_BASE::i386_out_al_dx, &I386_OPS_BASE::i386_out_al_dx, false}, - { 0xEF, OP_I386, &I386_OPS_BASE::i386_out_ax_dx, &I386_OPS_BASE::i386_out_eax_dx, false}, - { 0xF0, OP_I386, &I386_OPS_BASE::i386_lock, &I386_OPS_BASE::i386_lock, false}, - { 0xF1, OP_I386, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF2, OP_I386, &I386_OPS_BASE::i386_repne, &I386_OPS_BASE::i386_repne, false}, - { 0xF3, OP_I386, &I386_OPS_BASE::i386_rep, &I386_OPS_BASE::i386_rep, false}, - { 0xF4, OP_I386, &I386_OPS_BASE::i386_hlt, &I386_OPS_BASE::i386_hlt, false}, - { 0xF5, OP_I386, &I386_OPS_BASE::i386_cmc, &I386_OPS_BASE::i386_cmc, false}, - { 0xF6, OP_I386, &I386_OPS_BASE::i386_groupF6_8, &I386_OPS_BASE::i386_groupF6_8, true }, - { 0xF7, OP_I386, &I386_OPS_BASE::i386_groupF7_16, &I386_OPS_BASE::i386_groupF7_32, true }, - { 0xF8, OP_I386, &I386_OPS_BASE::i386_clc, &I386_OPS_BASE::i386_clc, false}, - { 0xF9, OP_I386, &I386_OPS_BASE::i386_stc, &I386_OPS_BASE::i386_stc, false}, - { 0xFA, OP_I386, &I386_OPS_BASE::i386_cli, &I386_OPS_BASE::i386_cli, false}, - { 0xFB, OP_I386, &I386_OPS_BASE::i386_sti, &I386_OPS_BASE::i386_sti, false}, - { 0xFC, OP_I386, &I386_OPS_BASE::i386_cld, &I386_OPS_BASE::i386_cld, false}, - { 0xFD, OP_I386, &I386_OPS_BASE::i386_std, &I386_OPS_BASE::i386_std, false}, - { 0xFE, OP_I386, &I386_OPS_BASE::i386_groupFE_8, &I386_OPS_BASE::i386_groupFE_8, true }, - { 0xFF, OP_I386, &I386_OPS_BASE::i386_groupFF_16, &I386_OPS_BASE::i386_groupFF_32, true }, - /* 0F ?? */ - { 0x00, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_group0F00_16, &I386_OPS_BASE::i386_group0F00_32, false}, - { 0x01, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_group0F01_16, &I386_OPS_BASE::i386_group0F01_32, false}, - { 0x01, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_group0F01_16, &I386_OPS_BASE::i486_group0F01_32, false}, - { 0x02, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_lar_r16_rm16, &I386_OPS_BASE::i386_lar_r32_rm32, false}, - { 0x03, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_lsl_r16_rm16, &I386_OPS_BASE::i386_lsl_r32_rm32, false}, - { 0x06, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_clts, &I386_OPS_BASE::i386_clts, false}, - { 0x07, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_loadall, &I386_OPS_BASE::i386_loadall, false}, - { 0x07, OP_2BYTE|OP_I486, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x08, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_invd, &I386_OPS_BASE::i486_invd, false}, - { 0x09, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_wbinvd, &I386_OPS_BASE::i486_wbinvd, false}, - { 0x0B, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_ud2, &I386_OPS_BASE::pentium_ud2, false}, - { 0x10, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movups_r128_rm128, &I386_OPS_BASE::sse_movups_r128_rm128, false}, - { 0x11, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movups_rm128_r128, &I386_OPS_BASE::sse_movups_rm128_r128, false}, - { 0x12, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movlps_r128_m64, &I386_OPS_BASE::sse_movlps_r128_m64, false}, - { 0x13, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movlps_m64_r128, &I386_OPS_BASE::sse_movlps_m64_r128, false}, - { 0x14, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_unpcklps_r128_rm128, &I386_OPS_BASE::sse_unpcklps_r128_rm128, false}, - { 0x15, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_unpckhps_r128_rm128, &I386_OPS_BASE::sse_unpckhps_r128_rm128, false}, - { 0x16, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movhps_r128_m64, &I386_OPS_BASE::sse_movhps_r128_m64, false}, - { 0x17, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movhps_m64_r128, &I386_OPS_BASE::sse_movhps_m64_r128, false}, - { 0x18, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_prefetch_m8, &I386_OPS_BASE::pentium_prefetch_m8, false}, - { 0x20, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_mov_r32_cr, &I386_OPS_BASE::i386_mov_r32_cr, false}, - { 0x21, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_mov_r32_dr, &I386_OPS_BASE::i386_mov_r32_dr, false}, - { 0x22, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_mov_cr_r32, &I386_OPS_BASE::i386_mov_cr_r32, false}, - { 0x22, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_mov_cr_r32, &I386_OPS_BASE::i486_mov_cr_r32, false}, - { 0x23, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_mov_dr_r32, &I386_OPS_BASE::i386_mov_dr_r32, false}, - { 0x24, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_mov_r32_tr, &I386_OPS_BASE::i386_mov_r32_tr, false}, - { 0x26, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_mov_tr_r32, &I386_OPS_BASE::i386_mov_tr_r32, false}, - { 0x28, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movaps_r128_rm128, &I386_OPS_BASE::sse_movaps_r128_rm128, false}, - { 0x29, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movaps_rm128_r128, &I386_OPS_BASE::sse_movaps_rm128_r128, false}, - { 0x2a, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_cvtpi2ps_r128_rm64, &I386_OPS_BASE::sse_cvtpi2ps_r128_rm64, false}, - { 0x2b, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movntps_m128_r128, &I386_OPS_BASE::sse_movntps_m128_r128, false}, - { 0x2c, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_cvttps2pi_r64_r128m64, &I386_OPS_BASE::sse_cvttps2pi_r64_r128m64,false}, - { 0x2d, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_cvtps2pi_r64_r128m64, &I386_OPS_BASE::sse_cvtps2pi_r64_r128m64,false}, - { 0x2e, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_ucomiss_r128_r128m32, &I386_OPS_BASE::sse_ucomiss_r128_r128m32,false}, - { 0x2f, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_comiss_r128_r128m32, &I386_OPS_BASE::sse_comiss_r128_r128m32, false}, - { 0x30, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_wrmsr, &I386_OPS_BASE::pentium_wrmsr, false}, - { 0x31, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_rdtsc, &I386_OPS_BASE::pentium_rdtsc, false}, - { 0x32, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_rdmsr, &I386_OPS_BASE::pentium_rdmsr, false}, - { 0x38, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::i386_decode_three_byte38, &I386_OPS_BASE::i386_decode_three_byte38,false}, - { 0x3A, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::i386_decode_three_byte3a, &I386_OPS_BASE::i386_decode_three_byte3a,false}, - { 0x3A, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_special, &I386_OPS_BASE::i386_cyrix_special, false}, - { 0x3B, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_special, &I386_OPS_BASE::i386_cyrix_special, false}, - { 0x3C, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_special, &I386_OPS_BASE::i386_cyrix_special, false}, - { 0x3D, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_special, &I386_OPS_BASE::i386_cyrix_special, false}, - { 0x40, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovo_r16_rm16, &I386_OPS_BASE::pentium_cmovo_r32_rm32, false}, - { 0x41, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovno_r16_rm16, &I386_OPS_BASE::pentium_cmovno_r32_rm32, false}, - { 0x42, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovb_r16_rm16, &I386_OPS_BASE::pentium_cmovb_r32_rm32, false}, - { 0x43, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovae_r16_rm16, &I386_OPS_BASE::pentium_cmovae_r32_rm32, false}, - { 0x44, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmove_r16_rm16, &I386_OPS_BASE::pentium_cmove_r32_rm32, false}, - { 0x45, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovne_r16_rm16, &I386_OPS_BASE::pentium_cmovne_r32_rm32, false}, - { 0x46, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovbe_r16_rm16, &I386_OPS_BASE::pentium_cmovbe_r32_rm32, false}, - { 0x47, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmova_r16_rm16, &I386_OPS_BASE::pentium_cmova_r32_rm32, false}, - { 0x48, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovs_r16_rm16, &I386_OPS_BASE::pentium_cmovs_r32_rm32, false}, - { 0x49, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovns_r16_rm16, &I386_OPS_BASE::pentium_cmovns_r32_rm32, false}, - { 0x4a, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovp_r16_rm16, &I386_OPS_BASE::pentium_cmovp_r32_rm32, false}, - { 0x4b, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovnp_r16_rm16, &I386_OPS_BASE::pentium_cmovnp_r32_rm32, false}, - { 0x4c, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovl_r16_rm16, &I386_OPS_BASE::pentium_cmovl_r32_rm32, false}, - { 0x4d, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovge_r16_rm16, &I386_OPS_BASE::pentium_cmovge_r32_rm32, false}, - { 0x4e, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovle_r16_rm16, &I386_OPS_BASE::pentium_cmovle_r32_rm32, false}, - { 0x4f, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmovg_r16_rm16, &I386_OPS_BASE::pentium_cmovg_r32_rm32, false}, - { 0x50, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_movmskps_r16_r128, &I386_OPS_BASE::sse_movmskps_r32_r128, false}, - { 0x51, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_sqrtps_r128_rm128, &I386_OPS_BASE::sse_sqrtps_r128_rm128, false}, - { 0x52, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_rsqrtps_r128_rm128, &I386_OPS_BASE::sse_rsqrtps_r128_rm128, false}, - { 0x53, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_rcpps_r128_rm128, &I386_OPS_BASE::sse_rcpps_r128_rm128, false}, - { 0x54, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_andps_r128_rm128, &I386_OPS_BASE::sse_andps_r128_rm128, false}, - { 0x55, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_andnps_r128_rm128, &I386_OPS_BASE::sse_andnps_r128_rm128, false}, - { 0x56, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_orps_r128_rm128, &I386_OPS_BASE::sse_orps_r128_rm128, false}, - { 0x57, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_xorps, &I386_OPS_BASE::sse_xorps, false}, - { 0x58, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_addps, &I386_OPS_BASE::sse_addps, false}, - { 0x59, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_mulps, &I386_OPS_BASE::sse_mulps, false}, - { 0x5a, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_cvtps2pd_r128_r128m64, &I386_OPS_BASE::sse_cvtps2pd_r128_r128m64,false}, - { 0x5b, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_cvtdq2ps_r128_rm128, &I386_OPS_BASE::sse_cvtdq2ps_r128_rm128, false}, - { 0x5c, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_subps, &I386_OPS_BASE::sse_subps, false}, - { 0x5d, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_minps, &I386_OPS_BASE::sse_minps, false}, - { 0x5e, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_divps, &I386_OPS_BASE::sse_divps, false}, - { 0x5f, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_maxps, &I386_OPS_BASE::sse_maxps, false}, - { 0x60, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_punpcklbw_r64_r64m32, &I386_OPS_BASE::mmx_punpcklbw_r64_r64m32,false}, - { 0x61, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_punpcklwd_r64_r64m32, &I386_OPS_BASE::mmx_punpcklwd_r64_r64m32,false}, - { 0x62, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_punpckldq_r64_r64m32, &I386_OPS_BASE::mmx_punpckldq_r64_r64m32,false}, - { 0x63, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_packsswb_r64_rm64, &I386_OPS_BASE::mmx_packsswb_r64_rm64, false}, - { 0x64, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pcmpgtb_r64_rm64, &I386_OPS_BASE::mmx_pcmpgtb_r64_rm64, false}, - { 0x65, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pcmpgtw_r64_rm64, &I386_OPS_BASE::mmx_pcmpgtw_r64_rm64, false}, - { 0x66, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pcmpgtd_r64_rm64, &I386_OPS_BASE::mmx_pcmpgtd_r64_rm64, false}, - { 0x67, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_packuswb_r64_rm64, &I386_OPS_BASE::mmx_packuswb_r64_rm64, false}, - { 0x68, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_punpckhbw_r64_rm64, &I386_OPS_BASE::mmx_punpckhbw_r64_rm64, false}, - { 0x69, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_punpckhwd_r64_rm64, &I386_OPS_BASE::mmx_punpckhwd_r64_rm64, false}, - { 0x6a, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_punpckhdq_r64_rm64, &I386_OPS_BASE::mmx_punpckhdq_r64_rm64, false}, - { 0x6b, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_packssdw_r64_rm64, &I386_OPS_BASE::mmx_packssdw_r64_rm64, false}, - { 0x6e, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_movd_r64_rm32, &I386_OPS_BASE::mmx_movd_r64_rm32, false}, - { 0x6f, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_movq_r64_rm64, &I386_OPS_BASE::mmx_movq_r64_rm64, false}, - { 0x70, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pshufw_r64_rm64_i8, &I386_OPS_BASE::mmx_pshufw_r64_rm64_i8, false}, - { 0x71, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_group_0f71, &I386_OPS_BASE::mmx_group_0f71, false}, - { 0x72, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_group_0f72, &I386_OPS_BASE::mmx_group_0f72, false}, - { 0x73, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_group_0f73, &I386_OPS_BASE::mmx_group_0f73, false}, - { 0x74, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_unknown, &I386_OPS_BASE::i386_cyrix_unknown, false}, - { 0x74, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pcmpeqb_r64_rm64, &I386_OPS_BASE::mmx_pcmpeqb_r64_rm64, false}, - { 0x75, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pcmpeqw_r64_rm64, &I386_OPS_BASE::mmx_pcmpeqw_r64_rm64, false}, - { 0x76, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pcmpeqd_r64_rm64, &I386_OPS_BASE::mmx_pcmpeqd_r64_rm64, false}, - { 0x77, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_emms, &I386_OPS_BASE::mmx_emms, false}, - { 0x78, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_svdc, &I386_OPS_BASE::i386_cyrix_svdc, false}, - { 0x79, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_rsdc, &I386_OPS_BASE::i386_cyrix_rsdc, false}, - { 0x7a, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_svldt, &I386_OPS_BASE::i386_cyrix_svldt, false}, - { 0x7b, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_rsldt, &I386_OPS_BASE::i386_cyrix_rsldt, false}, - { 0x7c, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_svts, &I386_OPS_BASE::i386_cyrix_svts, false}, - { 0x7d, OP_2BYTE|OP_CYRIX, &I386_OPS_BASE::i386_cyrix_rsts, &I386_OPS_BASE::i386_cyrix_rsts, false}, - { 0x7e, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_movd_rm32_r64, &I386_OPS_BASE::mmx_movd_rm32_r64, false}, - { 0x7f, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_movq_rm64_r64, &I386_OPS_BASE::mmx_movq_rm64_r64, false}, - { 0x80, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jo_rel16, &I386_OPS_BASE::i386_jo_rel32, false}, - { 0x81, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jno_rel16, &I386_OPS_BASE::i386_jno_rel32, false}, - { 0x82, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jc_rel16, &I386_OPS_BASE::i386_jc_rel32, false}, - { 0x83, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jnc_rel16, &I386_OPS_BASE::i386_jnc_rel32, false}, - { 0x84, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jz_rel16, &I386_OPS_BASE::i386_jz_rel32, false}, - { 0x85, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jnz_rel16, &I386_OPS_BASE::i386_jnz_rel32, false}, - { 0x86, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jbe_rel16, &I386_OPS_BASE::i386_jbe_rel32, false}, - { 0x87, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_ja_rel16, &I386_OPS_BASE::i386_ja_rel32, false}, - { 0x88, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_js_rel16, &I386_OPS_BASE::i386_js_rel32, false}, - { 0x89, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jns_rel16, &I386_OPS_BASE::i386_jns_rel32, false}, - { 0x8A, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jp_rel16, &I386_OPS_BASE::i386_jp_rel32, false}, - { 0x8B, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jnp_rel16, &I386_OPS_BASE::i386_jnp_rel32, false}, - { 0x8C, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jl_rel16, &I386_OPS_BASE::i386_jl_rel32, false}, - { 0x8D, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jge_rel16, &I386_OPS_BASE::i386_jge_rel32, false}, - { 0x8E, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jle_rel16, &I386_OPS_BASE::i386_jle_rel32, false}, - { 0x8F, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_jg_rel16, &I386_OPS_BASE::i386_jg_rel32, false}, - { 0x90, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_seto_rm8, &I386_OPS_BASE::i386_seto_rm8, false}, - { 0x91, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setno_rm8, &I386_OPS_BASE::i386_setno_rm8, false}, - { 0x92, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setc_rm8, &I386_OPS_BASE::i386_setc_rm8, false}, - { 0x93, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setnc_rm8, &I386_OPS_BASE::i386_setnc_rm8, false}, - { 0x94, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setz_rm8, &I386_OPS_BASE::i386_setz_rm8, false}, - { 0x95, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setnz_rm8, &I386_OPS_BASE::i386_setnz_rm8, false}, - { 0x96, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setbe_rm8, &I386_OPS_BASE::i386_setbe_rm8, false}, - { 0x97, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_seta_rm8, &I386_OPS_BASE::i386_seta_rm8, false}, - { 0x98, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_sets_rm8, &I386_OPS_BASE::i386_sets_rm8, false}, - { 0x99, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setns_rm8, &I386_OPS_BASE::i386_setns_rm8, false}, - { 0x9A, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setp_rm8, &I386_OPS_BASE::i386_setp_rm8, false}, - { 0x9B, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setnp_rm8, &I386_OPS_BASE::i386_setnp_rm8, false}, - { 0x9C, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setl_rm8, &I386_OPS_BASE::i386_setl_rm8, false}, - { 0x9D, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setge_rm8, &I386_OPS_BASE::i386_setge_rm8, false}, - { 0x9E, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setle_rm8, &I386_OPS_BASE::i386_setle_rm8, false}, - { 0x9F, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_setg_rm8, &I386_OPS_BASE::i386_setg_rm8, false}, - { 0xA0, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_push_fs16, &I386_OPS_BASE::i386_push_fs32, false}, - { 0xA1, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_pop_fs16, &I386_OPS_BASE::i386_pop_fs32, false}, - { 0xA2, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_cpuid, &I386_OPS_BASE::i486_cpuid, false}, - { 0xA3, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_bt_rm16_r16, &I386_OPS_BASE::i386_bt_rm32_r32, false}, - { 0xA4, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_shld16_i8, &I386_OPS_BASE::i386_shld32_i8, false}, - { 0xA5, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_shld16_cl, &I386_OPS_BASE::i386_shld32_cl, false}, - { 0xA8, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_push_gs16, &I386_OPS_BASE::i386_push_gs32, false}, - { 0xA9, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_pop_gs16, &I386_OPS_BASE::i386_pop_gs32, false}, - { 0xAA, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_rsm, &I386_OPS_BASE::pentium_rsm, false}, - { 0xAB, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_bts_rm16_r16, &I386_OPS_BASE::i386_bts_rm32_r32, true }, - { 0xAC, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_shrd16_i8, &I386_OPS_BASE::i386_shrd32_i8, false}, - { 0xAD, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_shrd16_cl, &I386_OPS_BASE::i386_shrd32_cl, false}, - { 0xAE, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_group_0fae, &I386_OPS_BASE::sse_group_0fae, false}, - { 0xAF, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_imul_r16_rm16, &I386_OPS_BASE::i386_imul_r32_rm32, false}, - { 0xB0, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_cmpxchg_rm8_r8, &I386_OPS_BASE::i486_cmpxchg_rm8_r8, true }, - { 0xB1, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_cmpxchg_rm16_r16, &I386_OPS_BASE::i486_cmpxchg_rm32_r32, true }, - { 0xB2, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_lss16, &I386_OPS_BASE::i386_lss32, false}, - { 0xB3, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_btr_rm16_r16, &I386_OPS_BASE::i386_btr_rm32_r32, true }, - { 0xB4, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_lfs16, &I386_OPS_BASE::i386_lfs32, false}, - { 0xB5, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_lgs16, &I386_OPS_BASE::i386_lgs32, false}, - { 0xB6, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_movzx_r16_rm8, &I386_OPS_BASE::i386_movzx_r32_rm8, false}, - { 0xB7, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_movzx_r32_rm16, false}, - { 0xBA, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_group0FBA_16, &I386_OPS_BASE::i386_group0FBA_32, true }, - { 0xBB, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_btc_rm16_r16, &I386_OPS_BASE::i386_btc_rm32_r32, true }, - { 0xBC, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_bsf_r16_rm16, &I386_OPS_BASE::i386_bsf_r32_rm32, false}, - { 0xBD, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_bsr_r16_rm16, &I386_OPS_BASE::i386_bsr_r32_rm32, false}, - { 0xBE, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_movsx_r16_rm8, &I386_OPS_BASE::i386_movsx_r32_rm8, false}, - { 0xBF, OP_2BYTE|OP_I386, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_movsx_r32_rm16, false}, - { 0xC0, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_xadd_rm8_r8, &I386_OPS_BASE::i486_xadd_rm8_r8, true }, - { 0xC1, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_xadd_rm16_r16, &I386_OPS_BASE::i486_xadd_rm32_r32, true }, - { 0xC2, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_cmpps_r128_rm128_i8, &I386_OPS_BASE::sse_cmpps_r128_rm128_i8, false}, - { 0xC3, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_movnti_m16_r16, &I386_OPS_BASE::pentium_movnti_m32_r32, false}, - { 0xC4, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pinsrw_r64_r16m16_i8, &I386_OPS_BASE::sse_pinsrw_r64_r32m16_i8,false}, - { 0xC5, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pextrw_r16_r64_i8, &I386_OPS_BASE::sse_pextrw_r32_r64_i8, false}, - { 0xC6, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_shufps, &I386_OPS_BASE::sse_shufps, false}, - { 0xC7, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_cmpxchg8b_m64, &I386_OPS_BASE::pentium_cmpxchg8b_m64, true }, - { 0xC8, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_eax, &I386_OPS_BASE::i486_bswap_eax, false}, - { 0xC9, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_ecx, &I386_OPS_BASE::i486_bswap_ecx, false}, - { 0xCA, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_edx, &I386_OPS_BASE::i486_bswap_edx, false}, - { 0xCB, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_ebx, &I386_OPS_BASE::i486_bswap_ebx, false}, - { 0xCC, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_esp, &I386_OPS_BASE::i486_bswap_esp, false}, - { 0xCD, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_ebp, &I386_OPS_BASE::i486_bswap_ebp, false}, - { 0xCE, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_esi, &I386_OPS_BASE::i486_bswap_esi, false}, - { 0xCF, OP_2BYTE|OP_I486, &I386_OPS_BASE::i486_bswap_edi, &I386_OPS_BASE::i486_bswap_edi, false}, - { 0xD1, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psrlw_r64_rm64, &I386_OPS_BASE::mmx_psrlw_r64_rm64, false}, - { 0xD2, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psrld_r64_rm64, &I386_OPS_BASE::mmx_psrld_r64_rm64, false}, - { 0xD3, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psrlq_r64_rm64, &I386_OPS_BASE::mmx_psrlq_r64_rm64, false}, - { 0xD4, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddq_r64_rm64, &I386_OPS_BASE::mmx_paddq_r64_rm64, false}, - { 0xD5, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pmullw_r64_rm64, &I386_OPS_BASE::mmx_pmullw_r64_rm64, false}, - { 0xD7, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pmovmskb_r16_r64, &I386_OPS_BASE::sse_pmovmskb_r32_r64, false}, - { 0xD8, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psubusb_r64_rm64, &I386_OPS_BASE::mmx_psubusb_r64_rm64, false}, - { 0xD9, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psubusw_r64_rm64, &I386_OPS_BASE::mmx_psubusw_r64_rm64, false}, - { 0xDA, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pminub_r64_rm64, &I386_OPS_BASE::sse_pminub_r64_rm64, false}, - { 0xDB, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pand_r64_rm64, &I386_OPS_BASE::mmx_pand_r64_rm64, false}, - { 0xDC, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddusb_r64_rm64, &I386_OPS_BASE::mmx_paddusb_r64_rm64, false}, - { 0xDD, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddusw_r64_rm64, &I386_OPS_BASE::mmx_paddusw_r64_rm64, false}, - { 0xDE, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pmaxub_r64_rm64, &I386_OPS_BASE::sse_pmaxub_r64_rm64, false}, - { 0xDF, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pandn_r64_rm64, &I386_OPS_BASE::mmx_pandn_r64_rm64, false}, - { 0xE0, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pavgb_r64_rm64, &I386_OPS_BASE::sse_pavgb_r64_rm64, false}, - { 0xE1, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psraw_r64_rm64, &I386_OPS_BASE::mmx_psraw_r64_rm64, false}, - { 0xE2, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psrad_r64_rm64, &I386_OPS_BASE::mmx_psrad_r64_rm64, false}, - { 0xE3, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pavgw_r64_rm64, &I386_OPS_BASE::sse_pavgw_r64_rm64, false}, - { 0xE4, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pmulhuw_r64_rm64, &I386_OPS_BASE::sse_pmulhuw_r64_rm64, false}, - { 0xE5, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pmulhw_r64_rm64, &I386_OPS_BASE::mmx_pmulhw_r64_rm64, false}, - { 0xE7, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_movntq_m64_r64, &I386_OPS_BASE::pentium_movntq_m64_r64, false}, - { 0xE8, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psubsb_r64_rm64, &I386_OPS_BASE::mmx_psubsb_r64_rm64, false}, - { 0xE9, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psubsw_r64_rm64, &I386_OPS_BASE::mmx_psubsw_r64_rm64, false}, - { 0xEA, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pminsw_r64_rm64, &I386_OPS_BASE::sse_pminsw_r64_rm64, false}, - { 0xEB, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_por_r64_rm64, &I386_OPS_BASE::mmx_por_r64_rm64, false}, - { 0xEC, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddsb_r64_rm64, &I386_OPS_BASE::mmx_paddsb_r64_rm64, false}, - { 0xED, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddsw_r64_rm64, &I386_OPS_BASE::mmx_paddsw_r64_rm64, false}, - { 0xEE, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pmaxsw_r64_rm64, &I386_OPS_BASE::sse_pmaxsw_r64_rm64, false}, - { 0xEF, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pxor_r64_rm64, &I386_OPS_BASE::mmx_pxor_r64_rm64, false}, - { 0xF1, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psllw_r64_rm64, &I386_OPS_BASE::mmx_psllw_r64_rm64, false}, - { 0xF2, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pslld_r64_rm64, &I386_OPS_BASE::mmx_pslld_r64_rm64, false}, - { 0xF3, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psllq_r64_rm64, &I386_OPS_BASE::mmx_psllq_r64_rm64, false}, - { 0xF4, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_pmuludq_r64_rm64, &I386_OPS_BASE::sse_pmuludq_r64_rm64, false}, - { 0xF5, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_pmaddwd_r64_rm64, &I386_OPS_BASE::mmx_pmaddwd_r64_rm64, false}, - { 0xF6, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_psadbw_r64_rm64, &I386_OPS_BASE::sse_psadbw_r64_rm64, false}, - { 0xf7, OP_2BYTE|OP_PENTIUM, &I386_OPS_BASE::pentium_maskmovq_r64_r64, &I386_OPS_BASE::pentium_maskmovq_r64_r64,false}, - { 0xF8, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psubb_r64_rm64, &I386_OPS_BASE::mmx_psubb_r64_rm64, false}, - { 0xF9, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psubw_r64_rm64, &I386_OPS_BASE::mmx_psubw_r64_rm64, false}, - { 0xFA, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_psubd_r64_rm64, &I386_OPS_BASE::mmx_psubd_r64_rm64, false}, - { 0xFB, OP_2BYTE|OP_SSE, &I386_OPS_BASE::sse_psubq_r64_rm64, &I386_OPS_BASE::sse_psubq_r64_rm64, false}, - { 0xFC, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddb_r64_rm64, &I386_OPS_BASE::mmx_paddb_r64_rm64, false}, - { 0xFD, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddw_r64_rm64, &I386_OPS_BASE::mmx_paddw_r64_rm64, false}, - { 0xFE, OP_2BYTE|OP_MMX, &I386_OPS_BASE::mmx_paddd_r64_rm64, &I386_OPS_BASE::mmx_paddd_r64_rm64, false}, - /* F3 0F ?? */ - { 0x10, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movss_r128_rm128, &I386_OPS_BASE::sse_movss_r128_rm128, false}, - { 0x11, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movss_rm128_r128, &I386_OPS_BASE::sse_movss_rm128_r128, false}, - { 0x12, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movsldup_r128_rm128, &I386_OPS_BASE::sse_movsldup_r128_rm128, false}, - { 0x16, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movshdup_r128_rm128, &I386_OPS_BASE::sse_movshdup_r128_rm128, false}, - { 0x2A, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_cvtsi2ss_r128_rm32, &I386_OPS_BASE::sse_cvtsi2ss_r128_rm32, false}, - { 0x2C, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_cvttss2si_r32_r128m32, &I386_OPS_BASE::sse_cvttss2si_r32_r128m32,false}, - { 0x2D, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_cvtss2si_r32_r128m32, &I386_OPS_BASE::sse_cvtss2si_r32_r128m32,false}, - { 0x51, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_sqrtss_r128_r128m32, &I386_OPS_BASE::sse_sqrtss_r128_r128m32, false}, - { 0x52, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_rsqrtss_r128_r128m32, &I386_OPS_BASE::sse_rsqrtss_r128_r128m32,false}, - { 0x53, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_rcpss_r128_r128m32, &I386_OPS_BASE::sse_rcpss_r128_r128m32, false}, - { 0x58, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_addss, &I386_OPS_BASE::sse_addss, false}, - { 0x59, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_mulss, &I386_OPS_BASE::sse_mulss, false}, - { 0x5A, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_cvtss2sd_r128_r128m32, &I386_OPS_BASE::sse_cvtss2sd_r128_r128m32,false}, - { 0x5B, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_cvttps2dq_r128_rm128, &I386_OPS_BASE::sse_cvttps2dq_r128_rm128,false}, - { 0x5C, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_subss, &I386_OPS_BASE::sse_subss, false}, - { 0x5D, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_minss_r128_r128m32, &I386_OPS_BASE::sse_minss_r128_r128m32, false}, - { 0x5E, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_divss, &I386_OPS_BASE::sse_divss, false}, - { 0x5F, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_maxss_r128_r128m32, &I386_OPS_BASE::sse_maxss_r128_r128m32, false}, - { 0x6F, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movdqu_r128_rm128, &I386_OPS_BASE::sse_movdqu_r128_rm128, false}, - { 0x70, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_pshufhw_r128_rm128_i8, &I386_OPS_BASE::sse_pshufhw_r128_rm128_i8,false}, - { 0x7E, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movq_r128_r128m64, &I386_OPS_BASE::sse_movq_r128_r128m64, false}, - { 0x7F, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movdqu_rm128_r128, &I386_OPS_BASE::sse_movdqu_rm128_r128, false}, - { 0xAE, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xB8, OP_3BYTEF3|OP_PENTIUM, &I386_OPS_BASE::pentium_popcnt_r16_rm16, &I386_OPS_BASE::pentium_popcnt_r32_rm32, false}, - { 0xBC, OP_3BYTEF3|OP_PENTIUM, &I386_OPS_BASE::pentium_tzcnt_r16_rm16, &I386_OPS_BASE::pentium_tzcnt_r32_rm32, false}, - { 0xC2, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_cmpss_r128_r128m32_i8, &I386_OPS_BASE::sse_cmpss_r128_r128m32_i8,false}, - { 0xC7, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xD6, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_movq2dq_r128_r64, &I386_OPS_BASE::sse_movq2dq_r128_r64, false}, - { 0xE6, OP_3BYTEF3|OP_SSE, &I386_OPS_BASE::sse_cvtdq2pd_r128_r128m64, &I386_OPS_BASE::sse_cvtdq2pd_r128_r128m64,false}, - /* F2 0F ?? */ - { 0x10, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_movsd_r128_r128m64, &I386_OPS_BASE::sse_movsd_r128_r128m64, false}, - { 0x11, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_movsd_r128m64_r128, &I386_OPS_BASE::sse_movsd_r128m64_r128, false}, - { 0x12, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_movddup_r128_r128m64, &I386_OPS_BASE::sse_movddup_r128_r128m64,false}, - { 0x2A, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_cvtsi2sd_r128_rm32, &I386_OPS_BASE::sse_cvtsi2sd_r128_rm32, false}, - { 0x2C, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_cvttsd2si_r32_r128m64, &I386_OPS_BASE::sse_cvttsd2si_r32_r128m64,false}, - { 0x2D, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_cvtsd2si_r32_r128m64, &I386_OPS_BASE::sse_cvtsd2si_r32_r128m64,false}, - { 0x51, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_sqrtsd_r128_r128m64, &I386_OPS_BASE::sse_sqrtsd_r128_r128m64, false}, - { 0x58, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_addsd_r128_r128m64, &I386_OPS_BASE::sse_addsd_r128_r128m64, false}, - { 0x59, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_mulsd_r128_r128m64, &I386_OPS_BASE::sse_mulsd_r128_r128m64, false}, - { 0x5A, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_cvtsd2ss_r128_r128m64, &I386_OPS_BASE::sse_cvtsd2ss_r128_r128m64,false}, - { 0x5C, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_subsd_r128_r128m64, &I386_OPS_BASE::sse_subsd_r128_r128m64, false}, - { 0x5D, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_minsd_r128_r128m64, &I386_OPS_BASE::sse_minsd_r128_r128m64, false}, - { 0x5E, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_divsd_r128_r128m64, &I386_OPS_BASE::sse_divsd_r128_r128m64, false}, - { 0x5F, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_maxsd_r128_r128m64, &I386_OPS_BASE::sse_maxsd_r128_r128m64, false}, - { 0x70, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_pshuflw_r128_rm128_i8, &I386_OPS_BASE::sse_pshuflw_r128_rm128_i8,false}, - { 0x7C, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_haddps_r128_rm128, &I386_OPS_BASE::sse_haddps_r128_rm128, false}, - { 0x7D, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_hsubps_r128_rm128, &I386_OPS_BASE::sse_hsubps_r128_rm128, false}, - { 0xC2, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_cmpsd_r128_r128m64_i8, &I386_OPS_BASE::sse_cmpsd_r128_r128m64_i8,false}, - { 0xD0, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_addsubps_r128_rm128, &I386_OPS_BASE::sse_addsubps_r128_rm128, false}, - { 0xD6, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_movdq2q_r64_r128, &I386_OPS_BASE::sse_movdq2q_r64_r128, false}, - { 0xE6, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_cvtpd2dq_r128_rm128, &I386_OPS_BASE::sse_cvtpd2dq_r128_rm128, false}, - { 0xF0, OP_3BYTEF2|OP_SSE, &I386_OPS_BASE::sse_lddqu_r128_m128, &I386_OPS_BASE::sse_lddqu_r128_m128, false}, - /* 66 0F ?? */ - { 0x10, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movupd_r128_rm128, &I386_OPS_BASE::sse_movupd_r128_rm128, false}, - { 0x11, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movupd_rm128_r128, &I386_OPS_BASE::sse_movupd_rm128_r128, false}, - { 0x12, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movlpd_r128_m64, &I386_OPS_BASE::sse_movlpd_r128_m64, false}, - { 0x13, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movlpd_m64_r128, &I386_OPS_BASE::sse_movlpd_m64_r128, false}, - { 0x14, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_unpcklpd_r128_rm128, &I386_OPS_BASE::sse_unpcklpd_r128_rm128, false}, - { 0x15, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_unpckhpd_r128_rm128, &I386_OPS_BASE::sse_unpckhpd_r128_rm128, false}, - { 0x16, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movhpd_r128_m64, &I386_OPS_BASE::sse_movhpd_r128_m64, false}, - { 0x17, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movhpd_m64_r128, &I386_OPS_BASE::sse_movhpd_m64_r128, false}, - { 0x28, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movapd_r128_rm128, &I386_OPS_BASE::sse_movapd_r128_rm128, false}, - { 0x29, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movapd_rm128_r128, &I386_OPS_BASE::sse_movapd_rm128_r128, false}, - { 0x2A, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_cvtpi2pd_r128_rm64, &I386_OPS_BASE::sse_cvtpi2pd_r128_rm64, false}, - { 0x2B, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movntpd_m128_r128, &I386_OPS_BASE::sse_movntpd_m128_r128, false}, - { 0x2C, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_cvttpd2pi_r64_rm128, &I386_OPS_BASE::sse_cvttpd2pi_r64_rm128, false}, - { 0x2D, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_cvtpd2pi_r64_rm128, &I386_OPS_BASE::sse_cvtpd2pi_r64_rm128, false}, - { 0x2E, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_ucomisd_r128_r128m64, &I386_OPS_BASE::sse_ucomisd_r128_r128m64,false}, - { 0x2F, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_comisd_r128_r128m64, &I386_OPS_BASE::sse_comisd_r128_r128m64, false}, - { 0x50, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movmskpd_r32_r128, &I386_OPS_BASE::sse_movmskpd_r32_r128, false}, - { 0x51, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_sqrtpd_r128_rm128, &I386_OPS_BASE::sse_sqrtpd_r128_rm128, false}, - { 0x54, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_andpd_r128_rm128, &I386_OPS_BASE::sse_andpd_r128_rm128, false}, - { 0x55, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_andnpd_r128_rm128, &I386_OPS_BASE::sse_andnpd_r128_rm128, false}, - { 0x56, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_orpd_r128_rm128, &I386_OPS_BASE::sse_orpd_r128_rm128, false}, - { 0x57, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_xorpd_r128_rm128, &I386_OPS_BASE::sse_xorpd_r128_rm128, false}, - { 0x58, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_addpd_r128_rm128, &I386_OPS_BASE::sse_addpd_r128_rm128, false}, - { 0x59, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_mulpd_r128_rm128, &I386_OPS_BASE::sse_mulpd_r128_rm128, false}, - { 0x5A, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_cvtpd2ps_r128_rm128, &I386_OPS_BASE::sse_cvtpd2ps_r128_rm128, false}, - { 0x5B, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_cvtps2dq_r128_rm128, &I386_OPS_BASE::sse_cvtps2dq_r128_rm128, false}, - { 0x5C, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_subpd_r128_rm128, &I386_OPS_BASE::sse_subpd_r128_rm128, false}, - { 0x5D, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_minpd_r128_rm128, &I386_OPS_BASE::sse_minpd_r128_rm128, false}, - { 0x5E, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_divpd_r128_rm128, &I386_OPS_BASE::sse_divpd_r128_rm128, false}, - { 0x5F, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_maxpd_r128_rm128, &I386_OPS_BASE::sse_maxpd_r128_rm128, false}, - { 0x60, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_punpcklbw_r128_rm128, &I386_OPS_BASE::sse_punpcklbw_r128_rm128,false}, - { 0x61, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_punpcklwd_r128_rm128, &I386_OPS_BASE::sse_punpcklwd_r128_rm128,false}, - { 0x62, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_punpckldq_r128_rm128, &I386_OPS_BASE::sse_punpckldq_r128_rm128,false}, - { 0x63, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_packsswb_r128_rm128, &I386_OPS_BASE::sse_packsswb_r128_rm128, false}, - { 0x64, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pcmpgtb_r128_rm128, &I386_OPS_BASE::sse_pcmpgtb_r128_rm128, false}, - { 0x65, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pcmpgtw_r128_rm128, &I386_OPS_BASE::sse_pcmpgtw_r128_rm128, false}, - { 0x66, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pcmpgtd_r128_rm128, &I386_OPS_BASE::sse_pcmpgtd_r128_rm128, false}, - { 0x67, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_packuswb_r128_rm128, &I386_OPS_BASE::sse_packuswb_r128_rm128, false}, - { 0x68, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_punpckhbw_r128_rm128, &I386_OPS_BASE::sse_punpckhbw_r128_rm128,false}, - { 0x69, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_punpckhwd_r128_rm128, &I386_OPS_BASE::sse_punpckhwd_r128_rm128,false}, - { 0x6A, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_unpckhdq_r128_rm128, &I386_OPS_BASE::sse_unpckhdq_r128_rm128, false}, - { 0x6B, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_packssdw_r128_rm128, &I386_OPS_BASE::sse_packssdw_r128_rm128, false}, - { 0x6C, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_punpcklqdq_r128_rm128, &I386_OPS_BASE::sse_punpcklqdq_r128_rm128,false}, - { 0x6D, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_punpckhqdq_r128_rm128, &I386_OPS_BASE::sse_punpckhqdq_r128_rm128,false}, - { 0x6E, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movd_m128_rm32, &I386_OPS_BASE::sse_movd_m128_rm32, false}, - { 0x6F, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movdqa_m128_rm128, &I386_OPS_BASE::sse_movdqa_m128_rm128, false}, - { 0x70, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pshufd_r128_rm128_i8, &I386_OPS_BASE::sse_pshufd_r128_rm128_i8,false}, - { 0x71, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_group_660f71, &I386_OPS_BASE::sse_group_660f71, false}, - { 0x72, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_group_660f72, &I386_OPS_BASE::sse_group_660f72, false}, - { 0x73, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_group_660f73, &I386_OPS_BASE::sse_group_660f73, false}, - { 0x74, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pcmpeqb_r128_rm128, &I386_OPS_BASE::sse_pcmpeqb_r128_rm128, false}, - { 0x75, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pcmpeqw_r128_rm128, &I386_OPS_BASE::sse_pcmpeqw_r128_rm128, false}, - { 0x76, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pcmpeqd_r128_rm128, &I386_OPS_BASE::sse_pcmpeqd_r128_rm128, false}, - { 0x7C, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_haddpd_r128_rm128, &I386_OPS_BASE::sse_haddpd_r128_rm128, false}, - { 0x7D, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_hsubpd_r128_rm128, &I386_OPS_BASE::sse_hsubpd_r128_rm128, false}, - { 0x7E, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movd_rm32_r128, &I386_OPS_BASE::sse_movd_rm32_r128, false}, - { 0x7F, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movdqa_rm128_r128, &I386_OPS_BASE::sse_movdqa_rm128_r128, false}, - { 0xC2, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_cmppd_r128_rm128_i8, &I386_OPS_BASE::sse_cmppd_r128_rm128_i8, false}, - { 0xC4, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pinsrw_r128_r32m16_i8, &I386_OPS_BASE::sse_pinsrw_r128_r32m16_i8,false}, - { 0xC5, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pextrw_reg_r128_i8, &I386_OPS_BASE::sse_pextrw_reg_r128_i8, false}, - { 0xC6, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_shufpd_r128_rm128_i8, &I386_OPS_BASE::sse_shufpd_r128_rm128_i8,false}, - { 0xC7, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xD0, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_addsubpd_r128_rm128, &I386_OPS_BASE::sse_addsubpd_r128_rm128, false}, - { 0xD1, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psrlw_r128_rm128, &I386_OPS_BASE::sse_psrlw_r128_rm128, false}, - { 0xD2, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psrld_r128_rm128, &I386_OPS_BASE::sse_psrld_r128_rm128, false}, - { 0xD3, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psrlq_r128_rm128, &I386_OPS_BASE::sse_psrlq_r128_rm128, false}, - { 0xD4, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddq_r128_rm128, &I386_OPS_BASE::sse_paddq_r128_rm128, false}, - { 0xD5, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pmullw_r128_rm128, &I386_OPS_BASE::sse_pmullw_r128_rm128, false}, - { 0xD6, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movq_r128m64_r128, &I386_OPS_BASE::sse_movq_r128m64_r128, false}, - { 0xD7, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pmovmskb_r32_r128, &I386_OPS_BASE::sse_pmovmskb_r32_r128, false}, - { 0xD8, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubusb_r128_rm128, &I386_OPS_BASE::sse_psubusb_r128_rm128, false}, - { 0xD9, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubusw_r128_rm128, &I386_OPS_BASE::sse_psubusw_r128_rm128, false}, - { 0xDA, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pminub_r128_rm128, &I386_OPS_BASE::sse_pminub_r128_rm128, false}, - { 0xDB, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pand_r128_rm128, &I386_OPS_BASE::sse_pand_r128_rm128, false}, - { 0xDC, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddusb_r128_rm128, &I386_OPS_BASE::sse_paddusb_r128_rm128, false}, - { 0xDD, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddusw_r128_rm128, &I386_OPS_BASE::sse_paddusw_r128_rm128, false}, - { 0xDE, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pmaxub_r128_rm128, &I386_OPS_BASE::sse_pmaxub_r128_rm128, false}, - { 0xDF, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pandn_r128_rm128, &I386_OPS_BASE::sse_pandn_r128_rm128, false}, - { 0xE0, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pavgb_r128_rm128, &I386_OPS_BASE::sse_pavgb_r128_rm128, false}, - { 0xE1, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psraw_r128_rm128, &I386_OPS_BASE::sse_psraw_r128_rm128, false}, - { 0xE2, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psrad_r128_rm128, &I386_OPS_BASE::sse_psrad_r128_rm128, false}, - { 0xE3, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pavgw_r128_rm128, &I386_OPS_BASE::sse_pavgw_r128_rm128, false}, - { 0xE4, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pmulhuw_r128_rm128, &I386_OPS_BASE::sse_pmulhuw_r128_rm128, false}, - { 0xE5, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pmulhw_r128_rm128, &I386_OPS_BASE::sse_pmulhw_r128_rm128, false}, - { 0xE6, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_cvttpd2dq_r128_rm128, &I386_OPS_BASE::sse_cvttpd2dq_r128_rm128,false}, - { 0xE7, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_movntdq_m128_r128, &I386_OPS_BASE::sse_movntdq_m128_r128, false}, - { 0xE8, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubsb_r128_rm128, &I386_OPS_BASE::sse_psubsb_r128_rm128, false}, - { 0xE9, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubsw_r128_rm128, &I386_OPS_BASE::sse_psubsw_r128_rm128, false}, - { 0xEA, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pminsw_r128_rm128, &I386_OPS_BASE::sse_pminsw_r128_rm128, false}, - { 0xEB, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_por_r128_rm128, &I386_OPS_BASE::sse_por_r128_rm128, false}, - { 0xEC, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddsb_r128_rm128, &I386_OPS_BASE::sse_paddsb_r128_rm128, false}, - { 0xED, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddsw_r128_rm128, &I386_OPS_BASE::sse_paddsw_r128_rm128, false}, - { 0xEE, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_pmaxsw_r128_rm128, &I386_OPS_BASE::sse_pmaxsw_r128_rm128, false}, - { 0xEF, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pxor_r128_rm128, &I386_OPS_BASE::sse_pxor_r128_rm128, false}, - { 0xF1, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psllw_r128_rm128, &I386_OPS_BASE::sse_psllw_r128_rm128, false}, - { 0xF2, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pslld_r128_rm128, &I386_OPS_BASE::sse_pslld_r128_rm128, false}, - { 0xF3, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psllq_r128_rm128, &I386_OPS_BASE::sse_psllq_r128_rm128, false}, - { 0xF4, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pmuludq_r128_rm128, &I386_OPS_BASE::sse_pmuludq_r128_rm128, false}, - { 0xF5, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_pmaddwd_r128_rm128, &I386_OPS_BASE::sse_pmaddwd_r128_rm128, false}, - { 0xF6, OP_3BYTE66|OP_SSE, &I386_OPS_BASE::sse_psadbw_r128_rm128, &I386_OPS_BASE::sse_psadbw_r128_rm128, false}, - { 0xF7, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_maskmovdqu_r128_r128, &I386_OPS_BASE::sse_maskmovdqu_r128_r128,false}, - { 0xF8, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubb_r128_rm128, &I386_OPS_BASE::sse_psubb_r128_rm128, false}, - { 0xF9, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubw_r128_rm128, &I386_OPS_BASE::sse_psubw_r128_rm128, false}, - { 0xFA, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubd_r128_rm128, &I386_OPS_BASE::sse_psubd_r128_rm128, false}, - { 0xFB, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_psubq_r128_rm128, &I386_OPS_BASE::sse_psubq_r128_rm128, false}, - { 0xFC, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddb_r128_rm128, &I386_OPS_BASE::sse_paddb_r128_rm128, false}, - { 0xFD, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddw_r128_rm128, &I386_OPS_BASE::sse_paddw_r128_rm128, false}, - { 0xFE, OP_3BYTE66|OP_SSE2, &I386_OPS_BASE::sse_paddd_r128_rm128, &I386_OPS_BASE::sse_paddd_r128_rm128, false}, - /* 0F 38 ?? */ - { 0x00, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x01, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x02, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x03, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x04, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x05, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x06, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x07, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x08, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x09, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0A, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0B, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1C, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1D, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1E, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF0, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF1, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF2, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF3, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF5, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF7, OP_3BYTE38|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - /* 0F 3A ?? */ - { 0x0F, OP_3BYTE3A|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - /* 66 0F 38 ?? */ - { 0x00, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x01, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x02, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x03, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x04, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x05, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x06, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x07, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x08, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x09, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0A, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0B, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0C, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0D, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0E, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0F, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x10, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x13, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x14, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x15, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x16, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x17, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x18, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x19, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1A, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1C, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1D, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1E, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x20, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x21, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x22, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x23, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x24, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x25, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x28, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x29, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x2A, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x2B, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x2C, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x2D, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x2E, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x2F, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x30, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x31, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x32, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x33, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x34, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x35, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x36, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x37, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x38, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x39, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x3A, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x3B, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x3C, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x3D, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x3E, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x3F, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x40, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x41, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x45, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x46, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x47, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x58, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x59, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x5A, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x78, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x79, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x80, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x81, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x82, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x8C, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x8E, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x90, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x91, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x92, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x93, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x96, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x97, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x98, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x99, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x9A, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x9B, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x9C, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x9D, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x9E, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x9F, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xA6, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xA7, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xA8, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xA9, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xAA, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xAB, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xAC, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xAD, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xAE, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xAF, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xB6, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xB7, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xB8, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xB9, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xBA, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xBB, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xBC, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xBD, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xBE, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xBF, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xDB, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xDC, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xDD, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xDE, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xDF, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF0, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF1, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF3, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF6, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF7, OP_4BYTE3866|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - /* F2 0F 38 ?? */ - { 0xF0, OP_4BYTE38F2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF1, OP_4BYTE38F2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF3, OP_4BYTE38F2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF5, OP_4BYTE38F2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF6, OP_4BYTE38F2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF7, OP_4BYTE38F2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - /* F3 0F 38 ?? */ - { 0xF3, OP_4BYTE38F3|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF5, OP_4BYTE38F3|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF6, OP_4BYTE38F3|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xF7, OP_4BYTE38F3|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - /* 66 0F 3A ?? */ - { 0x00, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x01, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x02, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x04, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x05, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x06, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x08, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x09, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0A, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0B, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0C, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0D, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0E, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x0F, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x14, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x15, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x16, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x17, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x18, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x19, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x1D, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x20, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x21, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x22, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x38, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x39, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x40, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x41, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x42, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x44, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x46, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x4A, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x4B, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x4C, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x60, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x61, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x62, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0x63, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - { 0xDF, OP_4BYTE3A66|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false}, - /* F2 0F 3A ?? */ - { 0xF0, OP_4BYTE3AF2|OP_SSE, &I386_OPS_BASE::i386_invalid, &I386_OPS_BASE::i386_invalid, false} -}; -#endif diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386_real.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386_real.cpp deleted file mode 100644 index 4e56ca21f..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386_real.cpp +++ /dev/null @@ -1,836 +0,0 @@ - -#include "../vm.h" -#include "../debugger.h" -#include "../../emu.h" -#include "./i386_real.h" -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} -extern "C" { - #include "../libcpu_softfloat/softfloat.h" -}; - -int I386_OPS::cpu_translate_i386(void *cpudevice, address_spacenum space, int intention, offs_t *address) -{ - i386_state *cpu_state = (i386_state *)cpudevice; - int ret = TRUE; - if(space == AS_PROGRAM) - ret = i386_translate_address(intention, address, NULL); - *address &= cpu_state->a20_mask; - return ret; -} - -i386_state *I386_OPS::i386_common_init(int tlbsize) -{ - int i, j; - static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH}; - static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI}; - static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI}; - cpustate = &__cpustate; - //cpustate = (i386_state *)malloc(sizeof(i386_state)); - //x86_cycle_table = _x86_cycle_table_real; - - assert((sizeof(XMM_REG)/sizeof(double)) == 2); - - build_cycle_table(); - - for( i=0; i < 256; i++ ) { - int c=0; - for( j=0; j < 8; j++ ) { - if( i & (1 << j) ) - c++; - } - i386_parity_table[i] = ~(c & 0x1) & 0x1; - } - - for( i=0; i < 256; i++ ) { - i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7]; - i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7]; - i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7]; - - i386_MODRM_table[i].rm.b = regs8[i & 0x7]; - i386_MODRM_table[i].rm.w = regs16[i & 0x7]; - i386_MODRM_table[i].rm.d = regs32[i & 0x7]; - } - - cpustate->vtlb = vtlb_alloc((void *)cpustate, AS_PROGRAM, 0, tlbsize); - cpustate->smi = false; - cpustate->lock = false; - -// i386_interface *intf = (i386_interface *) device->static_config(); -// -// if (intf != NULL) -// cpustate->smiact.resolve(intf->smiact, *device); -// else -// memset(&cpustate->smiact, 0, sizeof(cpustate->smiact)); - - zero_state(); - cpustate->program = d_mem; - cpustate->io = d_io; - cpustate->pic = d_pic; -#ifdef I386_PSEUDO_BIOS - cpustate->bios = d_bios; -#endif -#ifdef SINGLE_MODE_DMA - cpustate->dma = d_dma; -#endif - return cpustate; -} - -void I386_OPS::i386_decode_opcode() -{ - cpustate->opcode = FETCH(); - - if(cpustate->lock && !cpustate->lock_table[0][cpustate->opcode]) - return I386OP(invalid)(); - - if( cpustate->operand_size ) - (this->*cpustate->opcode_table1_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table1_16[cpustate->opcode])(); -} - - -int I386_OPS::cpu_execute_i386(int cycles) -{ - CHANGE_PC(cpustate->eip); - - if (cpustate->halted || cpustate->busreq) - { -#ifdef SINGLE_MODE_DMA - if(cpustate->dma != NULL) { - cpustate->dma->do_dma(); - } -#endif - if (cycles == -1) { - int passed_cycles = max(1, cpustate->extra_cycles); - // this is main cpu, cpustate->cycles is not used - /*cpustate->cycles = */cpustate->extra_cycles = 0; - cpustate->tsc += passed_cycles; - return passed_cycles; - } else { - cpustate->cycles += cycles; - cpustate->base_cycles = cpustate->cycles; - - /* adjust for any interrupts that came in */ - cpustate->cycles -= cpustate->extra_cycles; - cpustate->extra_cycles = 0; - - /* if busreq is raised, spin cpu while remained clock */ - if (cpustate->cycles > 0) { - cpustate->cycles = 0; - } - int passed_cycles = cpustate->base_cycles - cpustate->cycles; - cpustate->tsc += passed_cycles; - return passed_cycles; - } - } - - if (cycles == -1) { - cpustate->cycles = 1; - } else { - cpustate->cycles += cycles; - } - cpustate->base_cycles = cpustate->cycles; - - /* adjust for any interrupts that came in */ - cpustate->cycles -= cpustate->extra_cycles; - cpustate->extra_cycles = 0; - - while( cpustate->cycles > 0 && !cpustate->busreq ) - { -#ifdef USE_DEBUGGER - bool now_debugging = cpustate->debugger->now_debugging; - if(now_debugging) { - cpustate->debugger->check_break_points(cpustate->pc); - if(cpustate->debugger->now_suspended) { - cpustate->debugger->now_waiting = true; - cpustate->emu->start_waiting_in_debugger(); - while(cpustate->debugger->now_debugging && cpustate->debugger->now_suspended) { - cpustate->emu->process_waiting_in_debugger(); - } - cpustate->emu->finish_waiting_in_debugger(); - cpustate->debugger->now_waiting = false; - } - if(cpustate->debugger->now_debugging) { - cpustate->program = cpustate->io = cpustate->debugger; - } else { - now_debugging = false; - } - i386_check_irq_line(); - cpustate->operand_size = cpustate->sreg[CS].d; - cpustate->xmm_operand_size = 0; - cpustate->address_size = cpustate->sreg[CS].d; - cpustate->operand_prefix = 0; - cpustate->address_prefix = 0; - - cpustate->ext = 1; - int old_tf = cpustate->TF; - - cpustate->segment_prefix = 0; - cpustate->prev_eip = cpustate->eip; - cpustate->prev_pc = cpustate->pc; - - if(cpustate->delayed_interrupt_enable != 0) - { - cpustate->IF = 1; - cpustate->delayed_interrupt_enable = 0; - } -#ifdef DEBUG_MISSING_OPCODE - cpustate->opcode_bytes_length = 0; - cpustate->opcode_pc = cpustate->pc; -#endif - try - { - i386_decode_opcode(); - if(cpustate->TF && old_tf) - { - cpustate->prev_eip = cpustate->eip; - cpustate->ext = 1; - i386_trap(1,0,0); - } - if(cpustate->lock && (cpustate->opcode != 0xf0)) - cpustate->lock = false; - } - catch(UINT64 e) - { - cpustate->ext = 1; - i386_trap_with_error(e&0xffffffff,0,0,e>>32); - } -#ifdef SINGLE_MODE_DMA - if(cpustate->dma != NULL) { - cpustate->dma->do_dma(); - } -#endif - /* adjust for any interrupts that came in */ - cpustate->cycles -= cpustate->extra_cycles; - cpustate->extra_cycles = 0; - - if(now_debugging) { - if(!cpustate->debugger->now_going) { - cpustate->debugger->now_suspended = true; - } - cpustate->program = cpustate->program_stored; - cpustate->io = cpustate->io_stored; - } - } else { -#endif - i386_check_irq_line(); - - cpustate->operand_size = cpustate->sreg[CS].d; - cpustate->xmm_operand_size = 0; - cpustate->address_size = cpustate->sreg[CS].d; - cpustate->operand_prefix = 0; - cpustate->address_prefix = 0; - - cpustate->ext = 1; - int old_tf = cpustate->TF; - - cpustate->segment_prefix = 0; - cpustate->prev_eip = cpustate->eip; - cpustate->prev_pc = cpustate->pc; - - if(cpustate->delayed_interrupt_enable != 0) - { - cpustate->IF = 1; - cpustate->delayed_interrupt_enable = 0; - } -#ifdef DEBUG_MISSING_OPCODE - cpustate->opcode_bytes_length = 0; - cpustate->opcode_pc = cpustate->pc; -#endif - try - { - i386_decode_opcode(); - if(cpustate->TF && old_tf) - { - cpustate->prev_eip = cpustate->eip; - cpustate->ext = 1; - i386_trap(1,0,0); - } - if(cpustate->lock && (cpustate->opcode != 0xf0)) - cpustate->lock = false; - } - catch(UINT64 e) - { - cpustate->ext = 1; - i386_trap_with_error(e&0xffffffff,0,0,e>>32); - } -#ifdef SINGLE_MODE_DMA - if(cpustate->dma != NULL) { - cpustate->dma->do_dma(); - } -#endif - /* adjust for any interrupts that came in */ - cpustate->cycles -= cpustate->extra_cycles; - cpustate->extra_cycles = 0; -#ifdef USE_DEBUGGER - } -#endif - } - - /* if busreq is raised, spin cpu while remained clock */ - if (cpustate->cycles > 0 && cpustate->busreq) { - cpustate->cycles = 0; - } - int passed_cycles = cpustate->base_cycles - cpustate->cycles; - cpustate->tsc += passed_cycles; - return passed_cycles; -} - -void I386_OPS::i386_trap(int irq, int irq_gate, int trap_level) -{ - /* I386 Interrupts/Traps/Faults: - * - * 0x00 Divide by zero - * 0x01 Debug exception - * 0x02 NMI - * 0x03 Int3 - * 0x04 Overflow - * 0x05 Array bounds check - * 0x06 Illegal Opcode - * 0x07 FPU not available - * 0x08 Double fault - * 0x09 Coprocessor segment overrun - * 0x0a Invalid task state - * 0x0b Segment not present - * 0x0c Stack exception - * 0x0d General Protection Fault - * 0x0e Page fault - * 0x0f Reserved - * 0x10 Coprocessor error - */ - UINT32 v1, v2; - UINT32 offset, oldflags = get_flags(); - UINT16 segment; - int entry = irq * (PROTECTED_MODE ? 8 : 4); - int SetRPL = 0; - cpustate->lock = false; - - if( !(PROTECTED_MODE) ) - { - /* 16-bit */ - PUSH16(oldflags & 0xffff ); - PUSH16(cpustate->sreg[CS].selector ); - if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1) - PUSH16(cpustate->eip ); - else - PUSH16(cpustate->prev_eip ); - - cpustate->sreg[CS].selector = READ16(cpustate->idtr.base + entry + 2 ); - cpustate->eip = READ16(cpustate->idtr.base + entry ); - - cpustate->TF = 0; - cpustate->IF = 0; - } - else - { - int type; - UINT16 flags; - I386_SREG desc; - UINT8 CPL = cpustate->CPL, DPL = 0; //, RPL = 0; - - /* 32-bit */ - v1 = READ32PL0(cpustate->idtr.base + entry ); - v2 = READ32PL0(cpustate->idtr.base + entry + 4 ); - offset = (v2 & 0xffff0000) | (v1 & 0xffff); - segment = (v1 >> 16) & 0xffff; - type = (v2>>8) & 0x1F; - flags = (v2>>8) & 0xf0ff; - - if(trap_level == 2) - { - logerror("IRQ: Double fault.\n"); - FAULT_EXP(FAULT_DF,0); - } - if(trap_level >= 3) - { - logerror("IRQ: Triple fault. CPU reset.\n"); -#if defined(HAS_I386) - cpu_reset_i386(); -#elif defined(HAS_I486) - cpu_reset_i486(); -#elif defined(HAS_PENTIUM) - cpu_reset_pentium(); -#elif defined(HAS_MEDIAGX) - cpu_reset_mediagx(); -#elif defined(HAS_PENTIUM_PRO) - cpu_reset_pentium_pro(); -#elif defined(HAS_PENTIUM_MMX) - cpu_reset_pentium_mmx(); -#elif defined(HAS_PENTIUM2) - cpu_reset_pentium2(); -#elif defined(HAS_PENTIUM3) - cpu_reset_pentium3(); -#elif defined(HAS_PENTIUM4) - cpu_reset_pentium4(); -#endif - - cpustate->shutdown = 1; - return; - } - - /* segment privilege checks */ - if(entry >= cpustate->idtr.limit) - { - logerror("IRQ (%08x): Vector %02xh is past IDT limit.\n",cpustate->pc,entry); - FAULT_EXP(FAULT_GP,entry+2) - } - /* segment must be interrupt gate, trap gate, or task gate */ - if(type != 0x05 && type != 0x06 && type != 0x07 && type != 0x0e && type != 0x0f) - { - logerror("IRQ#%02x (%08x): Vector segment %04x is not an interrupt, trap or task gate.\n",irq,cpustate->pc,segment); - FAULT_EXP(FAULT_GP,entry+2) - } - - if(cpustate->ext == 0) // if software interrupt (caused by INT/INTO/INT3) - { - if(((flags >> 5) & 0x03) < CPL) - { - logerror("IRQ (%08x): Software IRQ - gate DPL is less than CPL.\n",cpustate->pc); - FAULT_EXP(FAULT_GP,entry+2) - } - if(V8086_MODE) - { - if((!cpustate->IOP1 || !cpustate->IOP2) && (cpustate->opcode != 0xcc)) - { - logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc); - FAULT(FAULT_GP,0) - } - - } - } - - if((flags & 0x0080) == 0) - { - logerror("IRQ: Vector segment is not present.\n"); - FAULT_EXP(FAULT_NP,entry+2) - } - - if(type == 0x05) - { - /* Task gate */ - memset(&desc, 0, sizeof(desc)); - desc.selector = segment; - i386_load_protected_mode_segment(&desc,NULL); - if(segment & 0x04) - { - logerror("IRQ: Task gate: TSS is not in the GDT.\n"); - FAULT_EXP(FAULT_TS,segment & ~0x03); - } - else - { - if(segment > cpustate->gdtr.limit) - { - logerror("IRQ: Task gate: TSS is past GDT limit.\n"); - FAULT_EXP(FAULT_TS,segment & ~0x03); - } - } - if((desc.flags & 0x000f) != 0x09 && (desc.flags & 0x000f) != 0x01) - { - logerror("IRQ: Task gate: TSS is not an available TSS.\n"); - FAULT_EXP(FAULT_TS,segment & ~0x03); - } - if((desc.flags & 0x0080) == 0) - { - logerror("IRQ: Task gate: TSS is not present.\n"); - FAULT_EXP(FAULT_NP,segment & ~0x03); - } - if(!(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)) - cpustate->eip = cpustate->prev_eip; - if(desc.flags & 0x08) - i386_task_switch(desc.selector,1); - else - i286_task_switch(desc.selector,1); - return; - } - else - { - /* Interrupt or Trap gate */ - memset(&desc, 0, sizeof(desc)); - desc.selector = segment; - i386_load_protected_mode_segment(&desc,NULL); - CPL = cpustate->CPL; // current privilege level - DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level -// RPL = segment & 0x03; // requested privilege level - - if((segment & ~0x03) == 0) - { - logerror("IRQ: Gate segment is null.\n"); - FAULT_EXP(FAULT_GP,cpustate->ext) - } - if(segment & 0x04) - { - if((segment & ~0x07) > cpustate->ldtr.limit) - { - logerror("IRQ: Gate segment is past LDT limit.\n"); - FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) - } - } - else - { - if((segment & ~0x07) > cpustate->gdtr.limit) - { - logerror("IRQ: Gate segment is past GDT limit.\n"); - FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) - } - } - if((desc.flags & 0x0018) != 0x18) - { - logerror("IRQ: Gate descriptor is not a code segment.\n"); - FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext) - } - if((desc.flags & 0x0080) == 0) - { - logerror("IRQ: Gate segment is not present.\n"); - FAULT_EXP(FAULT_NP,(segment & 0x03)+cpustate->ext) - } - if((desc.flags & 0x0004) == 0 && (DPL < CPL)) - { - /* IRQ to inner privilege */ - I386_SREG stack; - UINT32 newESP,oldSS,oldESP; - - if(V8086_MODE && DPL) - { - logerror("IRQ: Gate to CPL>0 from VM86 mode.\n"); - FAULT_EXP(FAULT_GP,segment & ~0x03); - } - /* Check new stack segment in TSS */ - memset(&stack, 0, sizeof(stack)); - stack.selector = i386_get_stack_segment(DPL); - i386_load_protected_mode_segment(&stack,NULL); - oldSS = cpustate->sreg[SS].selector; - if(flags & 0x0008) - oldESP = REG32(ESP); - else - oldESP = REG16(SP); - if((stack.selector & ~0x03) == 0) - { - logerror("IRQ: New stack selector is null.\n"); - FAULT_EXP(FAULT_GP,cpustate->ext) - } - if(stack.selector & 0x04) - { - if((stack.selector & ~0x07) > cpustate->ldtr.base) - { - logerror("IRQ: New stack selector is past LDT limit.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - } - else - { - if((stack.selector & ~0x07) > cpustate->gdtr.base) - { - logerror("IRQ: New stack selector is past GDT limit.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - } - if((stack.selector & 0x03) != DPL) - { - logerror("IRQ: New stack selector RPL is not equal to code segment DPL.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - if(((stack.flags >> 5) & 0x03) != DPL) - { - logerror("IRQ: New stack segment DPL is not equal to code segment DPL.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) - } - if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0) - { - logerror("IRQ: New stack segment is not a writable data segment.\n"); - FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT) - } - if((stack.flags & 0x0080) == 0) - { - logerror("IRQ: New stack segment is not present.\n"); - FAULT_EXP(FAULT_SS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT) - } - newESP = i386_get_stack_ptr(DPL); - if(type & 0x08) // 32-bit gate - { - if(((newESP < (V8086_MODE?36:20)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?36:20))) && (stack.flags & 0x4))) - { - logerror("IRQ: New stack has no space for return addresses.\n"); - FAULT_EXP(FAULT_SS,0) - } - } - else // 16-bit gate - { - newESP &= 0xffff; - if(((newESP < (V8086_MODE?18:10)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?18:10))) && (stack.flags & 0x4))) - { - logerror("IRQ: New stack has no space for return addresses.\n"); - FAULT_EXP(FAULT_SS,0) - } - } - if(offset > desc.limit) - { - logerror("IRQ: New EIP is past code segment limit.\n"); - FAULT_EXP(FAULT_GP,0) - } - /* change CPL before accessing the stack */ - cpustate->CPL = DPL; - /* check for page fault at new stack TODO: check if stack frame crosses page boundary */ - WRITE_TEST(stack.base+newESP-1); - /* Load new stack segment descriptor */ - cpustate->sreg[SS].selector = stack.selector; - i386_load_protected_mode_segment(&cpustate->sreg[SS],NULL); - i386_set_descriptor_accessed(stack.selector); - REG32(ESP) = newESP; - if(V8086_MODE) - { - //logerror("IRQ (%08x): Interrupt during V8086 task\n",cpustate->pc); - if(type & 0x08) - { - PUSH32(cpustate->sreg[GS].selector & 0xffff); - PUSH32(cpustate->sreg[FS].selector & 0xffff); - PUSH32(cpustate->sreg[DS].selector & 0xffff); - PUSH32(cpustate->sreg[ES].selector & 0xffff); - } - else - { - PUSH16(cpustate->sreg[GS].selector); - PUSH16(cpustate->sreg[FS].selector); - PUSH16(cpustate->sreg[DS].selector); - PUSH16(cpustate->sreg[ES].selector); - } - cpustate->sreg[GS].selector = 0; - cpustate->sreg[FS].selector = 0; - cpustate->sreg[DS].selector = 0; - cpustate->sreg[ES].selector = 0; - cpustate->VM = 0; - i386_load_segment_descriptor(GS); - i386_load_segment_descriptor(FS); - i386_load_segment_descriptor(DS); - i386_load_segment_descriptor(ES); - } - if(type & 0x08) - { - // 32-bit gate - PUSH32(oldSS); - PUSH32(oldESP); - } - else - { - // 16-bit gate - PUSH16(oldSS); - PUSH16(oldESP); - } - SetRPL = 1; - } - else - { - int stack_limit; - if((desc.flags & 0x0004) || (DPL == CPL)) - { - /* IRQ to same privilege */ - if(V8086_MODE && !cpustate->ext) - { - logerror("IRQ: Gate to same privilege from VM86 mode.\n"); - FAULT_EXP(FAULT_GP,segment & ~0x03); - } - if(type == 0x0e || type == 0x0f) // 32-bit gate - stack_limit = 10; - else - stack_limit = 6; - // TODO: Add check for error code (2 extra bytes) - if(REG32(ESP) < stack_limit) - { - logerror("IRQ: Stack has no space left (needs %i bytes).\n",stack_limit); - FAULT_EXP(FAULT_SS,0) - } - if(offset > desc.limit) - { - logerror("IRQ: Gate segment offset is past segment limit.\n"); - FAULT_EXP(FAULT_GP,0) - } - SetRPL = 1; - } - else - { - logerror("IRQ: Gate descriptor is non-conforming, and DPL does not equal CPL.\n"); - FAULT_EXP(FAULT_GP,segment) - } - } - } - UINT32 tempSP = REG32(ESP); - try - { - // this is ugly but the alternative is worse - if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate - { - PUSH16(oldflags & 0xffff ); - PUSH16(cpustate->sreg[CS].selector ); - if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1) - PUSH16(cpustate->eip ); - else - PUSH16(cpustate->prev_eip ); - } - else - { - PUSH32(oldflags & 0x00ffffff ); - PUSH32(cpustate->sreg[CS].selector ); - if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1) - PUSH32(cpustate->eip ); - else - PUSH32(cpustate->prev_eip ); - } - } - catch(UINT64 e) - { - REG32(ESP) = tempSP; - throw e; - } - if(SetRPL != 0) - segment = (segment & ~0x03) | cpustate->CPL; - cpustate->sreg[CS].selector = segment; - cpustate->eip = offset; - - if(type == 0x0e || type == 0x06) - cpustate->IF = 0; - cpustate->TF = 0; - cpustate->NT = 0; - } - - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); - -} - -void I386_OPS::i386_trap_with_error(int irq, int irq_gate, int trap_level, UINT32 error) -{ - i386_trap(irq,irq_gate,trap_level); - if(irq == 8 || irq == 10 || irq == 11 || irq == 12 || irq == 13 || irq == 14) - { - // for these exceptions, an error code is pushed onto the stack by the processor. - // no error code is pushed for software interrupts, either. - if(PROTECTED_MODE) - { - UINT32 entry = irq * 8; - UINT32 v2,type; - v2 = READ32PL0(cpustate->idtr.base + entry + 4 ); - type = (v2>>8) & 0x1F; - if(type == 5) - { - v2 = READ32PL0(cpustate->idtr.base + entry); - v2 = READ32PL0(cpustate->gdtr.base + ((v2 >> 16) & 0xfff8) + 4); - type = (v2>>8) & 0x1F; - } - if(type >= 9) - PUSH32(error); - else - PUSH16(error); - } - else - PUSH16(error); - } -} - -bool I386_OPS::write_debug_reg(const _TCHAR *reg, uint32_t data) -{ -#if defined(USE_DEBUGGER) - if(_tcsicmp(reg, _T("IP")) == 0) { - cpustate->eip = data & 0xffff; - CHANGE_PC(cpustate->eip); - } else if(_tcsicmp(reg, _T("AX")) == 0) { - REG16(AX) = data; - } else if(_tcsicmp(reg, _T("BX")) == 0) { - REG16(BX) = data; - } else if(_tcsicmp(reg, _T("CX")) == 0) { - REG16(CX) = data; - } else if(_tcsicmp(reg, _T("DX")) == 0) { - REG16(DX) = data; - } else if(_tcsicmp(reg, _T("SP")) == 0) { - REG16(SP) = data; - } else if(_tcsicmp(reg, _T("BP")) == 0) { - REG16(BP) = data; - } else if(_tcsicmp(reg, _T("SI")) == 0) { - REG16(SI) = data; - } else if(_tcsicmp(reg, _T("DI")) == 0) { - REG16(DI) = data; - } else if(_tcsicmp(reg, _T("AL")) == 0) { - REG8(AL) = data; - } else if(_tcsicmp(reg, _T("AH")) == 0) { - REG8(AH) = data; - } else if(_tcsicmp(reg, _T("BL")) == 0) { - REG8(BL) = data; - } else if(_tcsicmp(reg, _T("BH")) == 0) { - REG8(BH) = data; - } else if(_tcsicmp(reg, _T("CL")) == 0) { - REG8(CL) = data; - } else if(_tcsicmp(reg, _T("CH")) == 0) { - REG8(CH) = data; - } else if(_tcsicmp(reg, _T("DL")) == 0) { - REG8(DL) = data; - } else if(_tcsicmp(reg, _T("DH")) == 0) { - REG8(DH) = data; - } else { - return false; - } -#endif - return true; -} - -uint32_t I386_OPS::read_debug_reg(const _TCHAR *reg) -{ -#if defined(USE_DEBUGGER) - if(_tcsicmp(reg, _T("IP")) == 0) { - return cpustate->eip; - } else if(_tcsicmp(reg, _T("AX")) == 0) { - return REG16(AX); - } else if(_tcsicmp(reg, _T("BX")) == 0) { - return REG16(BX); - } else if(_tcsicmp(reg, _T("CX")) == 0) { - return REG16(CX); - } else if(_tcsicmp(reg, _T("DX")) == 0) { - return REG16(DX); - } else if(_tcsicmp(reg, _T("SP")) == 0) { - return REG16(SP); - } else if(_tcsicmp(reg, _T("BP")) == 0) { - return REG16(BP); - } else if(_tcsicmp(reg, _T("SI")) == 0) { - return REG16(SI); - } else if(_tcsicmp(reg, _T("DI")) == 0) { - return REG16(DI); - } else if(_tcsicmp(reg, _T("AL")) == 0) { - return REG8(AL); - } else if(_tcsicmp(reg, _T("AH")) == 0) { - return REG8(AH); - } else if(_tcsicmp(reg, _T("BL")) == 0) { - return REG8(BL); - } else if(_tcsicmp(reg, _T("BH")) == 0) { - return REG8(BH); - } else if(_tcsicmp(reg, _T("CL")) == 0) { - return REG8(CL); - } else if(_tcsicmp(reg, _T("CH")) == 0) { - return REG8(CH); - } else if(_tcsicmp(reg, _T("DL")) == 0) { - return REG8(DL); - } else if(_tcsicmp(reg, _T("DH")) == 0) { - return REG8(DH); - } -#endif - return 0; -} - -int I386_OPS::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len) -{ -#if defined(USE_DEBUGGER) - //UINT64 eip = cpustate->eip; - UINT64 eip = pc - cpustate->sreg[CS].base; - UINT8 ops[16]; - for(int i = 0; i < 16; i++) { - int wait; - ops[i] = d_mem->read_data8w(pc + i, &wait); - } - UINT8 *oprom = ops; - - if(cpustate->operand_size) { - return CPU_DISASSEMBLE_CALL(x86_32) & DASMFLAG_LENGTHMASK; - } else { - return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK; - } -#else - return 0; -#endif -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386_real.h b/source/src/vm/libcpu_newdev/libcpu_i386/i386_real.h deleted file mode 100644 index b7e1c4de5..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386_real.h +++ /dev/null @@ -1,175 +0,0 @@ - -#ifndef __LIB_I386_REAL_H__ -#define __LIB_I386_REAL_H__ - -#include "./i386_opdef.h" - -struct I386_OPCODE; -class I386_OPS: public I386_OPS_BASE -{ -public: - I386_OPS(int cputypes = I386_OPS_CPUTYPE_I386) : I386_OPS_BASE(cputypes) - { - } - - ~I386_OPS() {} - - int cpu_translate_i386(void *cpudevice, address_spacenum space, int intention, offs_t *address); - int cpu_execute_i386(int cycles); - void i386_trap(int irq, int irq_gate, int trap_level); - void i386_trap_with_error(int irq, int irq_gate, int trap_level, UINT32 error); - void i386__int(); // Opcode 0xcd - void i386_call_abs16(); // Opcode 0x9a - void i386_call_rel16(); // Opcode 0xe8 - void i386_groupFF_16(); // Opcode 0xff - void i386_decode_opcode(); - //void build_opcode_table(UINT32 features); - i386_state *i386_common_init(int tlbsize); - - void set_context_io_stored(DEVICE *dev) { -#ifdef USE_DEBUGGER - cpustate->io_stored = dev; -#endif - } - - void set_context_emu(EMU *p_emu) { -#ifdef USE_DEBUGGER - cpustate->emu = p_emu; -#endif - } - - void set_context_debugger(DEBUGGER *debugger) { -#ifdef USE_DEBUGGER - cpustate->debugger = debugger; -#endif - } - void set_context_progmem_stored(DEVICE *dev) { -#ifdef USE_DEBUGGER - cpustate->program_stored = dev; -#endif - } - void set_context_pseudo_bios(DEVICE *dev) { -#ifdef I386_PSEUDO_BIOS - cpustate->bios = dev; - d_bios = dev; -#endif - } - void set_context_dma(DEVICE *dev) { -#ifdef SINGLE_MODE_DMA - cpustate->dma = dev; - d_dma = dev; -#endif - } - bool write_debug_reg(const _TCHAR *reg, uint32_t data); - uint32_t read_debug_reg(const _TCHAR *reg); - int debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len); - -protected: - const UINT8 *opcode_ptr; - const UINT8 *opcode_ptr_base; - int address_size; - int operand_size; - int address_prefix; - int operand_prefix; - int max_length; - UINT64 pc; - UINT8 modrm; - UINT32 segment; - offs_t dasm_flags; - _TCHAR modrm_string[256]; - UINT8 rex, regex, sibex, rmex; - UINT8 pre0f; - UINT8 curmode; - - INLINE UINT8 _FETCH(void); -#if 0 - INLINE UINT16 _FETCH16(void); -#endif - INLINE UINT32 _FETCH32(void); - INLINE UINT8 _FETCHD(void); - INLINE UINT16 _FETCHD16(void); - INLINE UINT32 _FETCHD32(void); - _TCHAR *hexstring(UINT32 value, int digits); - _TCHAR *hexstring64(UINT32 lo, UINT32 hi); - _TCHAR *hexstringpc(UINT64 pc); - _TCHAR *shexstring(UINT32 value, int digits, int always); - _TCHAR* handle_sib_byte( _TCHAR* s, UINT8 mod ); - void handle_modrm(_TCHAR* s); - _TCHAR* handle_param(_TCHAR* s, UINT32 param); - void handle_fpu(_TCHAR *s, UINT8 op1, UINT8 op2); - void decode_opcode(_TCHAR *s, const I386_OPCODE *op, UINT8 op1); - - int i386_dasm_one_ex(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom, int mode); - int i386_dasm_one(_TCHAR *buffer, offs_t eip, const UINT8 *oprom, int mode); - int cpu_disassemble_x86_16(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom); - int cpu_disassemble_x86_32(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom); - int cpu_disassemble_x86_64(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom); -}; - -INLINE UINT8 I386_OPS::_FETCH(void) -{ - if ((opcode_ptr - opcode_ptr_base) + 1 > max_length) - return 0xff; - pc++; - return *opcode_ptr++; -} - -#if 0 -INLINE UINT16 I386_OPS::_FETCH16(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; -} -#endif - -INLINE UINT32 I386_OPS::_FETCH32(void) -{ - UINT32 d; - if ((opcode_ptr - opcode_ptr_base) + 4 > max_length) - return 0xffffffff; - d = opcode_ptr[0] | (opcode_ptr[1] << 8) | (opcode_ptr[2] << 16) | (opcode_ptr[3] << 24); - opcode_ptr += 4; - pc += 4; - return d; -} - -INLINE UINT8 I386_OPS::_FETCHD(void) -{ - if ((opcode_ptr - opcode_ptr_base) + 1 > max_length) - return 0xff; - pc++; - return *opcode_ptr++; -} - -INLINE UINT16 I386_OPS::_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; -} - -INLINE UINT32 I386_OPS::_FETCHD32(void) -{ - UINT32 d; - if ((opcode_ptr - opcode_ptr_base) + 4 > max_length) - return 0xffffffff; - d = opcode_ptr[0] | (opcode_ptr[1] << 8) | (opcode_ptr[2] << 16) | (opcode_ptr[3] << 24); - opcode_ptr += 4; - pc += 4; - return d; -} - - - -#endif - - diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386dasm.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386dasm.cpp deleted file mode 100644 index d13b2ae92..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386dasm.cpp +++ /dev/null @@ -1,3052 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde -/* - i386 Disassembler - - Written by Ville Linde, Peter Ferrie -*/ - -//#include "emu.h" -#include "../../../common.h" -#include "./i386_real.h" -enum -{ - PARAM_REG = 1, /* 16 or 32-bit register */ - PARAM_REG8, /* 8-bit register */ - PARAM_REG16, /* 16-bit register */ - PARAM_REG32, /* 32-bit register */ - PARAM_REG3264, /* 32-bit or 64-bit register */ - PARAM_REG2_32, /* 32-bit register */ - PARAM_MMX, /* MMX register */ - PARAM_MMX2, /* MMX register in modrm */ - PARAM_XMM, /* XMM register */ - PARAM_RM, /* 16 or 32-bit memory or register */ - PARAM_RM8, /* 8-bit memory or register */ - PARAM_RM16, /* 16-bit memory or register */ - PARAM_RM32, /* 32-bit memory or register */ - PARAM_RMPTR, /* 16 or 32-bit memory or register */ - PARAM_RMPTR8, /* 8-bit memory or register */ - PARAM_RMPTR16, /* 16-bit memory or register */ - PARAM_RMPTR32, /* 32-bit memory or register */ - PARAM_RMXMM, /* 32 or 64-bit memory or register */ - PARAM_REGORXMM, /* 32 or 64-bit register or XMM register */ - PARAM_M64, /* 64-bit memory */ - PARAM_M64PTR, /* 64-bit memory */ - PARAM_MMXM, /* 64-bit memory or MMX register */ - PARAM_XMMM, /* 128-bit memory or XMM register */ - PARAM_I4, /* 4-bit signed immediate */ - PARAM_I8, /* 8-bit signed immediate */ - PARAM_I16, /* 16-bit signed immediate */ - PARAM_UI8, /* 8-bit unsigned immediate */ - PARAM_UI16, /* 16-bit unsigned immediate */ - PARAM_IMM, /* 16 or 32-bit immediate */ - PARAM_IMM64, /* 16, 32 or 64-bit immediate */ - PARAM_ADDR, /* 16:16 or 16:32 address */ - PARAM_REL, /* 16 or 32-bit PC-relative displacement */ - PARAM_REL8, /* 8-bit PC-relative displacement */ - PARAM_MEM_OFFS, /* 16 or 32-bit mem offset */ - PARAM_PREIMP, /* prefix with implicit register */ - PARAM_SREG, /* segment register */ - PARAM_CREG, /* control register */ - PARAM_DREG, /* debug register */ - PARAM_TREG, /* test 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_DX, - PARAM_EAX, /* EAX or AX */ - PARAM_ECX, /* ECX or CX */ - PARAM_EDX, /* EDX or DX */ - PARAM_EBX, /* EBX or BX */ - PARAM_ESP, /* ESP or SP */ - PARAM_EBP, /* EBP or BP */ - PARAM_ESI, /* ESI or SI */ - PARAM_EDI, /* EDI or DI */ - PARAM_XMM0, - PARAM_XMM64, /* 64-bit memory or XMM register */ - PARAM_XMM32, /* 32-bit memory or XMM register */ - PARAM_XMM16, /* 16-bit memory or XMM register */ -}; - -enum -{ - MODRM = 1, - GROUP, - FPU, - OP_SIZE, - ADDR_SIZE, - TWO_BYTE, - PREFIX, - SEG_CS, - SEG_DS, - SEG_ES, - SEG_FS, - SEG_GS, - SEG_SS, - ISREX, - THREE_BYTE /* [prefix] 0f op1 op2 and then mod/rm */ -}; - -#define FLAGS_MASK 0x0ff -#define VAR_NAME 0x100 -#define VAR_NAME4 0x200 -#define ALWAYS64 0x400 -#define SPECIAL64 0x800 -#define SPECIAL64_ENT(x) (SPECIAL64 | ((x) << 24)) -#define GROUP_MOD 0x1000 - -struct I386_OPCODE { - const _TCHAR *mnemonic; - UINT32 flags; - UINT32 param1; - UINT32 param2; - UINT32 param3; - offs_t dasm_flags; -}; - -struct GROUP_OP { - _TCHAR mnemonic[32]; - const I386_OPCODE *opcode; -}; - -static const I386_OPCODE i386_opcode_table1[256] = -{ - // 0x00 - {_T("add"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("add"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("add"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("add"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("add"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("add"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("push es"), 0, 0, 0, 0 }, - {_T("pop es"), 0, 0, 0, 0 }, - {_T("or"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("or"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("or"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("or"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("or"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("or"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("push cs"), 0, 0, 0, 0 }, - {_T("two_byte"), TWO_BYTE, 0, 0, 0 }, - // 0x10 - {_T("adc"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("adc"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("adc"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("adc"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("adc"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("adc"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("push ss"), 0, 0, 0, 0 }, - {_T("pop ss"), 0, 0, 0, 0 }, - {_T("sbb"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("sbb"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("sbb"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("sbb"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("sbb"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("sbb"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("push ds"), 0, 0, 0, 0 }, - {_T("pop ds"), 0, 0, 0, 0 }, - // 0x20 - {_T("and"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("and"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("and"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("and"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("and"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("and"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("seg_es"), SEG_ES, 0, 0, 0 }, - {_T("daa"), 0, 0, 0, 0 }, - {_T("sub"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("sub"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("sub"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("sub"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("sub"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("sub"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("seg_cs"), SEG_CS, 0, 0, 0 }, - {_T("das"), 0, 0, 0, 0 }, - // 0x30 - {_T("xor"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("xor"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("xor"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("xor"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("xor"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("xor"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("seg_ss"), SEG_SS, 0, 0, 0 }, - {_T("aaa"), 0, 0, 0, 0 }, - {_T("cmp"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("cmp"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("cmp"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("cmp"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmp"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("cmp"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("seg_ds"), SEG_DS, 0, 0, 0 }, - {_T("aas"), 0, 0, 0, 0 }, - // 0x40 - {_T("inc"), ISREX, PARAM_EAX, 0, 0 }, - {_T("inc"), ISREX, PARAM_ECX, 0, 0 }, - {_T("inc"), ISREX, PARAM_EDX, 0, 0 }, - {_T("inc"), ISREX, PARAM_EBX, 0, 0 }, - {_T("inc"), ISREX, PARAM_ESP, 0, 0 }, - {_T("inc"), ISREX, PARAM_EBP, 0, 0 }, - {_T("inc"), ISREX, PARAM_ESI, 0, 0 }, - {_T("inc"), ISREX, PARAM_EDI, 0, 0 }, - {_T("dec"), ISREX, PARAM_EAX, 0, 0 }, - {_T("dec"), ISREX, PARAM_ECX, 0, 0 }, - {_T("dec"), ISREX, PARAM_EDX, 0, 0 }, - {_T("dec"), ISREX, PARAM_EBX, 0, 0 }, - {_T("dec"), ISREX, PARAM_ESP, 0, 0 }, - {_T("dec"), ISREX, PARAM_EBP, 0, 0 }, - {_T("dec"), ISREX, PARAM_ESI, 0, 0 }, - {_T("dec"), ISREX, PARAM_EDI, 0, 0 }, - // 0x50 - {_T("push"), ALWAYS64, PARAM_EAX, 0, 0 }, - {_T("push"), ALWAYS64, PARAM_ECX, 0, 0 }, - {_T("push"), ALWAYS64, PARAM_EDX, 0, 0 }, - {_T("push"), ALWAYS64, PARAM_EBX, 0, 0 }, - {_T("push"), ALWAYS64, PARAM_ESP, 0, 0 }, - {_T("push"), ALWAYS64, PARAM_EBP, 0, 0 }, - {_T("push"), ALWAYS64, PARAM_ESI, 0, 0 }, - {_T("push"), ALWAYS64, PARAM_EDI, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_EAX, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_ECX, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_EDX, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_EBX, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_ESP, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_EBP, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_ESI, 0, 0 }, - {_T("pop"), ALWAYS64, PARAM_EDI, 0, 0 }, - // 0x60 - {_T("pusha\0pushad\0"),VAR_NAME,0, 0, 0 }, - {_T("popa\0popad\0"), VAR_NAME,0, 0, 0 }, - {_T("bound"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("arpl"), MODRM | SPECIAL64_ENT(0),PARAM_RM, PARAM_REG16, 0 }, - {_T("seg_fs"), SEG_FS, 0, 0, 0 }, - {_T("seg_gs"), SEG_GS, 0, 0, 0 }, - {_T("op_size"), OP_SIZE, 0, 0, 0 }, - {_T("addr_size"), ADDR_SIZE, 0, 0, 0 }, - {_T("push"), 0, PARAM_IMM, 0, 0 }, - {_T("imul"), MODRM, PARAM_REG, PARAM_RM, PARAM_IMM }, - {_T("push"), 0, PARAM_I8, 0, 0 }, - {_T("imul"), MODRM, PARAM_REG, PARAM_RM, PARAM_I8 }, - {_T("insb"), 0, 0, 0, 0 }, - {_T("insw\0insd\0insd"),VAR_NAME, 0, 0, 0 }, - {_T("outsb"), 0, PARAM_PREIMP, 0, 0 }, - {_T("outsw\0outsd\0outsd"),VAR_NAME, PARAM_PREIMP, 0, 0 }, - // 0x70 - {_T("jo"), 0, PARAM_REL8, 0, 0 }, - {_T("jno"), 0, PARAM_REL8, 0, 0 }, - {_T("jb"), 0, PARAM_REL8, 0, 0 }, - {_T("jae"), 0, PARAM_REL8, 0, 0 }, - {_T("je"), 0, PARAM_REL8, 0, 0 }, - {_T("jne"), 0, PARAM_REL8, 0, 0 }, - {_T("jbe"), 0, PARAM_REL8, 0, 0 }, - {_T("ja"), 0, PARAM_REL8, 0, 0 }, - {_T("js"), 0, PARAM_REL8, 0, 0 }, - {_T("jns"), 0, PARAM_REL8, 0, 0 }, - {_T("jp"), 0, PARAM_REL8, 0, 0 }, - {_T("jnp"), 0, PARAM_REL8, 0, 0 }, - {_T("jl"), 0, PARAM_REL8, 0, 0 }, - {_T("jge"), 0, PARAM_REL8, 0, 0 }, - {_T("jle"), 0, PARAM_REL8, 0, 0 }, - {_T("jg"), 0, PARAM_REL8, 0, 0 }, - // 0x80 - {_T("group80"), GROUP, 0, 0, 0 }, - {_T("group81"), GROUP, 0, 0, 0 }, - {_T("group80"), GROUP, 0, 0, 0 }, - {_T("group83"), GROUP, 0, 0, 0 }, - {_T("test"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("test"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("xchg"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("xchg"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("mov"), MODRM, PARAM_RM8, PARAM_REG8, 0 }, - {_T("mov"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("mov"), MODRM, PARAM_REG8, PARAM_RM8, 0 }, - {_T("mov"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("mov"), MODRM, PARAM_RM, PARAM_SREG, 0 }, - {_T("lea"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("mov"), MODRM, PARAM_SREG, PARAM_RM, 0 }, - {_T("pop"), MODRM, PARAM_RM, 0, 0 }, - // 0x90 - {_T("nop\0???\0???\0pause"), VAR_NAME4, 0, 0, 0 }, - {_T("xchg"), 0, PARAM_EAX, PARAM_ECX, 0 }, - {_T("xchg"), 0, PARAM_EAX, PARAM_EDX, 0 }, - {_T("xchg"), 0, PARAM_EAX, PARAM_EBX, 0 }, - {_T("xchg"), 0, PARAM_EAX, PARAM_ESP, 0 }, - {_T("xchg"), 0, PARAM_EAX, PARAM_EBP, 0 }, - {_T("xchg"), 0, PARAM_EAX, PARAM_ESI, 0 }, - {_T("xchg"), 0, PARAM_EAX, PARAM_EDI, 0 }, - {_T("cbw\0cwde\0cdqe"), VAR_NAME, 0, 0, 0 }, - {_T("cwd\0cdq\0cqo"), VAR_NAME, 0, 0, 0 }, - {_T("call"), ALWAYS64, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER}, - {_T("wait"), 0, 0, 0, 0 }, - {_T("pushf\0pushfd\0pushfq"),VAR_NAME, 0, 0, 0 }, - {_T("popf\0popfd\0popfq"),VAR_NAME, 0, 0, 0 }, - {_T("sahf"), 0, 0, 0, 0 }, - {_T("lahf"), 0, 0, 0, 0 }, - // 0xa0 - {_T("mov"), 0, PARAM_AL, PARAM_MEM_OFFS, 0 }, - {_T("mov"), 0, PARAM_EAX, PARAM_MEM_OFFS, 0 }, - {_T("mov"), 0, PARAM_MEM_OFFS, PARAM_AL, 0 }, - {_T("mov"), 0, PARAM_MEM_OFFS, PARAM_EAX, 0 }, - {_T("movsb"), 0, PARAM_PREIMP, 0, 0 }, - {_T("movsw\0movsd\0movsq"),VAR_NAME, PARAM_PREIMP, 0, 0 }, - {_T("cmpsb"), 0, PARAM_PREIMP, 0, 0 }, - {_T("cmpsw\0cmpsd\0cmpsq"),VAR_NAME, PARAM_PREIMP, 0, 0 }, - {_T("test"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("test"), 0, PARAM_EAX, PARAM_IMM, 0 }, - {_T("stosb"), 0, 0, 0, 0 }, - {_T("stosw\0stosd\0stosq"),VAR_NAME, 0, 0, 0 }, - {_T("lodsb"), 0, PARAM_PREIMP, 0, 0 }, - {_T("lodsw\0lodsd\0lodsq"),VAR_NAME, PARAM_PREIMP, 0, 0 }, - {_T("scasb"), 0, 0, 0, 0 }, - {_T("scasw\0scasd\0scasq"),VAR_NAME, 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_EAX, PARAM_IMM64, 0 }, - {_T("mov"), 0, PARAM_ECX, PARAM_IMM64, 0 }, - {_T("mov"), 0, PARAM_EDX, PARAM_IMM64, 0 }, - {_T("mov"), 0, PARAM_EBX, PARAM_IMM64, 0 }, - {_T("mov"), 0, PARAM_ESP, PARAM_IMM64, 0 }, - {_T("mov"), 0, PARAM_EBP, PARAM_IMM64, 0 }, - {_T("mov"), 0, PARAM_ESI, PARAM_IMM64, 0 }, - {_T("mov"), 0, PARAM_EDI, PARAM_IMM64, 0 }, - // 0xc0 - {_T("groupC0"), GROUP, 0, 0, 0 }, - {_T("groupC1"), GROUP, 0, 0, 0 }, - {_T("ret"), 0, PARAM_UI16, 0, 0, DASMFLAG_STEP_OUT}, - {_T("ret"), 0, 0, 0, 0, DASMFLAG_STEP_OUT}, - {_T("les"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("lds"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("mov"), MODRM, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("mov"), MODRM, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("enter"), 0, PARAM_UI16, PARAM_UI8, 0 }, - {_T("leave"), 0, 0, 0, 0 }, - {_T("retf"), 0, PARAM_UI16, 0, 0, DASMFLAG_STEP_OUT}, - {_T("retf"), 0, 0, 0, 0, DASMFLAG_STEP_OUT}, - {_T("int 3"), 0, 0, 0, 0, DASMFLAG_STEP_OVER}, - {_T("int"), 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER}, - {_T("into"), 0, 0, 0, 0 }, - {_T("iret"), 0, 0, 0, 0, DASMFLAG_STEP_OUT}, - // 0xd0 - {_T("groupD0"), GROUP, 0, 0, 0 }, - {_T("groupD1"), GROUP, 0, 0, 0 }, - {_T("groupD2"), GROUP, 0, 0, 0 }, - {_T("groupD3"), GROUP, 0, 0, 0 }, - {_T("aam"), 0, PARAM_UI8, 0, 0 }, - {_T("aad"), 0, PARAM_UI8, 0, 0 }, - {_T("salc"), 0, 0, 0, 0 }, //AMD docs name it - {_T("xlat"), 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("loopne"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER}, - {_T("loopz"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER}, - {_T("loop"), 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER}, - {_T("jcxz\0jecxz\0jrcxz"),VAR_NAME, PARAM_REL8, 0, 0 }, - {_T("in"), 0, PARAM_AL, PARAM_UI8, 0 }, - {_T("in"), 0, PARAM_EAX, PARAM_UI8, 0 }, - {_T("out"), 0, PARAM_UI8, PARAM_AL, 0 }, - {_T("out"), 0, PARAM_UI8, PARAM_EAX, 0 }, - {_T("call"), 0, PARAM_REL, 0, 0, DASMFLAG_STEP_OVER}, - {_T("jmp"), 0, PARAM_REL, 0, 0 }, - {_T("jmp"), 0, PARAM_ADDR, 0, 0 }, - {_T("jmp"), 0, PARAM_REL8, 0, 0 }, - {_T("in"), 0, PARAM_AL, PARAM_DX, 0 }, - {_T("in"), 0, PARAM_EAX, PARAM_DX, 0 }, - {_T("out"), 0, PARAM_DX, PARAM_AL, 0 }, - {_T("out"), 0, PARAM_DX, PARAM_EAX, 0 }, - // 0xf0 - {_T("lock"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("repne"), PREFIX, 0, 0, 0 }, - {_T("rep"), PREFIX, 0, 0, 0 }, - {_T("hlt"), 0, 0, 0, 0 }, - {_T("cmc"), 0, 0, 0, 0 }, - {_T("groupF6"), GROUP, 0, 0, 0 }, - {_T("groupF7"), GROUP, 0, 0, 0 }, - {_T("clc"), 0, 0, 0, 0 }, - {_T("stc"), 0, 0, 0, 0 }, - {_T("cli"), 0, 0, 0, 0 }, - {_T("sti"), 0, 0, 0, 0 }, - {_T("cld"), 0, 0, 0, 0 }, - {_T("std"), 0, 0, 0, 0 }, - {_T("groupFE"), GROUP, 0, 0, 0 }, - {_T("groupFF"), GROUP, 0, 0, 0 } -}; - -static const I386_OPCODE x64_opcode_alt[] = -{ - {_T("movsxd"), MODRM | ALWAYS64,PARAM_REG, PARAM_RMPTR32, 0 }, -}; - -static const I386_OPCODE i386_opcode_table2[256] = -{ - // 0x00 - {_T("group0F00"), GROUP, 0, 0, 0 }, - {_T("group0F01"), GROUP, 0, 0, 0 }, - {_T("lar"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("lsl"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("syscall"), 0, 0, 0, 0 }, - {_T("clts"), 0, 0, 0, 0 }, - {_T("sysret"), 0, 0, 0, 0 }, - {_T("invd"), 0, 0, 0, 0 }, - {_T("wbinvd"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("ud2"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("group0F0D"), GROUP, 0, 0, 0 }, //AMD only - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x10 - {_T("movups\0") - _T("movupd\0") - _T("movsd\0") - _T("movss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movups\0") - _T("movupd\0") - _T("movsd\0") - _T("movss"), MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 }, - {_T("movlps\0") - _T("movlpd\0") - _T("movddup\0") - _T("movsldup"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movlps\0") - _T("movlpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 }, - {_T("unpcklps\0") - _T("unpcklpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("unpckhps\0") - _T("unpckhpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("group0F16"), GROUP|GROUP_MOD, 0, 0, 0 }, - {_T("movhps\0") - _T("movhpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 }, - {_T("group0F18"), GROUP, 0, 0, 0 }, - {_T("nop_hint"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("nop_hint"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("nop_hint"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("nop_hint"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("nop_hint"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("nop_hint"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("nop_hint"), 0, PARAM_RMPTR8, 0, 0 }, - // 0x20 - {_T("mov"), MODRM, PARAM_REG2_32, PARAM_CREG, 0 }, - {_T("mov"), MODRM, PARAM_REG2_32, PARAM_DREG, 0 }, - {_T("mov"), MODRM, PARAM_CREG, PARAM_REG2_32, 0 }, - {_T("mov"), MODRM, PARAM_DREG, PARAM_REG2_32, 0 }, - {_T("mov"), MODRM, PARAM_REG2_32, PARAM_TREG, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("mov"), MODRM, PARAM_TREG, PARAM_REG2_32, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("movaps\0") - _T("movapd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movaps\0") - _T("movapd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 }, - {_T("cvtpi2ps\0") - _T("cvtpi2pd\0") - _T("cvtsi2sd\0") - _T("cvtsi2ss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_RMXMM, 0 }, - {_T("movntps\0") - _T("movntpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 }, - {_T("cvttps2pi\0") - _T("cvttpd2pi\0") - _T("cvttsd2si\0") - _T("cvttss2si"), MODRM|VAR_NAME4,PARAM_REGORXMM, PARAM_XMMM, 0 }, - {_T("cvtps2pi\0") - _T("cvtpd2pi\0") - _T("cvtsd2si\0") - _T("cvtss2si"), MODRM|VAR_NAME4,PARAM_REGORXMM, PARAM_XMMM, 0 }, - {_T("ucomiss\0") - _T("ucomisd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("comiss\0") - _T("comisd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - // 0x30 - {_T("wrmsr"), 0, 0, 0, 0 }, - {_T("rdtsc"), 0, 0, 0, 0 }, - {_T("rdmsr"), 0, 0, 0, 0 }, - {_T("rdpmc"), 0, 0, 0, 0 }, - {_T("sysenter"), 0, 0, 0, 0 }, - {_T("sysexit"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("three_byte"), THREE_BYTE, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("three_byte"), THREE_BYTE, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x40 - {_T("cmovo"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovno"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovb"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovae"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmove"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovne"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovbe"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmova"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovs"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovns"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovpe"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovpo"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovl"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovge"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovle"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("cmovg"), MODRM, PARAM_REG, PARAM_RM, 0 }, - // 0x50 - {_T("movmskps\0") - _T("movmskpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_REG3264, PARAM_XMMM, 0 }, - {_T("sqrtps\0") - _T("sqrtpd\0") - _T("sqrtsd\0") - _T("sqrtss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("rsqrtps\0") - _T("???\0") - _T("???\0") - _T("rsqrtss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("rcpps\0") - _T("???\0") - _T("???\0") - _T("rcpss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("andps\0") - _T("andpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("andnps\0") - _T("andnpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("orps\0") - _T("orpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("xorps\0") - _T("xorpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("addps\0") - _T("addpd\0") - _T("addsd\0") - _T("addss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("mulps\0") - _T("mulpd\0") - _T("mulsd\0") - _T("mulss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("cvtps2pd\0") - _T("cvtpd2ps\0") - _T("cvtsd2ss\0") - _T("cvtss2sd"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("cvtdq2ps\0") - _T("cvtps2dq\0") - _T("???\0") - _T("cvttps2dq"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("subps\0") - _T("subpd\0") - _T("subsd\0") - _T("subss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("minps\0") - _T("minpd\0") - _T("minsd\0") - _T("minss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("divps\0") - _T("divpd\0") - _T("divsd\0") - _T("divss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("maxps\0") - _T("maxpd\0") - _T("maxsd\0") - _T("maxss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - // 0x60 - {_T("punpcklbw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("punpcklwd"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("punpckldq"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("packsswb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pcmpgtb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pcmpgtw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pcmpgtd"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("packuswb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("punpckhbw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("punpckhwd"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("punpckhdq"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("packssdw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("???\0") - _T("punpcklqdq\0") - _T("???\0") - _T("???\0"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("punpckhqdq\0") - _T("???\0") - _T("???\0"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movd"), MODRM, PARAM_MMX, PARAM_RM, 0 }, - {_T("movq\0") - _T("movdqa\0") - _T("???\0") - _T("movdqu"), MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 }, - // 0x70 - {_T("pshufw\0") - _T("pshufd\0") - _T("pshuflw\0") - _T("pshufhw"), MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, PARAM_UI8 }, - {_T("group0F71"), GROUP, 0, 0, 0 }, - {_T("group0F72"), GROUP, 0, 0, 0 }, - {_T("group0F73"), GROUP, 0, 0, 0 }, - {_T("pcmpeqb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pcmpeqw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pcmpeqd"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("emms"), 0, 0, 0, 0 }, - {_T("vmread"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("vmwrite"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???\0") - _T("haddpd\0") - _T("haddps\0") - _T("???"), MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 }, - {_T("???\0") - _T("hsubpd\0") - _T("hsubps\0") - _T("???"), MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 }, - {_T("movd\0") - _T("movd\0") - _T("???\0") - _T("movq"), MODRM|VAR_NAME4,PARAM_RM, PARAM_MMX, 0 }, - {_T("movq\0") - _T("movdqa\0") - _T("???\0") - _T("movdqu"), MODRM|VAR_NAME4,PARAM_MMXM, PARAM_MMX, 0 }, - // 0x80 - {_T("jo"), 0, PARAM_REL, 0, 0 }, - {_T("jno"), 0, PARAM_REL, 0, 0 }, - {_T("jb"), 0, PARAM_REL, 0, 0 }, - {_T("jae"), 0, PARAM_REL, 0, 0 }, - {_T("je"), 0, PARAM_REL, 0, 0 }, - {_T("jne"), 0, PARAM_REL, 0, 0 }, - {_T("jbe"), 0, PARAM_REL, 0, 0 }, - {_T("ja"), 0, PARAM_REL, 0, 0 }, - {_T("js"), 0, PARAM_REL, 0, 0 }, - {_T("jns"), 0, PARAM_REL, 0, 0 }, - {_T("jp"), 0, PARAM_REL, 0, 0 }, - {_T("jnp"), 0, PARAM_REL, 0, 0 }, - {_T("jl"), 0, PARAM_REL, 0, 0 }, - {_T("jge"), 0, PARAM_REL, 0, 0 }, - {_T("jle"), 0, PARAM_REL, 0, 0 }, - {_T("jg"), 0, PARAM_REL, 0, 0 }, - // 0x90 - {_T("seto"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setno"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setb"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setae"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("sete"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setne"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setbe"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("seta"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("sets"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setns"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setp"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setnp"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setl"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setge"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setle"), MODRM, PARAM_RMPTR8, 0, 0 }, - {_T("setg"), MODRM, PARAM_RMPTR8, 0, 0 }, - // 0xa0 - {_T("push fs"), 0, 0, 0, 0 }, - {_T("pop fs"), 0, 0, 0, 0 }, - {_T("cpuid"), 0, 0, 0, 0 }, - {_T("bt"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("shld"), MODRM, PARAM_RM, PARAM_REG, PARAM_UI8 }, - {_T("shld"), MODRM, PARAM_RM, PARAM_REG, PARAM_CL }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("push gs"), 0, 0, 0, 0 }, - {_T("pop gs"), 0, 0, 0, 0 }, - {_T("rsm"), 0, 0, 0, 0 }, - {_T("bts"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("shrd"), MODRM, PARAM_RM, PARAM_REG, PARAM_UI8 }, - {_T("shrd"), MODRM, PARAM_RM, PARAM_REG, PARAM_CL }, - {_T("group0FAE"), GROUP, 0, 0, 0 }, - {_T("imul"), MODRM, PARAM_REG, PARAM_RM, 0 }, - // 0xb0 - {_T("cmpxchg"), MODRM, PARAM_RM8, PARAM_REG, 0 }, - {_T("cmpxchg"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("lss"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("btr"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("lfs"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("lgs"), MODRM, PARAM_REG, PARAM_RM, 0 }, - {_T("movzx"), MODRM, PARAM_REG, PARAM_RMPTR8, 0 }, - {_T("movzx"), MODRM, PARAM_REG, PARAM_RMPTR16, 0 }, - {_T("???\0") - _T("???\0") - _T("???\0") - _T("popcnt"), MODRM|VAR_NAME4, PARAM_REG, PARAM_RM16, 0 }, - {_T("ud2"), 0, 0, 0, 0 }, - {_T("group0FBA"), GROUP, 0, 0, 0 }, - {_T("btc"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("bsf\0") - _T("???\0") - _T("???\0") - _T("tzcnt"), MODRM|VAR_NAME4, PARAM_REG, PARAM_RM, 0 }, - {_T("bsr\0") - _T("???\0") - _T("???\0") - _T("lzcnt"), MODRM|VAR_NAME4, PARAM_REG, PARAM_RM, 0, DASMFLAG_STEP_OVER}, - {_T("movsx"), MODRM, PARAM_REG, PARAM_RMPTR8, 0 }, - {_T("movsx"), MODRM, PARAM_REG, PARAM_RMPTR16, 0 }, - // 0xc0 - {_T("xadd"), MODRM, PARAM_RM8, PARAM_REG, 0 }, - {_T("xadd"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("cmpps\0") - _T("cmppd\0") - _T("cmpsd\0") - _T("cmpss"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movnti"), MODRM, PARAM_RM, PARAM_REG, 0 }, - {_T("pinsrw"), MODRM, PARAM_MMX, PARAM_RM, PARAM_UI8 }, - {_T("pextrw"), MODRM, PARAM_MMX, PARAM_RM, PARAM_UI8 }, - {_T("shufps\0") - _T("shufpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("group0FC7"), GROUP, 0, 0, 0 }, - {_T("bswap"), 0, PARAM_EAX, 0, 0 }, - {_T("bswap"), 0, PARAM_ECX, 0, 0 }, - {_T("bswap"), 0, PARAM_EDX, 0, 0 }, - {_T("bswap"), 0, PARAM_EBX, 0, 0 }, - {_T("bswap"), 0, PARAM_ESP, 0, 0 }, - {_T("bswap"), 0, PARAM_EBP, 0, 0 }, - {_T("bswap"), 0, PARAM_ESI, 0, 0 }, - {_T("bswap"), 0, PARAM_EDI, 0, 0 }, - // 0xd0 - {_T("???\0") - _T("addsubpd\0") - _T("addsubps\0") - _T("???\0"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("psrlw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psrld"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psrlq"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddq"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmullw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("???\0") - _T("movq\0") - _T("movdq2q\0") - _T("movq2dq"), MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmovmskb"), MODRM, PARAM_REG3264, PARAM_MMXM, 0 }, - {_T("psubusb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psubusw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pminub"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pand"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddusb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddusw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmaxub"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pandn"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - // 0xe0 - {_T("pavgb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psraw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psrad"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pavgw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmulhuw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmulhw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("???\0") - _T("cvttpd2dq\0") - _T("cvtpd2dq\0") - _T("cvtdq2pd"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movntq\0") - _T("movntdq\0") - _T("???\0") - _T("???\0"), MODRM|VAR_NAME4, PARAM_M64, PARAM_MMX, 0 }, - {_T("psubsb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psubsw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pminsw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("por"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddsb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddsw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmaxsw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pxor"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - // 0xf0 - {_T("???\0") - _T("???\0") - _T("lddqu\0") - _T("???"), MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("psllw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pslld"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psllq"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmuludq"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("pmaddwd"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psadbw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("maskmovq\0") - _T("maskmovdqu\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psubb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psubw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psubd"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("psubq"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddb"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddw"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("paddd"), MODRM, PARAM_MMX, PARAM_MMXM, 0 }, - {_T("???"), 0, 0, 0, 0 } -}; - -static const I386_OPCODE i386_opcode_table0F38[256] = -{ - // 0x00 - {_T("pshufb\0") - _T("pshufb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("phaddw\0") - _T("phaddw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("phaddd\0") - _T("phadd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("phaddsw\0") - _T("phaddsw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("pmaddubsw\0") - _T("pmaddubsw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("phsubw\0") - _T("phsubw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("phsubd\0") - _T("phsubd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("phsubsw\0") - _T("phsubsw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("psignb\0") - _T("psignb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("psignw\0") - _T("psignw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("psignd\0") - _T("psignd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("pmulhrsw\0") - _T("pmulhrsw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x10 - {_T("???\0") - _T("pblendvb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_XMM0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???\0") - _T("blendvps\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_XMM0 }, - {_T("???\0") - _T("blendvpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_XMM0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???\0") - _T("ptest\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("pabsb\0") - _T("pabsb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("pabsw\0") - _T("pabsw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("pabsd\0") - _T("pabsd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x20 - {_T("???\0") - _T("pmovsxbw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM64, 0 }, - {_T("???\0") - _T("pmovsxbd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM32, 0 }, - {_T("???\0") - _T("pmovsxbq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM16, 0 }, - {_T("???\0") - _T("pmovsxwd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM64, 0 }, - {_T("???\0") - _T("pmovsxwq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM32, 0 }, - {_T("???\0") - _T("pmovsxdq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM64, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???\0") - _T("pmuldq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pcmpeqq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("movntdqa\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("packusdw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x30 - {_T("???\0") - _T("pmovzxbw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM64, 0 }, - {_T("???\0") - _T("pmovzxbd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM32, 0 }, - {_T("???\0") - _T("pmovzxbq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM16, 0 }, - {_T("???\0") - _T("pmovzxwd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM64, 0 }, - {_T("???\0") - _T("pmovzxwq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM32, 0 }, - {_T("???\0") - _T("pmovzxdq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMM64, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???\0") - _T("pcmpgtq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pminsb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pminsd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pminuw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pminud\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pmaxsb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pmaxsd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pmaxuw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("pmaxud\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - // 0x40 - {_T("???\0") - _T("pmulld\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("phminposuw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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") - _T("invept\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_REG32, PARAM_XMMM, 0 }, - {_T("???\0") - _T("invvpid\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_REG32, PARAM_XMMM, 0 }, - {_T("???\0") - _T("invpcid\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_REG32, PARAM_XMMM, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_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") - _T("aesimc\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("aesenc\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("aesenclast\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("aesdec\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - {_T("???\0") - _T("aesdeclast\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, 0 }, - // 0xe0 - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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("movbe\0") - _T("???\0") - _T("crc32\0") - _T("???"), MODRM|VAR_NAME4, PARAM_REG32, PARAM_RMPTR, 0 }, // not quite correct - {_T("movbe\0") - _T("???\0") - _T("crc32\0") - _T("???"), MODRM|VAR_NAME4, PARAM_RMPTR, PARAM_REG32, 0 }, // not quite correct - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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 i386_opcode_table0F3A[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") - _T("roundps\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("roundpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("roundss\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("roundsd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("blendps\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("blendpd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("pblendw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("palignr\0") - _T("palignr\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - // 0x10 - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???\0") - _T("pextrb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_RM8, PARAM_XMM, PARAM_UI8 }, - {_T("???\0") - _T("pextrw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_RM16, PARAM_XMM, PARAM_UI8 }, - {_T("???\0") - _T("pextrd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_RM8, PARAM_XMM, PARAM_UI8 }, - {_T("???\0") - _T("extractps\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_RM32, PARAM_XMM, PARAM_UI8 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x20 - {_T("???\0") - _T("pinsrb\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_RM8, PARAM_UI8 }, - {_T("???\0") - _T("insertps\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_RM8, PARAM_UI8 }, - {_T("???\0") - _T("pinsrd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_RM32, PARAM_UI8 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x30 - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - // 0x40 - {_T("???\0") - _T("dpps\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("dppd\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("mpsadbw\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???\0") - _T("pclmulqdq\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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") - _T("pcmestrm\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("pcmestri\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("pcmistrm\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???\0") - _T("pcmistri\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_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") - _T("aeskeygenassist\0") - _T("???\0") - _T("???"), MODRM|VAR_NAME4, PARAM_XMM, PARAM_XMMM, PARAM_UI8 }, - // 0xe0 - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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 group80_table[8] = -{ - {_T("add"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("or"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("adc"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("sbb"), 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 group81_table[8] = -{ - {_T("add"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("or"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("adc"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("sbb"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("and"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("sub"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("xor"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("cmp"), 0, PARAM_RMPTR, PARAM_IMM, 0 } -}; - -static const I386_OPCODE group83_table[8] = -{ - {_T("add"), 0, PARAM_RMPTR, PARAM_I8, 0 }, - {_T("or"), 0, PARAM_RMPTR, PARAM_I8, 0 }, - {_T("adc"), 0, PARAM_RMPTR, PARAM_I8, 0 }, - {_T("sbb"), 0, PARAM_RMPTR, PARAM_I8, 0 }, - {_T("and"), 0, PARAM_RMPTR, PARAM_I8, 0 }, - {_T("sub"), 0, PARAM_RMPTR, PARAM_I8, 0 }, - {_T("xor"), 0, PARAM_RMPTR, PARAM_I8, 0 }, - {_T("cmp"), 0, PARAM_RMPTR, PARAM_I8, 0 } -}; - -static const I386_OPCODE groupC0_table[8] = -{ - {_T("rol"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("ror"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("rcl"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("rcr"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("shl"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("shr"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("sal"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("sar"), 0, PARAM_RMPTR8, PARAM_UI8, 0 } -}; - -static const I386_OPCODE groupC1_table[8] = -{ - {_T("rol"), 0, PARAM_RMPTR, PARAM_UI8, 0 }, - {_T("ror"), 0, PARAM_RMPTR, PARAM_UI8, 0 }, - {_T("rcl"), 0, PARAM_RMPTR, PARAM_UI8, 0 }, - {_T("rcr"), 0, PARAM_RMPTR, PARAM_UI8, 0 }, - {_T("shl"), 0, PARAM_RMPTR, PARAM_UI8, 0 }, - {_T("shr"), 0, PARAM_RMPTR, PARAM_UI8, 0 }, - {_T("sal"), 0, PARAM_RMPTR, PARAM_UI8, 0 }, - {_T("sar"), 0, PARAM_RMPTR, PARAM_UI8, 0 } -}; - -static const I386_OPCODE groupD0_table[8] = -{ - {_T("rol"), 0, PARAM_RMPTR8, PARAM_1, 0 }, - {_T("ror"), 0, PARAM_RMPTR8, PARAM_1, 0 }, - {_T("rcl"), 0, PARAM_RMPTR8, PARAM_1, 0 }, - {_T("rcr"), 0, PARAM_RMPTR8, PARAM_1, 0 }, - {_T("shl"), 0, PARAM_RMPTR8, PARAM_1, 0 }, - {_T("shr"), 0, PARAM_RMPTR8, PARAM_1, 0 }, - {_T("sal"), 0, PARAM_RMPTR8, PARAM_1, 0 }, - {_T("sar"), 0, PARAM_RMPTR8, PARAM_1, 0 } -}; - -static const I386_OPCODE groupD1_table[8] = -{ - {_T("rol"), 0, PARAM_RMPTR, PARAM_1, 0 }, - {_T("ror"), 0, PARAM_RMPTR, PARAM_1, 0 }, - {_T("rcl"), 0, PARAM_RMPTR, PARAM_1, 0 }, - {_T("rcr"), 0, PARAM_RMPTR, PARAM_1, 0 }, - {_T("shl"), 0, PARAM_RMPTR, PARAM_1, 0 }, - {_T("shr"), 0, PARAM_RMPTR, PARAM_1, 0 }, - {_T("sal"), 0, PARAM_RMPTR, PARAM_1, 0 }, - {_T("sar"), 0, PARAM_RMPTR, PARAM_1, 0 } -}; - -static const I386_OPCODE groupD2_table[8] = -{ - {_T("rol"), 0, PARAM_RMPTR8, PARAM_CL, 0 }, - {_T("ror"), 0, PARAM_RMPTR8, PARAM_CL, 0 }, - {_T("rcl"), 0, PARAM_RMPTR8, PARAM_CL, 0 }, - {_T("rcr"), 0, PARAM_RMPTR8, PARAM_CL, 0 }, - {_T("shl"), 0, PARAM_RMPTR8, PARAM_CL, 0 }, - {_T("shr"), 0, PARAM_RMPTR8, PARAM_CL, 0 }, - {_T("sal"), 0, PARAM_RMPTR8, PARAM_CL, 0 }, - {_T("sar"), 0, PARAM_RMPTR8, PARAM_CL, 0 } -}; - -static const I386_OPCODE groupD3_table[8] = -{ - {_T("rol"), 0, PARAM_RMPTR, PARAM_CL, 0 }, - {_T("ror"), 0, PARAM_RMPTR, PARAM_CL, 0 }, - {_T("rcl"), 0, PARAM_RMPTR, PARAM_CL, 0 }, - {_T("rcr"), 0, PARAM_RMPTR, PARAM_CL, 0 }, - {_T("shl"), 0, PARAM_RMPTR, PARAM_CL, 0 }, - {_T("shr"), 0, PARAM_RMPTR, PARAM_CL, 0 }, - {_T("sal"), 0, PARAM_RMPTR, PARAM_CL, 0 }, - {_T("sar"), 0, PARAM_RMPTR, PARAM_CL, 0 } -}; - -static const I386_OPCODE groupF6_table[8] = -{ - {_T("test"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("test"), 0, PARAM_RMPTR8, PARAM_UI8, 0 }, - {_T("not"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("neg"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("mul"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("imul"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("div"), 0, PARAM_RMPTR8, 0, 0 }, - {_T("idiv"), 0, PARAM_RMPTR8, 0, 0 } -}; - -static const I386_OPCODE groupF7_table[8] = -{ - {_T("test"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("test"), 0, PARAM_RMPTR, PARAM_IMM, 0 }, - {_T("not"), 0, PARAM_RMPTR, 0, 0 }, - {_T("neg"), 0, PARAM_RMPTR, 0, 0 }, - {_T("mul"), 0, PARAM_RMPTR, 0, 0 }, - {_T("imul"), 0, PARAM_RMPTR, 0, 0 }, - {_T("div"), 0, PARAM_RMPTR, 0, 0 }, - {_T("idiv"), 0, PARAM_RMPTR, 0, 0 } -}; - -static const I386_OPCODE groupFE_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 groupFF_table[8] = -{ - {_T("inc"), 0, PARAM_RMPTR, 0, 0 }, - {_T("dec"), 0, PARAM_RMPTR, 0, 0 }, - {_T("call"), ALWAYS64, PARAM_RMPTR, 0, 0, DASMFLAG_STEP_OVER}, - {_T("call far ptr "),0, PARAM_RM, 0, 0, DASMFLAG_STEP_OVER}, - {_T("jmp"), ALWAYS64, PARAM_RMPTR, 0, 0 }, - {_T("jmp far ptr "),0, PARAM_RM, 0, 0 }, - {_T("push"), 0, PARAM_RMPTR, 0, 0 }, - {_T("???"), 0, 0, 0, 0 } -}; - -static const I386_OPCODE group0F00_table[8] = -{ - {_T("sldt"), 0, PARAM_RM, 0, 0 }, - {_T("str"), 0, PARAM_RM, 0, 0 }, - {_T("lldt"), 0, PARAM_RM, 0, 0 }, - {_T("ltr"), 0, PARAM_RM, 0, 0 }, - {_T("verr"), 0, PARAM_RM, 0, 0 }, - {_T("verw"), 0, PARAM_RM, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 } -}; - -static const I386_OPCODE group0F01_table[8] = -{ - {_T("sgdt"), 0, PARAM_RM, 0, 0 }, - {_T("sidt"), 0, PARAM_RM, 0, 0 }, - {_T("lgdt"), 0, PARAM_RM, 0, 0 }, - {_T("lidt"), 0, PARAM_RM, 0, 0 }, - {_T("smsw"), 0, PARAM_RM, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("lmsw"), 0, PARAM_RM, 0, 0 }, - {_T("invlpg"), 0, PARAM_RM, 0, 0 } -}; - -static const I386_OPCODE group0F0D_table[8] = -{ - {_T("prefetch"), 0, PARAM_RM8, 0, 0 }, - {_T("prefetchw"), 0, PARAM_RM8, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 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 group0F12_table[4] = -{ - {_T("movlps\0") - _T("movlpd\0") - _T("movddup\0") - _T("movsldup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movlps\0") - _T("movlpd\0") - _T("movddup\0") - _T("movsldup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movlps\0") - _T("movlpd\0") - _T("movddup\0") - _T("movsldup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movhlps\0") - _T("???\0") - _T("movddup\0") - _T("movsldup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 } -}; - -static const I386_OPCODE group0F16_table[4] = -{ - {_T("movhps\0") - _T("movhpd\0") - _T("???\0") - _T("movshdup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movhps\0") - _T("movhpd\0") - _T("???\0") - _T("movshdup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movhps\0") - _T("movhpd\0") - _T("???\0") - _T("movshdup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 }, - {_T("movlhps\0") - _T("movhpd\0") - _T("???\0") - _T("movshdup"), VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 } -}; - -static const I386_OPCODE group0F18_table[8] = -{ - {_T("prefetchnta"), 0, PARAM_RM8, 0, 0 }, - {_T("prefetch0"), 0, PARAM_RM8, 0, 0 }, - {_T("prefetch1"), 0, PARAM_RM8, 0, 0 }, - {_T("prefetch2"), 0, PARAM_RM8, 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 group0F71_table[8] = -{ - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("psrlw"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("psraw"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("psllw"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("???"), 0, 0, 0, 0 } -}; - -static const I386_OPCODE group0F72_table[8] = -{ - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("psrld"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("psrad"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("pslld"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("???"), 0, 0, 0, 0 } -}; - -static const I386_OPCODE group0F73_table[8] = -{ - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("psrlq"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("psrldq"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("psllq"), 0, PARAM_MMX2, PARAM_UI8, 0 }, - {_T("pslldq"), 0, PARAM_MMX2, PARAM_UI8, 0 }, -}; - -static const I386_OPCODE group0FAE_table[8] = -{ - {_T("fxsave"), 0, PARAM_RM, 0, 0 }, - {_T("fxrstor"), 0, PARAM_RM, 0, 0 }, - {_T("ldmxcsr"), 0, PARAM_RM, 0, 0 }, - {_T("stmxscr"), 0, PARAM_RM, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("lfence"), 0, 0, 0, 0 }, - {_T("mfence"), 0, 0, 0, 0 }, - {_T("sfence"), 0, 0, 0, 0 } -}; - - -static const I386_OPCODE group0FBA_table[8] = -{ - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("bt"), 0, PARAM_RM, PARAM_UI8, 0 }, - {_T("bts"), 0, PARAM_RM, PARAM_UI8, 0 }, - {_T("btr"), 0, PARAM_RM, PARAM_UI8, 0 }, - {_T("btc"), 0, PARAM_RM, PARAM_UI8, 0 } -}; - -static const I386_OPCODE group0FC7_table[8] = -{ - {_T("???"), 0, 0, 0, 0 }, - {_T("cmpxchg8b"), MODRM, PARAM_M64PTR, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("???"), 0, 0, 0, 0 }, - {_T("vmptrld\0") - _T("vmclear\0") - _T("???\0") - _T("vmxon"), MODRM|VAR_NAME4, PARAM_M64PTR, 0, 0 }, - {_T("vmptrtst"), MODRM, PARAM_M64PTR, 0, 0 } -}; - -static const GROUP_OP group_op_table[] = -{ - {_T("group80"), group80_table }, - {_T("group81"), group81_table }, - {_T("group83"), group83_table }, - {_T("groupC0"), groupC0_table }, - {_T("groupC1"), groupC1_table }, - {_T("groupD0"), groupD0_table }, - {_T("groupD1"), groupD1_table }, - {_T("groupD2"), groupD2_table }, - {_T("groupD3"), groupD3_table }, - {_T("groupF6"), groupF6_table }, - {_T("groupF7"), groupF7_table }, - {_T("groupFE"), groupFE_table }, - {_T("groupFF"), groupFF_table }, - {_T("group0F00"), group0F00_table }, - {_T("group0F01"), group0F01_table }, - {_T("group0F0D"), group0F0D_table }, - {_T("group0F12"), group0F12_table }, - {_T("group0F16"), group0F16_table }, - {_T("group0F18"), group0F18_table }, - {_T("group0F71"), group0F71_table }, - {_T("group0F72"), group0F72_table }, - {_T("group0F73"), group0F73_table }, - {_T("group0FAE"), group0FAE_table }, - {_T("group0FBA"), group0FBA_table }, - {_T("group0FC7"), group0FC7_table } -}; - - - -static const _TCHAR *const i386_reg[3][16] = -{ - {_T("ax"), _T("cx"), _T("dx"), _T("bx"), _T("sp"), _T("bp"), _T("si"), _T("di"), _T("r8w"), _T("r9w"), _T("r10w"),_T("r11w"),_T("r12w"),_T("r13w"),_T("r14w"),_T("r15w")}, - {_T("eax"), _T("ecx"), _T("edx"), _T("ebx"), _T("esp"), _T("ebp"), _T("esi"), _T("edi"), _T("r8d"), _T("r9d"), _T("r10d"),_T("r11d"),_T("r12d"),_T("r13d"),_T("r14d"),_T("r15d")}, - {_T("rax"), _T("rcx"), _T("rdx"), _T("rbx"), _T("rsp"), _T("rbp"), _T("rsi"), _T("rdi"), _T("r8"), _T("r9"), _T("r10"), _T("r11"), _T("r12"), _T("r13"), _T("r14"), _T("r15")} -}; - -static const _TCHAR *const i386_reg8[8] = {_T("al"), _T("cl"), _T("dl"), _T("bl"), _T("ah"), _T("ch"), _T("dh"), _T("bh")}; -static const _TCHAR *const i386_reg8rex[16] = {_T("al"), _T("cl"), _T("dl"), _T("bl"), _T("spl"), _T("bpl"), _T("sil"), _T("dil"), _T("r8l"), _T("r9l"), _T("r10l"), _T("r11l"), _T("r12l"), _T("r13l"), _T("r14l"), _T("r15l")}; -static const _TCHAR *const i386_sreg[8] = {_T("es"), _T("cs"), _T("ss"), _T("ds"), _T("fs"), _T("gs"), _T("???"), _T("???")}; - - -#define MODRM_REG1 ((modrm >> 3) & 0x7) -#define MODRM_REG2 (modrm & 0x7) -#define MODRM_MOD ((modrm >> 6) & 0x3) - -_TCHAR *I386_OPS::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]; -} - -_TCHAR *I386_OPS::hexstring64(UINT32 lo, UINT32 hi) -{ - static _TCHAR buffer[40]; - buffer[0] = _T('0'); - if (hi != 0) - _stprintf(&buffer[1], _T("%X%08Xh"), hi, lo); - else - _stprintf(&buffer[1], _T("%Xh"), lo); - return (buffer[1] >= _T('0') && buffer[1] <= _T('9')) ? &buffer[1] : &buffer[0]; -} - -_TCHAR *I386_OPS::hexstringpc(UINT64 pc) -{ - if (curmode == 64) - return hexstring64((UINT32)pc, (UINT32)(pc >> 32)); - else - return hexstring((UINT32)pc, 0); -} - -_TCHAR *I386_OPS::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; -} - -_TCHAR* I386_OPS::handle_sib_byte( _TCHAR* s, UINT8 mod ) -{ - UINT32 i32; - UINT8 scale, i, base; - UINT8 sib = _FETCHD(); - - scale = (sib >> 6) & 0x3; - i = ((sib >> 3) & 0x7) | sibex; - base = (sib & 0x7) | rmex; - - if (base == 5 && mod == 0) { - i32 = _FETCH32(); - s += _stprintf( s, _T("%s"), hexstring(i32, 0) ); - } else if (base != 5 || mod != 3) - s += _stprintf( s, _T("%s"), i386_reg[address_size][base] ); - - if ( i != 4 ) { - s += _stprintf( s, _T("+%s"), i386_reg[address_size][i] ); - if (scale) - s += _stprintf( s, _T("*%d"), 1 << scale ); - } - return s; -} - -void I386_OPS::handle_modrm(_TCHAR* s) -{ - INT8 disp8; - INT16 disp16; - INT32 disp32; - UINT8 mod, rm; - - modrm = _FETCHD(); - mod = (modrm >> 6) & 0x3; - rm = (modrm & 0x7) | rmex; - - if( modrm >= 0xc0 ) - return; - - switch(segment) - { - case SEG_CS: s += _stprintf( s, _T("cs:") ); break; - case SEG_DS: s += _stprintf( s, _T("ds:") ); break; - case SEG_ES: s += _stprintf( s, _T("es:") ); break; - case SEG_FS: s += _stprintf( s, _T("fs:") ); break; - case SEG_GS: s += _stprintf( s, _T("gs:") ); break; - case SEG_SS: s += _stprintf( s, _T("ss:") ); break; - } - - s += _stprintf( s, _T("[") ); - if( address_size == 2 ) { - if ((rm & 7) == 4) - s = handle_sib_byte( s, mod ); - else if ((rm & 7) == 5 && mod == 0) { - disp32 = _FETCHD32(); - s += _stprintf( s, _T("rip%s"), shexstring(disp32, 0, TRUE) ); - } else - s += _stprintf( s, _T("%s"), i386_reg[2][rm]); - if( mod == 1 ) { - disp8 = _FETCHD(); - if (disp8 != 0) - s += _stprintf( s, _T("%s"), shexstring((INT32)disp8, 0, TRUE) ); - } else if( mod == 2 ) { - disp32 = _FETCHD32(); - if (disp32 != 0) - s += _stprintf( s, _T("%s"), shexstring(disp32, 0, TRUE) ); - } - } else if (address_size == 1) { - if ((rm & 7) == 4) - s = handle_sib_byte( s, mod ); - else if ((rm & 7) == 5 && mod == 0) { - disp32 = _FETCHD32(); - if (curmode == 64) - s += _stprintf( s, _T("eip%s"), shexstring(disp32, 0, TRUE) ); - else - s += _stprintf( s, _T("%s"), hexstring(disp32, 0) ); - } else - s += _stprintf( s, _T("%s"), i386_reg[1][rm]); - if( mod == 1 ) { - disp8 = _FETCHD(); - if (disp8 != 0) - s += _stprintf( s, _T("%s"), shexstring((INT32)disp8, 0, TRUE) ); - } else if( mod == 2 ) { - disp32 = _FETCHD32(); - if (disp32 != 0) - s += _stprintf( s, _T("%s"), shexstring(disp32, 0, TRUE) ); - } - } else { - switch( rm ) - { - case 0: s += _stprintf( s, _T("bx+si") ); break; - case 1: s += _stprintf( s, _T("bx+di") ); break; - case 2: s += _stprintf( s, _T("bp+si") ); break; - case 3: s += _stprintf( s, _T("bp+di") ); break; - case 4: s += _stprintf( s, _T("si") ); break; - case 5: s += _stprintf( s, _T("di") ); 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("bx") ); break; - } - if( mod == 1 ) { - disp8 = _FETCHD(); - if (disp8 != 0) - s += _stprintf( s, _T("%s"), shexstring((INT32)disp8, 0, TRUE) ); - } else if( mod == 2 ) { - disp16 = _FETCHD16(); - if (disp16 != 0) - s += _stprintf( s, _T("%s"), shexstring((INT32)disp16, 0, TRUE) ); - } - } - s += _stprintf( s, _T("]") ); -} - -_TCHAR* I386_OPS::handle_param(_TCHAR* s, UINT32 param) -{ - UINT8 i8; - UINT16 i16; - UINT32 i32; - UINT16 ptr; - UINT32 addr; - INT8 d8; - INT16 d16; - INT32 d32; - - switch(param) - { - case PARAM_REG: - s += _stprintf( s, _T("%s"), i386_reg[operand_size][MODRM_REG1 | regex] ); - break; - - case PARAM_REG8: - s += _stprintf( s, _T("%s"), (rex ? i386_reg8rex : i386_reg8)[MODRM_REG1 | regex] ); - break; - - case PARAM_REG16: - s += _stprintf( s, _T("%s"), i386_reg[0][MODRM_REG1 | regex] ); - break; - - case PARAM_REG32: - s += _stprintf( s, _T("%s"), i386_reg[1][MODRM_REG1 | regex] ); - break; - - case PARAM_REG3264: - s += _stprintf( s, _T("%s"), i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG1 | regex] ); - break; - - case PARAM_MMX: - if (pre0f == 0x66 || pre0f == 0xf2 || pre0f == 0xf3) - s += _stprintf( s, _T("xmm%d"), MODRM_REG1 | regex ); - else - s += _stprintf( s, _T("mm%d"), MODRM_REG1 | regex ); - break; - - case PARAM_MMX2: - if (pre0f == 0x66 || pre0f == 0xf2 || pre0f == 0xf3) - s += _stprintf( s, _T("xmm%d"), MODRM_REG2 | regex ); - else - s += _stprintf( s, _T("mm%d"), MODRM_REG2 | regex ); - break; - - case PARAM_XMM: - s += _stprintf( s, _T("xmm%d"), MODRM_REG1 | regex ); - break; - - case PARAM_REGORXMM: - if (pre0f != 0xf2 && pre0f != 0xf3) - s += _stprintf( s, _T("xmm%d"), MODRM_REG1 | regex ); - else - s += _stprintf( s, _T("%s"), i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG1 | regex] ); - break; - - case PARAM_REG2_32: - s += _stprintf( s, _T("%s"), i386_reg[1][MODRM_REG2 | rmex] ); - break; - - case PARAM_RM: - case PARAM_RMPTR: - if( modrm >= 0xc0 ) { - s += _stprintf( s, _T("%s"), i386_reg[operand_size][MODRM_REG2 | rmex] ); - } else { - if (param == PARAM_RMPTR) - { - if( operand_size == 2 ) - s += _stprintf( s, _T("qword ptr ") ); - else if (operand_size == 1) - s += _stprintf( s, _T("dword ptr ") ); - else - s += _stprintf( s, _T("word ptr ") ); - } - s += _stprintf( s, _T("%s"), modrm_string ); - } - break; - - case PARAM_RM8: - case PARAM_RMPTR8: - if( modrm >= 0xc0 ) { - s += _stprintf( s, _T("%s"), (rex ? i386_reg8rex : i386_reg8)[MODRM_REG2 | rmex] ); - } 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"), i386_reg[0][MODRM_REG2 | rmex] ); - } else { - if (param == PARAM_RMPTR16) - s += _stprintf( s, _T("word ptr ") ); - s += _stprintf( s, _T("%s"), modrm_string ); - } - break; - - case PARAM_RM32: - case PARAM_RMPTR32: - if( modrm >= 0xc0 ) { - s += _stprintf( s, _T("%s"), i386_reg[1][MODRM_REG2 | rmex] ); - } else { - if (param == PARAM_RMPTR32) - s += _stprintf( s, _T("dword ptr ") ); - s += _stprintf( s, _T("%s"), modrm_string ); - } - break; - - case PARAM_RMXMM: - if( modrm >= 0xc0 ) { - if (pre0f != 0xf2 && pre0f != 0xf3) - s += _stprintf( s, _T("xmm%d"), MODRM_REG2 | rmex ); - else - s += _stprintf( s, _T("%s"), i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG2 | rmex] ); - } else { - if (param == PARAM_RMPTR32) - s += _stprintf( s, _T("dword ptr ") ); - s += _stprintf( s, _T("%s"), modrm_string ); - } - break; - - case PARAM_M64: - case PARAM_M64PTR: - if( modrm >= 0xc0 ) { - s += _stprintf( s, _T("???") ); - } else { - if (param == PARAM_M64PTR) - s += _stprintf( s, _T("qword ptr ") ); - s += _stprintf( s, _T("%s"), modrm_string ); - } - break; - - case PARAM_MMXM: - if( modrm >= 0xc0 ) { - if (pre0f == 0x66 || pre0f == 0xf2 || pre0f == 0xf3) - s += _stprintf( s, _T("xmm%d"), MODRM_REG2 | rmex ); - else - s += _stprintf( s, _T("mm%d"), MODRM_REG2 | rmex ); - } else { - s += _stprintf( s, _T("%s"), modrm_string ); - } - break; - - case PARAM_XMMM: - if( modrm >= 0xc0 ) { - s += _stprintf( s, _T("xmm%d"), MODRM_REG2 | rmex ); - } else { - s += _stprintf( s, _T("%s"), modrm_string ); - } - 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_UI16: - i16 = _FETCHD16(); - s += _stprintf( s, _T("%s"), shexstring((UINT16)i16, 0, FALSE) ); - break; - - case PARAM_IMM64: - if (operand_size == 2) { - UINT32 lo32 = _FETCHD32(); - i32 = _FETCHD32(); - s += _stprintf( s, _T("%s"), hexstring64(lo32, i32) ); - } else if( operand_size ) { - i32 = _FETCHD32(); - s += _stprintf( s, _T("%s"), hexstring(i32, 0) ); - } else { - i16 = _FETCHD16(); - s += _stprintf( s, _T("%s"), hexstring(i16, 0) ); - } - break; - - case PARAM_IMM: - if( operand_size ) { - i32 = _FETCHD32(); - s += _stprintf( s, _T("%s"), hexstring(i32, 0) ); - } else { - i16 = _FETCHD16(); - s += _stprintf( s, _T("%s"), hexstring(i16, 0) ); - } - break; - - case PARAM_ADDR: - if( operand_size ) { - addr = _FETCHD32(); - ptr = _FETCHD16(); - s += _stprintf( s, _T("%s:"), hexstring(ptr, 4) ); - s += _stprintf( s, _T("%s"), hexstring(addr, 0) ); - } else { - addr = _FETCHD16(); - ptr = _FETCHD16(); - s += _stprintf( s, _T("%s:"), hexstring(ptr, 4) ); - s += _stprintf( s, _T("%s"), hexstring(addr, 0) ); - } - break; - - case PARAM_REL: - if( operand_size ) { - d32 = _FETCHD32(); - s += _stprintf( s, _T("%s"), hexstringpc(pc + d32) ); - } else { - /* make sure to keep the relative offset within the segment */ - d16 = _FETCHD16(); - s += _stprintf( s, _T("%s"), hexstringpc((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF)) ); - } - break; - - case PARAM_REL8: - d8 = _FETCHD(); - s += _stprintf( s, _T("%s"), hexstringpc(pc + d8) ); - break; - - case PARAM_MEM_OFFS: - switch(segment) - { - case SEG_CS: s += _stprintf( s, _T("cs:") ); break; - case SEG_DS: s += _stprintf( s, _T("ds:") ); break; - case SEG_ES: s += _stprintf( s, _T("es:") ); break; - case SEG_FS: s += _stprintf( s, _T("fs:") ); break; - case SEG_GS: s += _stprintf( s, _T("gs:") ); break; - case SEG_SS: s += _stprintf( s, _T("ss:") ); break; - } - - if( address_size ) { - i32 = _FETCHD32(); - s += _stprintf( s, _T("[%s]"), hexstring(i32, 0) ); - } else { - i16 = _FETCHD16(); - s += _stprintf( s, _T("[%s]"), hexstring(i16, 0) ); - } - break; - - case PARAM_PREIMP: - switch(segment) - { - case SEG_CS: s += _stprintf( s, _T("cs:") ); break; - case SEG_DS: s += _stprintf( s, _T("ds:") ); break; - case SEG_ES: s += _stprintf( s, _T("es:") ); break; - case SEG_FS: s += _stprintf( s, _T("fs:") ); break; - case SEG_GS: s += _stprintf( s, _T("gs:") ); break; - case SEG_SS: s += _stprintf( s, _T("ss:") ); break; - } - break; - - case PARAM_SREG: - s += _stprintf( s, _T("%s"), i386_sreg[MODRM_REG1] ); - break; - - case PARAM_CREG: - s += _stprintf( s, _T("cr%d"), MODRM_REG1 | regex ); - break; - - case PARAM_TREG: - s += _stprintf( s, _T("tr%d"), MODRM_REG1 | regex ); - break; - - case PARAM_DREG: - s += _stprintf( s, _T("dr%d"), MODRM_REG1 | regex ); - break; - - case PARAM_1: - s += _stprintf( s, _T("1") ); - break; - - case PARAM_DX: - s += _stprintf( s, _T("dx") ); - break; - - case PARAM_XMM0: - s += _stprintf( s, _T("xmm0") ); - 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_EAX: s += _stprintf( s, _T("%s"), i386_reg[operand_size][0 | rmex] ); break; - case PARAM_ECX: s += _stprintf( s, _T("%s"), i386_reg[operand_size][1 | rmex] ); break; - case PARAM_EDX: s += _stprintf( s, _T("%s"), i386_reg[operand_size][2 | rmex] ); break; - case PARAM_EBX: s += _stprintf( s, _T("%s"), i386_reg[operand_size][3 | rmex] ); break; - case PARAM_ESP: s += _stprintf( s, _T("%s"), i386_reg[operand_size][4 | rmex] ); break; - case PARAM_EBP: s += _stprintf( s, _T("%s"), i386_reg[operand_size][5 | rmex] ); break; - case PARAM_ESI: s += _stprintf( s, _T("%s"), i386_reg[operand_size][6 | rmex] ); break; - case PARAM_EDI: s += _stprintf( s, _T("%s"), i386_reg[operand_size][7 | rmex] ); break; - } - return s; -} - -void I386_OPS::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("fmul st(0),st(%d)"), op2 & 0x7); break; - case 2: _stprintf(s, _T("fcom st(0),st(%d)"), op2 & 0x7); break; - case 3: _stprintf(s, _T("fcomp st(0),st(%d)"), op2 & 0x7); break; - case 4: _stprintf(s, _T("fsub st(0),st(%d)"), op2 & 0x7); break; - case 5: _stprintf(s, _T("fsubr st(0),st(%d)"), op2 & 0x7); break; - case 6: _stprintf(s, _T("fdiv 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; - case 0x29: - _stprintf(s, _T("fucompp")); 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("fisttp dword ptr %s"), modrm_string); 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("fisttp qword ptr %s"), modrm_string); 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("fisttp word ptr %s"), modrm_string); 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 ax")); 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; - } - } -} - -void I386_OPS::decode_opcode(_TCHAR *s, const I386_OPCODE *op, UINT8 op1) -{ - int i; - UINT8 op2; - - if ((op->flags & SPECIAL64) && (address_size == 2)) - op = &x64_opcode_alt[op->flags >> 24]; - - switch( op->flags & FLAGS_MASK ) - { - case ISREX: - if (curmode == 64) - { - rex = op1; - operand_size = (op1 & 8) ? 2 : 1; - regex = (op1 << 1) & 8; - sibex = (op1 << 2) & 8; - rmex = (op1 << 3) & 8; - op2 = _FETCH(); - decode_opcode( s, &i386_opcode_table1[op2], op1 ); - return; - } - break; - - case OP_SIZE: - rex = regex = sibex = rmex = 0; - if (operand_size < 2 && operand_prefix == 0) - { - operand_size ^= 1; - operand_prefix = 1; - } - op2 = _FETCH(); - decode_opcode( s, &i386_opcode_table1[op2], op2 ); - return; - - case ADDR_SIZE: - rex = regex = sibex = rmex = 0; - if(address_prefix == 0) - { - if (curmode != 64) - address_size ^= 1; - else - address_size ^= 3; - address_prefix = 1; - } - op2 = _FETCH(); - decode_opcode( s, &i386_opcode_table1[op2], op2 ); - return; - - case TWO_BYTE: - if (&opcode_ptr[-2] >= opcode_ptr_base) - pre0f = opcode_ptr[-2]; - op2 = _FETCHD(); - decode_opcode( s, &i386_opcode_table2[op2], op1 ); - return; - - case THREE_BYTE: - op2 = _FETCHD(); - if (opcode_ptr[-2] == 0x38) - decode_opcode( s, &i386_opcode_table0F38[op2], op1 ); - else - decode_opcode( s, &i386_opcode_table0F3A[op2], op1 ); - return; - - case SEG_CS: - case SEG_DS: - case SEG_ES: - case SEG_FS: - case SEG_GS: - case SEG_SS: - rex = regex = sibex = rmex = 0; - segment = op->flags; - op2 = _FETCH(); - decode_opcode( s, &i386_opcode_table1[op2], op2 ); - return; - - case PREFIX: - op2 = _FETCH(); - if ((op2 != 0x0f) && (op2 != 0x90)) - s += _stprintf( s, _T("%-7s "), op->mnemonic ); - if ((op2 == 0x90) && !pre0f) - pre0f = op1; - decode_opcode( s, &i386_opcode_table1[op2], op2 ); - 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 ) { - if (op->flags & GROUP_MOD) - decode_opcode( s, &group_op_table[i].opcode[MODRM_MOD], op1 ); - else - 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; - } - - if ((op->flags & ALWAYS64) && curmode == 64) - operand_size = 2; - - if ((op->flags & VAR_NAME) && operand_size > 0) - { - const _TCHAR *mnemonic = op->mnemonic + _tcslen(op->mnemonic) + 1; - if (operand_size == 2) - mnemonic += _tcslen(mnemonic) + 1; - s += _stprintf( s, _T("%-7s "), mnemonic ); - } - else if (op->flags & VAR_NAME4) - { - const _TCHAR *mnemonic = op->mnemonic; - int which = (pre0f == 0xf3) ? 3 : (pre0f == 0xf2) ? 2 : (pre0f == 0x66) ? 1 : 0; - while (which--) - mnemonic += _tcslen(mnemonic) + 1; - s += _stprintf( s, _T("%-7s "), mnemonic ); - } - else - s += _stprintf( s, _T("%-7s "), 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 I386_OPS::i386_dasm_one_ex(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom, int mode) -{ - UINT8 op; - - opcode_ptr = opcode_ptr_base = oprom; - switch(mode) - { - case 1: /* 8086/8088/80186/80188 */ - address_size = 0; - operand_size = 0; - max_length = 8; /* maximum without redundant prefixes - not enforced by chip */ - break; - case 2: /* 80286 */ - address_size = 0; - operand_size = 0; - max_length = 10; - break; - case 16: /* 80386+ 16-bit code segment */ - address_size = 0; - operand_size = 0; - max_length = 15; - break; - case 32: /* 80386+ 32-bit code segment */ - address_size = 1; - operand_size = 1; - max_length = 15; - break; - case 64: /* x86_64 */ - address_size = 2; - operand_size = 1; - max_length = 15; - break; - } - pc = eip; - dasm_flags = 0; - segment = 0; - curmode = mode; - pre0f = 0; - rex = regex = sibex = rmex = 0; - address_prefix = 0; - operand_prefix = 0; - - op = _FETCH(); - - decode_opcode( buffer, &i386_opcode_table1[op], op ); - return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED; -} - -int I386_OPS::i386_dasm_one(_TCHAR *buffer, offs_t eip, const UINT8 *oprom, int mode) -{ - return i386_dasm_one_ex(buffer, eip, oprom, mode); -} - -int I386_OPS::cpu_disassemble_x86_16(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom) -{ - return i386_dasm_one_ex(buffer, pc, oprom, 16); -} - -int I386_OPS::cpu_disassemble_x86_32(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom) -{ - return i386_dasm_one_ex(buffer, pc, oprom, 32); -} - -int I386_OPS::cpu_disassemble_x86_64(_TCHAR *buffer, UINT64 eip, const UINT8 *oprom) -{ - return i386_dasm_one_ex(buffer, pc, oprom, 64); -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386op16.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386op16.cpp deleted file mode 100644 index df4f2aace..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386op16.cpp +++ /dev/null @@ -1,3803 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -#include "./i386_opdef.h" - -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} - -UINT16 I386_OPS_BASE::I386OP(shift_rotate16)( UINT8 modrm, UINT32 value, UINT8 shift) -{ - UINT32 src = value & 0xffff; - UINT16 dst = value; - - if( shift == 0 ) { - CYCLES_RM(modrm, 3, 7); - } else if( shift == 1 ) { - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm16, 1 */ - cpustate->CF = (src & 0x8000) ? 1 : 0; - dst = (src << 1) + cpustate->CF; - cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm16, 1 */ - cpustate->CF = (src & 0x1) ? 1 : 0; - dst = (cpustate->CF << 15) | (src >> 1); - cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm16, 1 */ - dst = (src << 1) + cpustate->CF; - cpustate->CF = (src & 0x8000) ? 1 : 0; - cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm16, 1 */ - dst = (cpustate->CF << 15) | (src >> 1); - cpustate->CF = src & 0x1; - cpustate->OF = ((src ^ dst) & 0x8000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm16, 1 */ - case 6: - dst = src << 1; - cpustate->CF = (src & 0x8000) ? 1 : 0; - cpustate->OF = (((cpustate->CF << 15) ^ dst) & 0x8000) ? 1 : 0; - SetSZPF16(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm16, 1 */ - dst = src >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = (dst & 0x8000) ? 1 : 0; - SetSZPF16(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm16, 1 */ - dst = (INT16)(src) >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = 0; - SetSZPF16(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - } else { - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm16, i8 */ - if(!(shift & 15)) - { - if(shift & 16) - { - cpustate->CF = src & 1; - cpustate->OF = (src & 1) ^ ((src >> 15) & 1); - } - break; - } - shift &= 15; - dst = ((src & ((UINT16)0xffff >> shift)) << shift) | - ((src & ((UINT16)0xffff << (16-shift))) >> (16-shift)); - cpustate->CF = dst & 0x1; - cpustate->OF = (dst & 1) ^ (dst >> 15); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm16, i8 */ - if(!(shift & 15)) - { - if(shift & 16) - { - cpustate->CF = (src >> 15) & 1; - cpustate->OF = ((src >> 15) & 1) ^ ((src >> 14) & 1); - } - break; - } - shift &= 15; - dst = ((src & ((UINT16)0xffff << shift)) >> shift) | - ((src & ((UINT16)0xffff >> (16-shift))) << (16-shift)); - cpustate->CF = (dst >> 15) & 1; - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm16, i8 */ - shift %= 17; - dst = ((src & ((UINT16)0xffff >> shift)) << shift) | - ((src & ((UINT16)0xffff << (17-shift))) >> (17-shift)) | - (cpustate->CF << (shift-1)); - if(shift) cpustate->CF = (src >> (16-shift)) & 0x1; - cpustate->OF = cpustate->CF ^ ((dst >> 15) & 1); - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm16, i8 */ - shift %= 17; - dst = ((src & ((UINT16)0xffff << shift)) >> shift) | - ((src & ((UINT16)0xffff >> (16-shift))) << (17-shift)) | - (cpustate->CF << (16-shift)); - if(shift) cpustate->CF = (src >> (shift-1)) & 0x1; - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm16, i8 */ - case 6: - shift &= 31; - dst = src << shift; - cpustate->CF = (shift <= 16) && (src & (1 << (16-shift))); - SetSZPF16(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm16, i8 */ - shift &= 31; - dst = src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF16(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm16, i8 */ - shift &= 31; - dst = (INT16)src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF16(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - - } - return dst; -} - - - -void I386_OPS_BASE::I386OP(adc_rm16_r16)() // Opcode 0x11 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = ADC16( dst, src, cpustate->CF); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = ADC16( dst, src, cpustate->CF); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(adc_r16_rm16)() // Opcode 0x13 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - dst = ADC16( dst, src, cpustate->CF); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - dst = ADC16( dst, src, cpustate->CF); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(adc_ax_i16)() // Opcode 0x15 -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - dst = ADC16( dst, src, cpustate->CF); - REG16(AX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(add_rm16_r16)() // Opcode 0x01 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = ADD16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = ADD16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(add_r16_rm16)() // Opcode 0x03 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - dst = ADD16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - dst = ADD16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(add_ax_i16)() // Opcode 0x05 -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - dst = ADD16(dst, src); - REG16(AX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(and_rm16_r16)() // Opcode 0x21 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = AND16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = AND16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(and_r16_rm16)() // Opcode 0x23 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - dst = AND16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - dst = AND16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(and_ax_i16)() // Opcode 0x25 -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - dst = AND16(dst, src); - REG16(AX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(bsf_r16_rm16)() // Opcode 0x0f bc -{ - UINT16 src, dst, temp; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - } - - dst = 0; - - if( src == 0 ) { - cpustate->ZF = 1; - } else { - cpustate->ZF = 0; - temp = 0; - while( (src & (1 << temp)) == 0 ) { - temp++; - dst = temp; - CYCLES(CYCLES_BSF); - } - STORE_REG16(modrm, dst); - } - CYCLES(CYCLES_BSF_BASE); -} - -void I386_OPS_BASE::I386OP(bsr_r16_rm16)() // Opcode 0x0f bd -{ - UINT16 src, dst, temp; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - } - - dst = 0; - - if( src == 0 ) { - cpustate->ZF = 1; - } else { - cpustate->ZF = 0; - dst = temp = 15; - while( (src & (1 << temp)) == 0 ) { - temp--; - dst = temp; - CYCLES(CYCLES_BSR); - } - STORE_REG16(modrm, dst); - } - CYCLES(CYCLES_BSR_BASE); -} - - -void I386_OPS_BASE::I386OP(bt_rm16_r16)() // Opcode 0x0f a3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 bit = LOAD_REG16(modrm); - - if( dst & (1 << (bit & 0xf)) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT16 bit = LOAD_REG16(modrm); - ea += 2*(bit/16); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff), 0, 2); - bit %= 16; - UINT16 dst = READ16(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(btc_rm16_r16)() // Opcode 0x0f bb -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 bit = LOAD_REG16(modrm); - - if( dst & (1 << (bit & 0xf)) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << (bit & 0xf)); - - STORE_RM16(modrm, dst); - CYCLES(CYCLES_BTC_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT16 bit = LOAD_REG16(modrm); - ea += 2*(bit/16); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1, 2); - bit %= 16; - UINT16 dst = READ16(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << bit); - - WRITE16(ea, dst); - CYCLES(CYCLES_BTC_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(btr_rm16_r16)() // Opcode 0x0f b3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 bit = LOAD_REG16(modrm); - - if( dst & (1 << (bit & 0xf)) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << (bit & 0xf)); - - STORE_RM16(modrm, dst); - CYCLES(CYCLES_BTR_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT16 bit = LOAD_REG16(modrm); - ea += 2*(bit/16); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1, 2); - bit %= 16; - UINT16 dst = READ16(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << bit); - - WRITE16(ea, dst); - CYCLES(CYCLES_BTR_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(bts_rm16_r16)() // Opcode 0x0f ab -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 bit = LOAD_REG16(modrm); - - if( dst & (1 << (bit & 0xf)) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << (bit & 0xf)); - - STORE_RM16(modrm, dst); - CYCLES(CYCLES_BTS_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT16 bit = LOAD_REG16(modrm); - ea += 2*(bit/16); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1, 2); - bit %= 16; - UINT16 dst = READ16(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << bit); - - WRITE16(ea, dst); - CYCLES(CYCLES_BTS_REG_MEM); - } -} -// Belows are without PSEUDO_BIOS, sometimes needs to use i386op16_real.cpp . -void I386_OPS_BASE::I386OP(call_abs16)() // Opcode 0x9a -{ - UINT16 offset = FETCH16(); - UINT16 ptr = FETCH16(); - - CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */ - if( PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_call(ptr,offset,0,0); - } - else - { - PUSH16( cpustate->sreg[CS].selector ); - PUSH16( cpustate->eip ); - cpustate->sreg[CS].selector = ptr; - cpustate->performed_intersegment_jump = 1; - cpustate->eip = offset; - i386_load_segment_descriptor(CS); - } - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::I386OP(call_rel16)() // Opcode 0xe8 -{ - INT16 disp = FETCH16(); - - - PUSH16( cpustate->eip ); - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */ -} - -void I386_OPS_BASE::I386OP(cbw)() // Opcode 0x98 -{ - REG16(AX) = (INT16)((INT8)REG8(AL)); - CYCLES(CYCLES_CBW); -} - -void I386_OPS_BASE::I386OP(cmp_rm16_r16)() // Opcode 0x39 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - SUB16(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - SUB16(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(cmp_r16_rm16)() // Opcode 0x3b -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - SUB16(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - SUB16(dst, src); - CYCLES(CYCLES_CMP_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(cmp_ax_i16)() // Opcode 0x3d -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - SUB16(dst, src); - CYCLES(CYCLES_CMP_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(cmpsw)() // Opcode 0xa7 -{ - UINT32 eas, ead; - UINT16 src, dst; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 2 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 2 ); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 2 ); - src = READ16(eas); - dst = READ16(ead); - SUB16(src,dst); - BUMP_SI(2); - BUMP_DI(2); - CYCLES(CYCLES_CMPS); -} - -void I386_OPS_BASE::I386OP(cwd)() // Opcode 0x99 -{ - if( REG16(AX) & 0x8000 ) { - REG16(DX) = 0xffff; - } else { - REG16(DX) = 0x0000; - } - CYCLES(CYCLES_CWD); -} - -void I386_OPS_BASE::I386OP(dec_ax)() // Opcode 0x48 -{ - REG16(AX) = DEC16( REG16(AX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_cx)() // Opcode 0x49 -{ - REG16(CX) = DEC16( REG16(CX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_dx)() // Opcode 0x4a -{ - REG16(DX) = DEC16( REG16(DX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_bx)() // Opcode 0x4b -{ - REG16(BX) = DEC16( REG16(BX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_sp)() // Opcode 0x4c -{ - REG16(SP) = DEC16( REG16(SP) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_bp)() // Opcode 0x4d -{ - REG16(BP) = DEC16( REG16(BP) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_si)() // Opcode 0x4e -{ - REG16(SI) = DEC16( REG16(SI) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_di)() // Opcode 0x4f -{ - REG16(DI) = DEC16( REG16(DI) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(imul_r16_rm16)() // Opcode 0x0f af -{ - UINT8 modrm = FETCH(); - INT32 result; - INT32 src, dst; - if( modrm >= 0xc0 ) { - src = (INT32)(INT16)LOAD_RM16(modrm); - CYCLES(CYCLES_IMUL16_REG_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = (INT32)(INT16)READ16(ea); - CYCLES(CYCLES_IMUL16_REG_MEM); /* TODO: Correct multiply timing */ - } - - dst = (INT32)(INT16)LOAD_REG16(modrm); - result = src * dst; - - STORE_REG16(modrm, (UINT16)result); - - cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); -} - -void I386_OPS_BASE::I386OP(imul_r16_rm16_i16)() // Opcode 0x69 -{ - UINT8 modrm = FETCH(); - INT32 result; - INT32 src, dst; - if( modrm >= 0xc0 ) { - dst = (INT32)(INT16)LOAD_RM16(modrm); - CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - dst = (INT32)(INT16)READ16(ea); - CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ - } - - src = (INT32)(INT16)FETCH16(); - result = src * dst; - - STORE_REG16(modrm, (UINT16)result); - - cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); -} - -void I386_OPS_BASE::I386OP(imul_r16_rm16_i8)() // Opcode 0x6b -{ - UINT8 modrm = FETCH(); - INT32 result; - INT32 src, dst; - if( modrm >= 0xc0 ) { - dst = (INT32)(INT16)LOAD_RM16(modrm); - CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - dst = (INT32)(INT16)READ16(ea); - CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ - } - - src = (INT32)(INT8)FETCH(); - result = src * dst; - - STORE_REG16(modrm, (UINT16)result); - - cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); -} - -void I386_OPS_BASE::I386OP(in_ax_i8)() // Opcode 0xe5 -{ - UINT16 port = FETCH(); - UINT16 data = READPORT16( port); - REG16(AX) = data; - CYCLES(CYCLES_IN_VAR); -} - -void I386_OPS_BASE::I386OP(in_ax_dx)() // Opcode 0xed -{ - UINT16 port = REG16(DX); - UINT16 data = READPORT16( port); - REG16(AX) = data; - CYCLES(CYCLES_IN); -} - -void I386_OPS_BASE::I386OP(inc_ax)() // Opcode 0x40 -{ - REG16(AX) = INC16( REG16(AX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_cx)() // Opcode 0x41 -{ - REG16(CX) = INC16( REG16(CX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_dx)() // Opcode 0x42 -{ - REG16(DX) = INC16( REG16(DX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_bx)() // Opcode 0x43 -{ - REG16(BX) = INC16( REG16(BX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_sp)() // Opcode 0x44 -{ - REG16(SP) = INC16( REG16(SP) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_bp)() // Opcode 0x45 -{ - REG16(BP) = INC16( REG16(BP) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_si)() // Opcode 0x46 -{ - REG16(SI) = INC16( REG16(SI) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_di)() // Opcode 0x47 -{ - REG16(DI) = INC16( REG16(DI) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(iret16)() // Opcode 0xcf -{ - if( PROTECTED_MODE ) - { - i386_protected_mode_iret(0); - } - else - { - /* TODO: #SS(0) exception */ - /* TODO: #GP(0) exception */ - cpustate->eip = POP16(); - cpustate->sreg[CS].selector = POP16(); - set_flags( POP16() ); - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_IRET); -} - -void I386_OPS_BASE::I386OP(ja_rel16)() // Opcode 0x0f 87 -{ - INT16 disp = FETCH16(); - if( cpustate->CF == 0 && cpustate->ZF == 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jbe_rel16)() // Opcode 0x0f 86 -{ - INT16 disp = FETCH16(); - if( cpustate->CF != 0 || cpustate->ZF != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jc_rel16)() // Opcode 0x0f 82 -{ - INT16 disp = FETCH16(); - if( cpustate->CF != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jg_rel16)() // Opcode 0x0f 8f -{ - INT16 disp = FETCH16(); - if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jge_rel16)() // Opcode 0x0f 8d -{ - INT16 disp = FETCH16(); - if(cpustate->SF == cpustate->OF) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jl_rel16)() // Opcode 0x0f 8c -{ - INT16 disp = FETCH16(); - if( (cpustate->SF != cpustate->OF) ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jle_rel16)() // Opcode 0x0f 8e -{ - INT16 disp = FETCH16(); - if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnc_rel16)() // Opcode 0x0f 83 -{ - INT16 disp = FETCH16(); - if( cpustate->CF == 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jno_rel16)() // Opcode 0x0f 81 -{ - INT16 disp = FETCH16(); - if( cpustate->OF == 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnp_rel16)() // Opcode 0x0f 8b -{ - INT16 disp = FETCH16(); - if( cpustate->PF == 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jns_rel16)() // Opcode 0x0f 89 -{ - INT16 disp = FETCH16(); - if( cpustate->SF == 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnz_rel16)() // Opcode 0x0f 85 -{ - INT16 disp = FETCH16(); - if( cpustate->ZF == 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jo_rel16)() // Opcode 0x0f 80 -{ - INT16 disp = FETCH16(); - if( cpustate->OF != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jp_rel16)() // Opcode 0x0f 8a -{ - INT16 disp = FETCH16(); - if( cpustate->PF != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(js_rel16)() // Opcode 0x0f 88 -{ - INT16 disp = FETCH16(); - if( cpustate->SF != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jz_rel16)() // Opcode 0x0f 84 -{ - INT16 disp = FETCH16(); - if( cpustate->ZF != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jcxz16)() // Opcode 0xe3 -{ - INT8 disp = FETCH(); - int val = (cpustate->address_size)?(REG32(ECX) == 0):(REG16(CX) == 0); - if( val ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */ - } else { - CYCLES(CYCLES_JCXZ_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jmp_rel16)() // Opcode 0xe9 -{ - INT16 disp = FETCH16(); - - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */ -} - -void I386_OPS_BASE::I386OP(jmp_abs16)() // Opcode 0xea -{ - UINT16 address = FETCH16(); - UINT16 segment = FETCH16(); - //printf("!!!!!!!!!!!JMP ABS %04x:%04x\n", address, segment); - if( PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_jump(segment,address,0,0); - } - else - { - cpustate->eip = address; - cpustate->sreg[CS].selector = segment; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_JMP_INTERSEG); -} - -void I386_OPS_BASE::I386OP(lea16)() // Opcode 0x8d -{ - UINT8 modrm = FETCH(); - UINT32 ea = GetNonTranslatedEA(modrm,NULL); - STORE_REG16(modrm, ea); - CYCLES(CYCLES_LEA); -} - -void I386_OPS_BASE::I386OP(enter16)() // Opcode 0xc8 -{ - UINT16 framesize = FETCH16(); - UINT8 level = FETCH() % 32; - UINT8 x; - UINT16 frameptr; - PUSH16(REG16(BP)); - - if(!STACK_32BIT) - frameptr = REG16(SP); - else - frameptr = REG32(ESP); - - if(level > 0) - { - for(x=1;xsegment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 2 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 2 ); - } - REG16(AX) = READ16(eas); - BUMP_SI(2); - CYCLES(CYCLES_LODS); -} - -void I386_OPS_BASE::I386OP(loop16)() // Opcode 0xe2 -{ - INT8 disp = FETCH(); - INT32 val = (cpustate->address_size)?(--REG32(ECX)):(--REG16(CX)); - if( val != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */ -} - -void I386_OPS_BASE::I386OP(loopne16)() // Opcode 0xe0 -{ - INT8 disp = FETCH(); - INT32 val = (cpustate->address_size)?(--REG32(ECX)):(--REG16(CX)); - if( val != 0 && cpustate->ZF == 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ -} - -void I386_OPS_BASE::I386OP(loopz16)() // Opcode 0xe1 -{ - INT8 disp = FETCH(); - INT32 val = (cpustate->address_size)?(--REG32(ECX)):(--REG16(CX)); - if( val != 0 && cpustate->ZF != 0 ) { - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ -} - -void I386_OPS_BASE::I386OP(mov_rm16_r16)() // Opcode 0x89 -{ - UINT16 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - STORE_RM16(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); -#if 0 - // NEC PC-9801RA's ITF routine intentionally raise general protection fault :-( - int segment = DS; - if( cpustate->segment_prefix ) { - segment = cpustate->segment_override; - } - if( i386_limit_check(segment, (ea + 1) & 0xffff, 2) == 0 ) { - src = READ16(ea); - STORE_REG16(modrm, src); - } else { - FAULT(FAULT_GP, 0) - } - CYCLES(CYCLES_MOV_MEM_REG); -#else - src = LOAD_REG16(modrm); - WRITE16(ea, src); - CYCLES(CYCLES_MOV_REG_MEM); -#endif - } -} - -void I386_OPS_BASE::I386OP(mov_r16_rm16)() // Opcode 0x8b -{ - UINT16 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - STORE_REG16(modrm, src); - CYCLES(CYCLES_MOV_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(mov_rm16_i16)() // Opcode 0xc7 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 value = FETCH16(); - STORE_RM16(modrm, value); - CYCLES(CYCLES_MOV_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 value = FETCH16(); - WRITE16(ea, value); - CYCLES(CYCLES_MOV_IMM_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_ax_m16)() // Opcode 0xa1 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - /* TODO: Not sure if this is correct... */ - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 0, 2); - } else { - ea = i386_translate( DS, offset, 0, 2 ); - } - REG16(AX) = READ16(ea); - CYCLES(CYCLES_MOV_MEM_ACC); -} - -void I386_OPS_BASE::I386OP(mov_m16_ax)() // Opcode 0xa3 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - /* TODO: Not sure if this is correct... */ - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 1, 2); - } else { - ea = i386_translate( DS, offset, 1, 2); - } - WRITE16( ea, REG16(AX) ); - CYCLES(CYCLES_MOV_ACC_MEM); -} - -void I386_OPS_BASE::I386OP(mov_ax_i16)() // Opcode 0xb8 -{ - REG16(AX) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_cx_i16)() // Opcode 0xb9 -{ - REG16(CX) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_dx_i16)() // Opcode 0xba -{ - REG16(DX) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_bx_i16)() // Opcode 0xbb -{ - REG16(BX) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_sp_i16)() // Opcode 0xbc -{ - REG16(SP) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_bp_i16)() // Opcode 0xbd -{ - REG16(BP) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_si_i16)() // Opcode 0xbe -{ - REG16(SI) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_di_i16)() // Opcode 0xbf -{ - REG16(DI) = FETCH16(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(movsw)() // Opcode 0xa5 -{ - UINT32 eas, ead; - UINT16 v; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 2); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 2); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 2 ); - v = READ16(eas); - WRITE16(ead, v); - BUMP_SI(2); - BUMP_DI(2); - CYCLES(CYCLES_MOVS); -} - -void I386_OPS_BASE::I386OP(movsx_r16_rm8)() // Opcode 0x0f be -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - INT16 src = (INT8)LOAD_RM8(modrm); - STORE_REG16(modrm, src); - CYCLES(CYCLES_MOVSX_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 1); - INT16 src = (INT8)READ8(ea); - STORE_REG16(modrm, src); - CYCLES(CYCLES_MOVSX_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(movzx_r16_rm8)() // Opcode 0x0f b6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 src = (UINT8)LOAD_RM8(modrm); - STORE_REG16(modrm, src); - CYCLES(CYCLES_MOVZX_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 1); - UINT16 src = (UINT8)READ8(ea); - STORE_REG16(modrm, src); - CYCLES(CYCLES_MOVZX_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(or_rm16_r16)() // Opcode 0x09 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = OR16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = OR16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(or_r16_rm16)() // Opcode 0x0b -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - dst = OR16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - dst = OR16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(or_ax_i16)() // Opcode 0x0d -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - dst = OR16(dst, src); - REG16(AX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(out_ax_i8)() // Opcode 0xe7 -{ - UINT16 port = FETCH(); - UINT16 data = REG16(AX); - WRITEPORT16( port, data); - CYCLES(CYCLES_OUT_VAR); -} - -void I386_OPS_BASE::I386OP(out_ax_dx)() // Opcode 0xef -{ - UINT16 port = REG16(DX); - UINT16 data = REG16(AX); - WRITEPORT16( port, data); - CYCLES(CYCLES_OUT); -} - -void I386_OPS_BASE::I386OP(pop_ax)() // Opcode 0x58 -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(AX) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_cx)() // Opcode 0x59 -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(CX) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_dx)() // Opcode 0x5a -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(DX) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_bx)() // Opcode 0x5b -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(BX) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_sp)() // Opcode 0x5c -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(SP) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_bp)() // Opcode 0x5d -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(BP) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_si)() // Opcode 0x5e -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(SI) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_di)() // Opcode 0x5f -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset+1, 2) == 0) - REG16(DI) = POP16(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -bool I386_OPS_BASE::I386OP(pop_seg16)( int segment) -{ - UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - UINT16 value; - bool fault; - if(i386_limit_check(SS,offset, 2) == 0) - { - ea = i386_translate( SS, offset, 0, 2); - value = READ16( ea); - i386_sreg_load(value, segment, &fault); - if(fault) return false; - if(STACK_32BIT) - REG32(ESP) = offset + 2; - else - REG16(SP) = offset + 2; - } - else - { - cpustate->ext = 1; - i386_trap_with_error(FAULT_SS,0,0,0); - return false; - } - CYCLES(CYCLES_POP_SREG); - return true; -} - -void I386_OPS_BASE::I386OP(pop_ds16)() // Opcode 0x1f -{ - I386OP(pop_seg16)( DS); -} - -void I386_OPS_BASE::I386OP(pop_es16)() // Opcode 0x07 -{ - I386OP(pop_seg16)( ES); -} - -void I386_OPS_BASE::I386OP(pop_fs16)() // Opcode 0x0f a1 -{ - I386OP(pop_seg16)( FS); -} - -void I386_OPS_BASE::I386OP(pop_gs16)() // Opcode 0x0f a9 -{ - I386OP(pop_seg16)( GS); -} - -void I386_OPS_BASE::I386OP(pop_ss16)() // Opcode 0x17 -{ - if(!I386OP(pop_seg16)( SS)) return; - if(cpustate->IF != 0) // if external interrupts are enabled - { - cpustate->IF = 0; // reset IF for the next instruction - cpustate->delayed_interrupt_enable = 1; - } -} - -void I386_OPS_BASE::I386OP(pop_rm16)() // Opcode 0x8f -{ - UINT8 modrm = FETCH(); - UINT16 value; - UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - - if(i386_limit_check(SS,offset, 2) == 0) - { - UINT32 temp_sp = REG32(ESP); - value = POP16(); - - if( modrm >= 0xc0 ) { - STORE_RM16(modrm, value); - } else { - ea = GetEA(modrm,1, 2); - try - { - WRITE16(ea, value); - } - catch(UINT64 e) - { - REG32(ESP) = temp_sp; - throw e; - } - } - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_RM); -} - -void I386_OPS_BASE::I386OP(popa)() // Opcode 0x61 -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - - if(i386_limit_check(SS,offset ,16) == 0) - { - REG16(DI) = POP16(); - REG16(SI) = POP16(); - REG16(BP) = POP16(); - REG16(SP) += 2; - REG16(BX) = POP16(); - REG16(DX) = POP16(); - REG16(CX) = POP16(); - REG16(AX) = POP16(); - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POPA); -} - -void I386_OPS_BASE::I386OP(popf)() // Opcode 0x9d -{ - UINT32 value; - UINT32 current = get_flags(); - UINT8 IOPL = (current >> 12) & 0x03; - UINT32 mask = 0x7fd5; - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - - // IOPL can only change if CPL is 0 - if(cpustate->CPL != 0) - mask &= ~0x00003000; - - // IF can only change if CPL is at least as privileged as IOPL - if(cpustate->CPL > IOPL) - mask &= ~0x00000200; - - if(V8086_MODE) - { - if(IOPL < 3) - { - logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc); - FAULT(FAULT_GP,0) // #GP(0) - } - mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode - } - - if(i386_limit_check(SS,offset, 2) == 0) - { - value = POP16(); - set_flags((current & ~mask) | (value & mask)); // mask out reserved bits - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POPF); -} - -void I386_OPS_BASE::I386OP(push_ax)() // Opcode 0x50 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(AX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_cx)() // Opcode 0x51 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(CX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_dx)() // Opcode 0x52 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(DX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_bx)() // Opcode 0x53 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(BX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_sp)() // Opcode 0x54 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(SP) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_bp)() // Opcode 0x55 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(BP) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_si)() // Opcode 0x56 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(SI) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_di)() // Opcode 0x57 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( REG16(DI) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_cs16)() // Opcode 0x0e -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( cpustate->sreg[CS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_ds16)() // Opcode 0x1e -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( cpustate->sreg[DS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_es16)() // Opcode 0x06 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( cpustate->sreg[ES].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_fs16)() // Opcode 0x0f a0 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( cpustate->sreg[FS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_gs16)() // Opcode 0x0f a8 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( cpustate->sreg[GS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_ss16)() // Opcode 0x16 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( cpustate->sreg[SS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_i16)() // Opcode 0x68 -{ - UINT16 value = FETCH16(); - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16(value); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_IMM); -} - -void I386_OPS_BASE::I386OP(pusha)() // Opcode 0x60 -{ - UINT16 temp = REG16(SP); - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 16; - else - offset = (REG16(SP) - 16) & 0xffff; - if(i386_limit_check(SS,offset, 16) == 0) - { - PUSH16( REG16(AX) ); - PUSH16( REG16(CX) ); - PUSH16( REG16(DX) ); - PUSH16( REG16(BX) ); - PUSH16( temp ); - PUSH16( REG16(BP) ); - PUSH16( REG16(SI) ); - PUSH16( REG16(DI) ); - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSHA); -} - -void I386_OPS_BASE::I386OP(pushf)() // Opcode 0x9c -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 2; - else - offset = (REG16(SP) - 2) & 0xffff; - if(i386_limit_check(SS,offset, 2) == 0) - PUSH16( get_flags() & 0xffff ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSHF); -} - -void I386_OPS_BASE::I386OP(ret_near16_i16)() // Opcode 0xc2 -{ - INT16 disp = FETCH16(); - cpustate->eip = POP16(); - REG16(SP) += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ -} - -void I386_OPS_BASE::I386OP(ret_near16)() // Opcode 0xc3 -{ - cpustate->eip = POP16(); - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */ -} - -void I386_OPS_BASE::I386OP(sbb_rm16_r16)() // Opcode 0x19 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = SBB16( dst, src, cpustate->CF); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = SBB16( dst, src, cpustate->CF); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sbb_r16_rm16)() // Opcode 0x1b -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - dst = SBB16( dst, src, cpustate->CF); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - dst = SBB16( dst, src, cpustate->CF); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sbb_ax_i16)() // Opcode 0x1d -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - dst = SBB16( dst, src, cpustate->CF); - REG16(AX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(scasw)() // Opcode 0xaf -{ - UINT32 eas; - UINT16 src, dst; - eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 2); - src = READ16(eas); - dst = REG16(AX); - SUB16(dst, src); - BUMP_DI(2); - CYCLES(CYCLES_SCAS); -} - -void I386_OPS_BASE::I386OP(shld16_i8)() // Opcode 0x0f a4 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0 ) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; - // ppro and above should be (dst >> (32-shift)) - dst = (upper << (shift-16)) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (16-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } - STORE_RM16(modrm, dst); - CYCLES(CYCLES_SHLD_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0 ) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; - dst = (upper << (shift-16)) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (16-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } - WRITE16(ea, dst); - CYCLES(CYCLES_SHLD_MEM); - } -} - -void I386_OPS_BASE::I386OP(shld16_cl)() // Opcode 0x0f a5 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0 ) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; - dst = (upper << (shift-16)) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (16-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } - STORE_RM16(modrm, dst); - CYCLES(CYCLES_SHLD_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0 ) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; - dst = (upper << (shift-16)) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (16-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 15); - SetSZPF16(dst); - } - WRITE16(ea, dst); - CYCLES(CYCLES_SHLD_MEM); - } -} - -void I386_OPS_BASE::I386OP(shrd16_i8)() // Opcode 0x0f ac -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; - dst = (upper >> (shift-16)) | (upper << (32-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (16-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } - STORE_RM16(modrm, dst); - CYCLES(CYCLES_SHRD_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; - dst = (upper >> (shift-16)) | (upper << (32-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (16-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } - WRITE16(ea, dst); - CYCLES(CYCLES_SHRD_MEM); - } -} - -void I386_OPS_BASE::I386OP(shrd16_cl)() // Opcode 0x0f ad -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; - dst = (upper >> (shift-16)) | (upper << (32-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (16-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } - STORE_RM16(modrm, dst); - CYCLES(CYCLES_SHRD_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - UINT16 upper = LOAD_REG16(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0) { - } else if( shift > 15 ) { - cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; - dst = (upper >> (shift-16)) | (upper << (32-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (16-shift)); - cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; - SetSZPF16(dst); - } - WRITE16(ea, dst); - CYCLES(CYCLES_SHRD_MEM); - } -} - -void I386_OPS_BASE::I386OP(stosw)() // Opcode 0xab -{ - UINT32 ead; - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 2); - WRITE16(ead, REG16(AX)); - BUMP_DI(2); - CYCLES(CYCLES_STOS); -} - -void I386_OPS_BASE::I386OP(sub_rm16_r16)() // Opcode 0x29 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = SUB16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = SUB16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sub_r16_rm16)() // Opcode 0x2b -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - dst = SUB16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - dst = SUB16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sub_ax_i16)() // Opcode 0x2d -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - dst = SUB16(dst, src); - REG16(AX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_ax_i16)() // Opcode 0xa9 -{ - UINT16 src = FETCH16(); - UINT16 dst = REG16(AX); - dst = src & dst; - SetSZPF16(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_rm16_r16)() // Opcode 0x85 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = src & dst; - SetSZPF16(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = src & dst; - SetSZPF16(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xchg_ax_cx)() // Opcode 0x91 -{ - UINT16 temp; - temp = REG16(AX); - REG16(AX) = REG16(CX); - REG16(CX) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_ax_dx)() // Opcode 0x92 -{ - UINT16 temp; - temp = REG16(AX); - REG16(AX) = REG16(DX); - REG16(DX) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_ax_bx)() // Opcode 0x93 -{ - UINT16 temp; - temp = REG16(AX); - REG16(AX) = REG16(BX); - REG16(BX) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_ax_sp)() // Opcode 0x94 -{ - UINT16 temp; - temp = REG16(AX); - REG16(AX) = REG16(SP); - REG16(SP) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_ax_bp)() // Opcode 0x95 -{ - UINT16 temp; - temp = REG16(AX); - REG16(AX) = REG16(BP); - REG16(BP) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_ax_si)() // Opcode 0x96 -{ - UINT16 temp; - temp = REG16(AX); - REG16(AX) = REG16(SI); - REG16(SI) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_ax_di)() // Opcode 0x97 -{ - UINT16 temp; - temp = REG16(AX); - REG16(AX) = REG16(DI); - REG16(DI) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_r16_rm16)() // Opcode 0x87 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 src = LOAD_RM16(modrm); - UINT16 dst = LOAD_REG16(modrm); - STORE_REG16(modrm, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_XCHG_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 src = READ16(ea); - UINT16 dst = LOAD_REG16(modrm); - STORE_REG16(modrm, src); - WRITE16(ea, dst); - CYCLES(CYCLES_XCHG_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_rm16_r16)() // Opcode 0x31 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - dst = XOR16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - src = LOAD_REG16(modrm); - dst = READ16(ea); - dst = XOR16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_r16_rm16)() // Opcode 0x33 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - dst = LOAD_REG16(modrm); - dst = XOR16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - dst = LOAD_REG16(modrm); - dst = XOR16(dst, src); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(xor_ax_i16)() // Opcode 0x35 -{ - UINT16 src, dst; - src = FETCH16(); - dst = REG16(AX); - dst = XOR16(dst, src); - REG16(AX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - - - -void I386_OPS_BASE::I386OP(group81_16)() // Opcode 0x81 -{ - UINT32 ea; - UINT16 src, dst; - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: // ADD Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - dst = ADD16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = FETCH16(); - dst = ADD16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 1: // OR Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - dst = OR16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = FETCH16(); - dst = OR16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 2: // ADC Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - dst = ADC16( dst, src, cpustate->CF); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = FETCH16(); - dst = ADC16( dst, src, cpustate->CF); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 3: // SBB Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - dst = SBB16( dst, src, cpustate->CF); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = FETCH16(); - dst = SBB16( dst, src, cpustate->CF); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 4: // AND Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - dst = AND16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = FETCH16(); - dst = AND16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 5: // SUB Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - dst = SUB16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = FETCH16(); - dst = SUB16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 6: // XOR Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - dst = XOR16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = FETCH16(); - dst = XOR16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 7: // CMP Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = FETCH16(); - SUB16(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - ea = GetEA(modrm,0, 2); - dst = READ16(ea); - src = FETCH16(); - SUB16(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } - break; - } -} - -void I386_OPS_BASE::I386OP(group83_16)() // Opcode 0x83 -{ - UINT32 ea; - UINT16 src, dst; - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: // ADD Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = ADD16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = ADD16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 1: // OR Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = OR16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = OR16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 2: // ADC Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = ADC16( dst, src, cpustate->CF); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = ADC16( dst, src, cpustate->CF); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 3: // SBB Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = ((UINT16)(INT16)(INT8)FETCH()); - dst = SBB16( dst, src, cpustate->CF); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = ((UINT16)(INT16)(INT8)FETCH()); - dst = SBB16( dst, src, cpustate->CF); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 4: // AND Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = AND16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = AND16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 5: // SUB Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = SUB16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = SUB16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 6: // XOR Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = XOR16(dst, src); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1, 2); - dst = READ16(ea); - src = (UINT16)(INT16)(INT8)FETCH(); - dst = XOR16(dst, src); - WRITE16(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 7: // CMP Rm16, i16 - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - src = (UINT16)(INT16)(INT8)FETCH(); - SUB16(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - ea = GetEA(modrm,0, 2); - dst = READ16(ea); - src = (UINT16)(INT16)(INT8)FETCH(); - SUB16(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupC1_16)() // Opcode 0xc1 -{ - UINT16 dst; - UINT8 modrm = FETCH(); - UINT8 shift; - - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate16( modrm, dst, shift); - STORE_RM16(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1, 2); - dst = READ16(ea); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate16( modrm, dst, shift); - WRITE16(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD1_16)() // Opcode 0xd1 -{ - UINT16 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - dst = i386_shift_rotate16( modrm, dst, 1); - STORE_RM16(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1, 2); - dst = READ16(ea); - dst = i386_shift_rotate16( modrm, dst, 1); - WRITE16(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD3_16)() // Opcode 0xd3 -{ - UINT16 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM16(modrm); - dst = i386_shift_rotate16( modrm, dst, REG8(CL)); - STORE_RM16(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1, 2); - dst = READ16(ea); - dst = i386_shift_rotate16( modrm, dst, REG8(CL)); - WRITE16(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupF7_16)() // Opcode 0xf7 -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* TEST Rm16, i16 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 src = FETCH16(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF16(dst); - CYCLES(CYCLES_TEST_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - UINT16 dst = READ16(ea); - UINT16 src = FETCH16(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF16(dst); - CYCLES(CYCLES_TEST_IMM_MEM); - } - break; - case 2: /* NOT Rm16 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - dst = ~dst; - STORE_RM16(modrm, dst); - CYCLES(CYCLES_NOT_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - dst = ~dst; - WRITE16(ea, dst); - CYCLES(CYCLES_NOT_MEM); - } - break; - case 3: /* NEG Rm16 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - dst = SUB16( 0, dst ); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_NEG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - dst = SUB16( 0, dst ); - WRITE16(ea, dst); - CYCLES(CYCLES_NEG_MEM); - } - break; - case 4: /* MUL AX, Rm16 */ - { - UINT32 result; - UINT16 src, dst; - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - CYCLES(CYCLES_MUL16_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - CYCLES(CYCLES_MUL16_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = REG16(AX); - result = (UINT32)src * (UINT32)dst; - REG16(DX) = (UINT16)(result >> 16); - REG16(AX) = (UINT16)result; - - cpustate->CF = cpustate->OF = (REG16(DX) != 0); - } - break; - case 5: /* IMUL AX, Rm16 */ - { - INT32 result; - INT32 src, dst; - if( modrm >= 0xc0 ) { - src = (INT32)(INT16)LOAD_RM16(modrm); - CYCLES(CYCLES_IMUL16_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = (INT32)(INT16)READ16(ea); - CYCLES(CYCLES_IMUL16_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = (INT32)(INT16)REG16(AX); - result = src * dst; - - REG16(DX) = (UINT16)(result >> 16); - REG16(AX) = (UINT16)result; - - cpustate->CF = cpustate->OF = !(result == (INT32)(INT16)result); - } - break; - case 6: /* DIV AX, Rm16 */ - { - UINT32 quotient, remainder, result; - UINT16 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - CYCLES(CYCLES_DIV16_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - CYCLES(CYCLES_DIV16_ACC_MEM); - } - - quotient = ((UINT32)(REG16(DX)) << 16) | (UINT32)(REG16(AX)); - if( src ) { - remainder = quotient % (UINT32)src; - result = quotient / (UINT32)src; - if( result > 0xffff ) { - /* TODO: Divide error */ - } else { - REG16(DX) = (UINT16)remainder; - REG16(AX) = (UINT16)result; - - // this flag is actually undefined, enable on non-cyrix - if (cpustate->cpuid_id0 != 0x69727943) - cpustate->CF = 1; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - case 7: /* IDIV AX, Rm16 */ - { - INT32 quotient, remainder, result; - UINT16 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - CYCLES(CYCLES_IDIV16_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - src = READ16(ea); - CYCLES(CYCLES_IDIV16_ACC_MEM); - } - - quotient = (((INT32)REG16(DX)) << 16) | ((UINT32)REG16(AX)); - if( src ) { - remainder = quotient % (INT32)(INT16)src; - result = quotient / (INT32)(INT16)src; - if( result > 0xffff ) { - /* TODO: Divide error */ - } else { - REG16(DX) = (UINT16)remainder; - REG16(AX) = (UINT16)result; - - // this flag is actually undefined, enable on non-cyrix - if (cpustate->cpuid_id0 != 0x69727943) - cpustate->CF = 1; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupFF_16)() // Opcode 0xff -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* INC Rm16 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - dst = INC16(dst); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_INC_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - dst = INC16(dst); - WRITE16(ea, dst); - CYCLES(CYCLES_INC_MEM); - } - break; - case 1: /* DEC Rm16 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - dst = DEC16(dst); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_DEC_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - dst = DEC16(dst); - WRITE16(ea, dst); - CYCLES(CYCLES_DEC_MEM); - } - break; - case 2: /* CALL Rm16 */ - { - UINT16 address; - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - address = READ16(ea); - CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ - } - PUSH16( cpustate->eip ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - break; - case 3: /* CALL FAR Rm16 */ - { - UINT16 address, selector; - if( modrm >= 0xc0 ) - { - report_invalid_modrm( "groupFF_16", modrm); - } - else - { - UINT32 ea = GetEA(modrm,0, 4); - address = READ16(ea + 0); - selector = READ16(ea + 2); - CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_call(selector,address,1,0); - } - else - { - PUSH16( cpustate->sreg[CS].selector ); - PUSH16( cpustate->eip ); - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor( CS ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - } - } - break; - case 4: /* JMP Rm16 */ - { - UINT16 address; - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - address = READ16(ea); - CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ - } - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - break; - case 5: /* JMP FAR Rm16 */ - { - UINT16 address, selector; - - if( modrm >= 0xc0 ) - { - report_invalid_modrm( "groupFF_16", modrm); - } - else - { - UINT32 ea = GetEA(modrm,0, 4); - address = READ16(ea + 0); - selector = READ16(ea + 2); - CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_jump(selector,address,1,0); - } - else - { - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor( CS ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - } - } - break; - case 6: /* PUSH Rm16 */ - { - UINT16 value; - if( modrm >= 0xc0 ) { - value = LOAD_RM16(modrm); - } else { - UINT32 ea = GetEA(modrm,0, 2); - value = READ16(ea); - } - PUSH16(value); - CYCLES(CYCLES_PUSH_RM); - } - break; - default: - report_invalid_modrm( "groupFF_16", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(group0F00_16)() // Opcode 0x0f 00 -{ - UINT32 address, ea; - UINT8 modrm = FETCH(); - I386_SREG seg; - UINT8 result; - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* SLDT */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if( modrm >= 0xc0 ) { - STORE_RM16(modrm, cpustate->ldtr.segment); - CYCLES(CYCLES_SLDT_REG); - } else { - ea = GetEA(modrm,1, 2); - WRITE16( ea, cpustate->ldtr.segment); - CYCLES(CYCLES_SLDT_MEM); - } - } - else - { - i386_trap(6, 0, 0); - } - break; - case 1: /* STR */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if( modrm >= 0xc0 ) { - STORE_RM16(modrm, cpustate->task.segment); - CYCLES(CYCLES_STR_REG); - } else { - ea = GetEA(modrm,1, 2); - WRITE16( ea, cpustate->task.segment); - CYCLES(CYCLES_STR_MEM); - } - } - else - { - i386_trap(6, 0, 0); - } - break; - case 2: /* LLDT */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if(cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - cpustate->ldtr.segment = address; - CYCLES(CYCLES_LLDT_REG); - } else { - ea = GetEA(modrm,0, 2); - cpustate->ldtr.segment = READ16(ea); - CYCLES(CYCLES_LLDT_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = cpustate->ldtr.segment; - i386_load_protected_mode_segment(&seg,NULL); - cpustate->ldtr.limit = seg.limit; - cpustate->ldtr.base = seg.base; - cpustate->ldtr.flags = seg.flags; - } - else - { - i386_trap(6, 0, 0); - } - break; - - case 3: /* LTR */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if(cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - cpustate->task.segment = address; - CYCLES(CYCLES_LTR_REG); - } else { - ea = GetEA(modrm,0, 2); - cpustate->task.segment = READ16(ea); - CYCLES(CYCLES_LTR_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = cpustate->task.segment; - i386_load_protected_mode_segment(&seg,NULL); - - UINT32 addr = ((seg.selector & 4) ? cpustate->ldtr.base : cpustate->gdtr.base) + (seg.selector & ~7) + 5; - i386_translate_address( TRANSLATE_READ, &addr, NULL); - cpustate->program->write_data16(addr, (seg.flags & 0xff) | 2); - - cpustate->task.limit = seg.limit; - cpustate->task.base = seg.base; - cpustate->task.flags = seg.flags | 2; - } - else - { - i386_trap(6, 0, 0); - } - break; - - case 4: /* VERR */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - result = 1; - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - CYCLES(CYCLES_VERR_REG); - } else { - ea = GetEA(modrm,0, 2); - address = READ16(ea); - CYCLES(CYCLES_VERR_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = address; - result = i386_load_protected_mode_segment(&seg,NULL); - // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) - if(!(seg.flags & 0x10)) - result = 0; - // check that the segment is readable - if(seg.flags & 0x10) // is code or data segment - { - if(seg.flags & 0x08) // is code segment, so check if it's readable - { - if(!(seg.flags & 0x02)) - { - result = 0; - } - else - { // check if conforming, these are always readable, regardless of privilege - if(!(seg.flags & 0x04)) - { - // if not conforming, then we must check privilege levels (TODO: current privilege level check) - if(((seg.flags >> 5) & 0x03) < (address & 0x03)) - result = 0; - } - } - } - } - // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) - SetZF(result); - } - else - { - i386_trap(6, 0, 0); - logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n"); - } - break; - - case 5: /* VERW */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - result = 1; - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - CYCLES(CYCLES_VERW_REG); - } else { - ea = GetEA(modrm,0, 2); - address = READ16(ea); - CYCLES(CYCLES_VERW_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = address; - result = i386_load_protected_mode_segment(&seg,NULL); - // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) - if(!(seg.flags & 0x10)) - result = 0; - // check that the segment is writable - if(seg.flags & 0x10) // is code or data segment - { - if(seg.flags & 0x08) // is code segment (and thus, not writable) - { - result = 0; - } - else - { // is data segment - if(!(seg.flags & 0x02)) - result = 0; - } - } - // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) - if(((seg.flags >> 5) & 0x03) < (address & 0x03)) - result = 0; - SetZF(result); - } - else - { - i386_trap(6, 0, 0); - logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n"); - } - break; - - default: - report_invalid_modrm( "group0F00_16", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(group0F01_16)() // Opcode 0x0f 01 -{ - UINT8 modrm = FETCH(); - UINT16 address; - UINT32 ea; - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* SGDT */ - { - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } else { - ea = GetEA(modrm,1, 6); - } - WRITE16(ea, cpustate->gdtr.limit); - WRITE32(ea + 2, cpustate->gdtr.base); - CYCLES(CYCLES_SGDT); - break; - } - case 1: /* SIDT */ - { - if (modrm >= 0xc0) - { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } - else - { - ea = GetEA(modrm,1, 6); - } - WRITE16(ea, cpustate->idtr.limit); - WRITE32(ea + 2, cpustate->idtr.base); - CYCLES(CYCLES_SIDT); - break; - } - case 2: /* LGDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm,0, 6); - } - cpustate->gdtr.limit = READ16(ea); - cpustate->gdtr.base = READ32(ea + 2) & 0xffffff; - CYCLES(CYCLES_LGDT); - break; - } - case 3: /* LIDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm,0, 6); - } - cpustate->idtr.limit = READ16(ea); - cpustate->idtr.base = READ32(ea + 2) & 0xffffff; - CYCLES(CYCLES_LIDT); - break; - } - case 4: /* SMSW */ - { - if( modrm >= 0xc0 ) { - STORE_RM16(modrm, cpustate->cr[0]); - CYCLES(CYCLES_SMSW_REG); - } else { - ea = GetEA(modrm,1, 2); - WRITE16(ea, cpustate->cr[0]); - CYCLES(CYCLES_SMSW_MEM); - } - break; - } - case 6: /* LMSW */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - UINT16 b; - if( modrm >= 0xc0 ) { - b = LOAD_RM16(modrm); - CYCLES(CYCLES_LMSW_REG); - } else { - ea = GetEA(modrm,0, 2); - CYCLES(CYCLES_LMSW_MEM); - b = READ16(ea); - } - if(PROTECTED_MODE) - b |= 0x0001; // cannot return to real mode using this instruction. - cpustate->cr[0] &= ~0x0000000f; - cpustate->cr[0] |= b & 0x0000000f; - break; - } - default: - report_invalid_modrm( "group0F01_16", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(group0FBA_16)() // Opcode 0x0f ba -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 4: /* BT Rm16, i8 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - UINT16 dst = READ16(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_IMM_MEM); - } - break; - case 5: /* BTS Rm16, i8 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << bit); - - STORE_RM16(modrm, dst); - CYCLES(CYCLES_BTS_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << bit); - - WRITE16(ea, dst); - CYCLES(CYCLES_BTS_IMM_MEM); - } - break; - case 6: /* BTR Rm16, i8 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << bit); - - STORE_RM16(modrm, dst); - CYCLES(CYCLES_BTR_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << bit); - - WRITE16(ea, dst); - CYCLES(CYCLES_BTR_IMM_MEM); - } - break; - case 7: /* BTC Rm16, i8 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << bit); - - STORE_RM16(modrm, dst); - CYCLES(CYCLES_BTC_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << bit); - - WRITE16(ea, dst); - CYCLES(CYCLES_BTC_IMM_MEM); - } - break; - default: - report_invalid_modrm( "group0FBA_16", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(lar_r16_rm16)() // Opcode 0x0f 0x02 -{ - UINT8 modrm = FETCH(); - I386_SREG seg; - UINT8 type; - - if(PROTECTED_MODE && !V8086_MODE) - { - memset(&seg,0,sizeof(seg)); - if(modrm >= 0xc0) - { - seg.selector = LOAD_RM16(modrm); - CYCLES(CYCLES_LAR_REG); - } - else - { - UINT32 ea = GetEA(modrm,0, 2); - seg.selector = READ16(ea); - CYCLES(CYCLES_LAR_MEM); - } - if(seg.selector == 0) - { - SetZF(0); // not a valid segment - // logerror("i386 (%08x): LAR: Selector %04x is invalid type.\n",cpustate->pc,seg.selector); - } - else - { - if(!i386_load_protected_mode_segment(&seg,NULL)) - { - SetZF(0); - return; - } - UINT8 DPL = (seg.flags >> 5) & 3; - if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) - { - SetZF(0); - return; - } - if(!(seg.flags & 0x10)) // special segment - { - // check for invalid segment types - type = seg.flags & 0x000f; - if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d) - { - SetZF(0); // invalid segment type - } - else - { - STORE_REG16(modrm,(seg.flags << 8) & 0xff00); - SetZF(1); - } - } - else - { // data or code segment (both are valid for LAR) - STORE_REG16(modrm,(seg.flags << 8) & 0xff00); - SetZF(1); - } - } - } - else - { - // illegal opcode - i386_trap(6,0, 0); - logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n"); - } -} - -void I386_OPS_BASE::I386OP(lsl_r16_rm16)() // Opcode 0x0f 0x03 -{ - UINT8 modrm = FETCH(); - UINT32 limit; - I386_SREG seg; - - if(PROTECTED_MODE && !V8086_MODE) - { - memset(&seg, 0, sizeof(seg)); - if(modrm >= 0xc0) - { - seg.selector = LOAD_RM16(modrm); - } - else - { - UINT32 ea = GetEA(modrm,0, 2); - seg.selector = READ16(ea); - } - if(seg.selector == 0) - { - SetZF(0); // not a valid segment - } - else - { - UINT8 type; - if(!i386_load_protected_mode_segment(&seg,NULL)) - { - SetZF(0); - return; - } - UINT8 DPL = (seg.flags >> 5) & 3; - if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) - { - SetZF(0); - return; - } - type = seg.flags & 0x1f; - switch(type) - { - case 0: - case 4: - case 5: - case 6: - case 7: - case 8: - case 10: - case 12: - case 13: - case 14: - case 15: - SetZF(0); - return; - default: - limit = seg.limit; - STORE_REG16(modrm,limit & 0x0000ffff); - SetZF(1); - } - } - } - else - i386_trap(6, 0, 0); -} - -void I386_OPS_BASE::I386OP(bound_r16_m16_m16)() // Opcode 0x62 -{ - UINT8 modrm; - INT16 val, low, high; - - modrm = FETCH(); - - if (modrm >= 0xc0) - { - low = high = LOAD_RM16(modrm); - } - else - { - UINT32 ea = GetEA(modrm,0, 4); - low = READ16(ea + 0); - high = READ16(ea + 2); - } - val = LOAD_REG16(modrm); - - if ((val < low) || (val > high)) - { - CYCLES(CYCLES_BOUND_OUT_RANGE); - i386_trap(5, 0, 0); - } - else - { - CYCLES(CYCLES_BOUND_IN_RANGE); - } -} - -void I386_OPS_BASE::I386OP(retf16)() // Opcode 0xcb -{ - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_retf(0,0); - } - else - { - cpustate->eip = POP16(); - cpustate->sreg[CS].selector = POP16(); - i386_load_segment_descriptor( CS ); - CHANGE_PC(cpustate->eip); - } - - CYCLES(CYCLES_RET_INTERSEG); -} - -void I386_OPS_BASE::I386OP(retf_i16)() // Opcode 0xca -{ - UINT16 count = FETCH16(); - - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_retf(count,0); - } - else - { - cpustate->eip = POP16(); - cpustate->sreg[CS].selector = POP16(); - i386_load_segment_descriptor( CS ); - CHANGE_PC(cpustate->eip); - REG16(SP) += count; - } - - CYCLES(CYCLES_RET_IMM_INTERSEG); -} - -bool I386_OPS_BASE::I386OP(load_far_pointer16)(int s) -{ - UINT8 modrm = FETCH(); - UINT16 selector; - - if( modrm >= 0xc0 ) { - //logerror("i386: load_far_pointer16 NYI\n"); // don't log, NT will use this a lot - i386_trap(6, 0, 0); - return false; - } else { - UINT32 ea = GetEA(modrm,0, 4); - STORE_REG16(modrm, READ16(ea + 0)); - selector = READ16(ea + 2); - i386_sreg_load(selector,s,NULL); - } - return true; -} - -void I386_OPS_BASE::I386OP(lds16)() // Opcode 0xc5 -{ - if(I386OP(load_far_pointer16)( DS)) - CYCLES(CYCLES_LDS); -} - -void I386_OPS_BASE::I386OP(lss16)() // Opcode 0x0f 0xb2 -{ - if(I386OP(load_far_pointer16)( SS)) - CYCLES(CYCLES_LSS); -} - -void I386_OPS_BASE::I386OP(les16)() // Opcode 0xc4 -{ - if(I386OP(load_far_pointer16)( ES)) - CYCLES(CYCLES_LES); -} - -void I386_OPS_BASE::I386OP(lfs16)() // Opcode 0x0f 0xb4 -{ - if(I386OP(load_far_pointer16)( FS)) - CYCLES(CYCLES_LFS); -} - -void I386_OPS_BASE::I386OP(lgs16)() // Opcode 0x0f 0xb5 -{ - if(I386OP(load_far_pointer16)( GS)) - CYCLES(CYCLES_LGS); -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386op16_real.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386op16_real.cpp deleted file mode 100644 index 3100498fa..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386op16_real.cpp +++ /dev/null @@ -1,255 +0,0 @@ - -#include "../vm.h" -#include "../../emu.h" -#include "./i386_real.h" - -#ifdef I386_PSEUDO_BIOS -#define BIOS_INT(num) if(cpustate->bios != NULL) { \ - uint16_t regs[10], sregs[4]; \ - regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \ - regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \ - regs[8] = 0x0000; regs[9] = 0x0000; \ - sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \ - sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \ - int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \ - if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag)) { \ - REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \ - REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \ - cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \ - CYCLES(CYCLES_IRET); \ - if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \ - uint32_t hi = regs[9]; \ - uint32_t lo = regs[8]; \ - uint32_t addr = (hi << 16) | lo; \ - cpustate->eip = addr; \ - } \ - return; \ - } \ -} - -#define BIOS_CALL_FAR(address) if(cpustate->bios != NULL) { \ - uint16_t regs[10], sregs[4]; \ - regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \ - regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \ - regs[8] = 0x0000; regs[9] = 0x0000; \ - sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \ - sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \ - int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF; \ - if(cpustate->bios->bios_call_far_i86(address, regs, sregs, &ZeroFlag, &CarryFlag)) { \ - REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \ - REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \ - cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \ - CYCLES(CYCLES_RET_INTERSEG); \ - if((regs[8] != 0x0000) || (regs[9] != 0x0000)) { \ - uint32_t hi = regs[9]; \ - uint32_t lo = regs[8]; \ - uint32_t addr = (hi << 16) | lo; \ - cpustate->eip = addr; \ - } \ - return; \ - } \ -} -#endif - -void I386_OPS::i386_call_abs16() // Opcode 0x9a -{ - UINT16 offset = FETCH16(); - UINT16 ptr = FETCH16(); - CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */ - -#ifdef I386_PSEUDO_BIOS - BIOS_CALL_FAR(((ptr << 4) + offset) & cpustate->a20_mask) -#endif - //printf(" \n"); - - if( PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_call(ptr,offset,0,0); - } - else - { - PUSH16( cpustate->sreg[CS].selector ); - PUSH16( cpustate->eip ); - cpustate->sreg[CS].selector = ptr; - cpustate->performed_intersegment_jump = 1; - cpustate->eip = offset; - i386_load_segment_descriptor(CS); - } - CHANGE_PC(cpustate->eip); -} - -void I386_OPS::i386_call_rel16() // Opcode 0xe8 -{ - INT16 disp = FETCH16(); - - PUSH16( cpustate->eip ); - if (cpustate->sreg[CS].d) - { - cpustate->eip += disp; - } - else - { - cpustate->eip = (cpustate->eip + disp) & 0xffff; - } - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */ -} - -void I386_OPS::i386_groupFF_16() // Opcode 0xff -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* INC Rm16 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - dst = INC16(dst); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_INC_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - dst = INC16(dst); - WRITE16(ea, dst); - CYCLES(CYCLES_INC_MEM); - } - break; - case 1: /* DEC Rm16 */ - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - dst = DEC16(dst); - STORE_RM16(modrm, dst); - CYCLES(CYCLES_DEC_REG); - } else { - UINT32 ea = GetEA(modrm,1, 2); - UINT16 dst = READ16(ea); - dst = DEC16(dst); - WRITE16(ea, dst); - CYCLES(CYCLES_DEC_MEM); - } - break; - case 2: /* CALL Rm16 */ - { - UINT16 address; - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - address = READ16(ea); - CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ - } - PUSH16( cpustate->eip ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - break; - case 3: /* CALL FAR Rm16 */ - { - UINT16 address, selector; - if( modrm >= 0xc0 ) - { - report_invalid_modrm( "groupFF_16", modrm); - } - else - { - UINT32 ea = GetEA(modrm,0, 4); - address = READ16(ea + 0); - selector = READ16(ea + 2); - CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ -#ifdef I386_PSEUDO_BIOS - BIOS_CALL_FAR(((selector << 4) + address) & cpustate->a20_mask) -#endif - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_call(selector,address,1,0); - } - else - { - PUSH16( cpustate->sreg[CS].selector ); - PUSH16( cpustate->eip ); - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor( CS ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - } - } - break; - case 4: /* JMP Rm16 */ - { - UINT16 address; - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ - } else { - UINT32 ea = GetEA(modrm,0, 2); - address = READ16(ea); - CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ - } - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - break; - case 5: /* JMP FAR Rm16 */ - { - UINT16 address, selector; - - if( modrm >= 0xc0 ) - { - report_invalid_modrm( "groupFF_16", modrm); - } - else - { - UINT32 ea = GetEA(modrm,0, 4); - address = READ16(ea + 0); - selector = READ16(ea + 2); - CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_jump(selector,address,1,0); - } - else - { - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor( CS ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - } - } - break; - case 6: /* PUSH Rm16 */ - { - UINT16 value; - if( modrm >= 0xc0 ) { - value = LOAD_RM16(modrm); - } else { - UINT32 ea = GetEA(modrm,0, 2); - value = READ16(ea); - } - PUSH16(value); - CYCLES(CYCLES_PUSH_RM); - } - break; - default: - report_invalid_modrm( "groupFF_16", modrm); - break; - } -} - -void I386_OPS::i386__int() // Opcode 0xcd -{ - int interrupt = FETCH(); - CYCLES(CYCLES_INT); - -#ifdef I386_PSEUDO_BIOS - BIOS_INT(interrupt) -#endif - cpustate->ext = 0; // not an external interrupt - i386_trap(interrupt, 1, 0); - cpustate->ext = 1; -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386op32.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386op32.cpp deleted file mode 100644 index bfc9accf4..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386op32.cpp +++ /dev/null @@ -1,3592 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -#include "./i386_opdef.h" -#include "./i386ops.h" - -/* seems to be defined on mingw-gcc */ -#undef i386 - -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} - -UINT32 I386_OPS_BASE::I386OP(shift_rotate32)( UINT8 modrm, UINT32 value, UINT8 shift) -{ - UINT32 dst, src; - dst = value; - src = value; - - if( shift == 0 ) { - CYCLES_RM(modrm, 3, 7); - } else if( shift == 1 ) { - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm32, 1 */ - cpustate->CF = (src & 0x80000000) ? 1 : 0; - dst = (src << 1) + cpustate->CF; - cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm32, 1 */ - cpustate->CF = (src & 0x1) ? 1 : 0; - dst = (cpustate->CF << 31) | (src >> 1); - cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm32, 1 */ - dst = (src << 1) + cpustate->CF; - cpustate->CF = (src & 0x80000000) ? 1 : 0; - cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm32, 1 */ - dst = (cpustate->CF << 31) | (src >> 1); - cpustate->CF = src & 0x1; - cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm32, 1 */ - case 6: - dst = src << 1; - cpustate->CF = (src & 0x80000000) ? 1 : 0; - cpustate->OF = (((cpustate->CF << 31) ^ dst) & 0x80000000) ? 1 : 0; - SetSZPF32(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm32, 1 */ - dst = src >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = (src & 0x80000000) ? 1 : 0; - SetSZPF32(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm32, 1 */ - dst = (INT32)(src) >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = 0; - SetSZPF32(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - - } else { - shift &= 31; - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm32, i8 */ - dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | - ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift)); - cpustate->CF = dst & 0x1; - cpustate->OF = (dst & 1) ^ (dst >> 31); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm32, i8 */ - dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | - ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift)); - cpustate->CF = (dst >> 31) & 0x1; - cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm32, i8 */ - dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | - ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) | - (cpustate->CF << (shift-1)); - cpustate->CF = (src >> (32-shift)) & 0x1; - cpustate->OF = cpustate->CF ^ ((dst >> 31) & 1); - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm32, i8 */ - dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | - ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) | - (cpustate->CF << (32-shift)); - cpustate->CF = (src >> (shift-1)) & 0x1; - cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm32, i8 */ - case 6: - dst = src << shift; - cpustate->CF = (src & (1 << (32-shift))) ? 1 : 0; - SetSZPF32(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm32, i8 */ - dst = src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF32(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm32, i8 */ - dst = (INT32)src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF32(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - - } - return dst; -} - -void I386_OPS_BASE::I386OP(adc_rm32_r32)() // Opcode 0x11 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = ADC32( dst, src, cpustate->CF); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = ADC32( dst, src, cpustate->CF); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(adc_r32_rm32)() // Opcode 0x13 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - dst = ADC32( dst, src, cpustate->CF); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - dst = ADC32( dst, src, cpustate->CF); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(adc_eax_i32)() // Opcode 0x15 -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - dst = ADC32( dst, src, cpustate->CF); - REG32(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(add_rm32_r32)() // Opcode 0x01 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = ADD32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = ADD32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(add_r32_rm32)() // Opcode 0x03 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - dst = ADD32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - dst = ADD32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(add_eax_i32)() // Opcode 0x05 -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - dst = ADD32(dst, src); - REG32(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(and_rm32_r32)() // Opcode 0x21 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = AND32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = AND32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(and_r32_rm32)() // Opcode 0x23 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - dst = AND32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - dst = AND32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(and_eax_i32)() // Opcode 0x25 -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - dst = AND32(dst, src); - REG32(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(bsf_r32_rm32)() // Opcode 0x0f bc -{ - UINT32 src, dst, temp; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - } - - dst = 0; - - if( src == 0 ) { - cpustate->ZF = 1; - } else { - cpustate->ZF = 0; - temp = 0; - while( (src & (1 << temp)) == 0 ) { - temp++; - dst = temp; - CYCLES(CYCLES_BSF); - } - STORE_REG32(modrm, dst); - } - CYCLES(CYCLES_BSF_BASE); -} - -void I386_OPS_BASE::I386OP(bsr_r32_rm32)() // Opcode 0x0f bd -{ - UINT32 src, dst, temp; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - } - - dst = 0; - - if( src == 0 ) { - cpustate->ZF = 1; - } else { - cpustate->ZF = 0; - dst = temp = 31; - while( (src & (1U << temp)) == 0 ) { - temp--; - dst = temp; - CYCLES(CYCLES_BSR); - } - STORE_REG32(modrm, dst); - } - CYCLES(CYCLES_BSR_BASE); -} - -void I386_OPS_BASE::I386OP(bt_rm32_r32)() // Opcode 0x0f a3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 bit = LOAD_REG32(modrm); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT32 bit = LOAD_REG32(modrm); - ea += 4*(bit/32); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),0,4); - bit %= 32; - UINT32 dst = READ32(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(btc_rm32_r32)() // Opcode 0x0f bb -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 bit = LOAD_REG32(modrm); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << bit); - - STORE_RM32(modrm, dst); - CYCLES(CYCLES_BTC_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT32 bit = LOAD_REG32(modrm); - ea += 4*(bit/32); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4); - bit %= 32; - UINT32 dst = READ32(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << bit); - - WRITE32(ea, dst); - CYCLES(CYCLES_BTC_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(btr_rm32_r32)() // Opcode 0x0f b3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 bit = LOAD_REG32(modrm); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << bit); - - STORE_RM32(modrm, dst); - CYCLES(CYCLES_BTR_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT32 bit = LOAD_REG32(modrm); - ea += 4*(bit/32); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4); - bit %= 32; - UINT32 dst = READ32(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << bit); - - WRITE32(ea, dst); - CYCLES(CYCLES_BTR_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(bts_rm32_r32)() // Opcode 0x0f ab -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 bit = LOAD_REG32(modrm); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << bit); - - STORE_RM32(modrm, dst); - CYCLES(CYCLES_BTS_REG_REG); - } else { - UINT8 segment; - UINT32 ea = GetNonTranslatedEA(modrm,&segment); - UINT32 bit = LOAD_REG32(modrm); - ea += 4*(bit/32); - ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4); - bit %= 32; - UINT32 dst = READ32(ea); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << bit); - - WRITE32(ea, dst); - CYCLES(CYCLES_BTS_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(call_abs32)() // Opcode 0x9a -{ - UINT32 offset = FETCH32(); - UINT16 ptr = FETCH16(); - - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_call(ptr,offset,0,1); - } - else - { - PUSH32SEG( cpustate->sreg[CS].selector ); - PUSH32( cpustate->eip ); - cpustate->sreg[CS].selector = ptr; - cpustate->performed_intersegment_jump = 1; - cpustate->eip = offset; - i386_load_segment_descriptor(CS); - } - CYCLES(CYCLES_CALL_INTERSEG); - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::I386OP(call_rel32)() // Opcode 0xe8 -{ - INT32 disp = FETCH32(); - PUSH32( cpustate->eip ); - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */ -} - -void I386_OPS_BASE::I386OP(cdq)() // Opcode 0x99 -{ - if( REG32(EAX) & 0x80000000 ) { - REG32(EDX) = 0xffffffff; - } else { - REG32(EDX) = 0x00000000; - } - CYCLES(CYCLES_CWD); -} - -void I386_OPS_BASE::I386OP(cmp_rm32_r32)() // Opcode 0x39 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - SUB32(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - SUB32(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(cmp_r32_rm32)() // Opcode 0x3b -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - SUB32(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - SUB32(dst, src); - CYCLES(CYCLES_CMP_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(cmp_eax_i32)() // Opcode 0x3d -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - SUB32(dst, src); - CYCLES(CYCLES_CMP_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(cmpsd)() // Opcode 0xa7 -{ - UINT32 eas, ead, src, dst; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 ); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0,4 ); - src = READ32(eas); - dst = READ32(ead); - SUB32(src,dst); - BUMP_SI(4); - BUMP_DI(4); - CYCLES(CYCLES_CMPS); -} - -void I386_OPS_BASE::I386OP(cwde)() // Opcode 0x98 -{ - REG32(EAX) = (INT32)((INT16)REG16(AX)); - CYCLES(CYCLES_CBW); -} - -void I386_OPS_BASE::I386OP(dec_eax)() // Opcode 0x48 -{ - REG32(EAX) = DEC32( REG32(EAX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_ecx)() // Opcode 0x49 -{ - REG32(ECX) = DEC32( REG32(ECX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_edx)() // Opcode 0x4a -{ - REG32(EDX) = DEC32( REG32(EDX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_ebx)() // Opcode 0x4b -{ - REG32(EBX) = DEC32( REG32(EBX) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_esp)() // Opcode 0x4c -{ - REG32(ESP) = DEC32( REG32(ESP) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_ebp)() // Opcode 0x4d -{ - REG32(EBP) = DEC32( REG32(EBP) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_esi)() // Opcode 0x4e -{ - REG32(ESI) = DEC32( REG32(ESI) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(dec_edi)() // Opcode 0x4f -{ - REG32(EDI) = DEC32( REG32(EDI) ); - CYCLES(CYCLES_DEC_REG); -} - -void I386_OPS_BASE::I386OP(imul_r32_rm32)() // Opcode 0x0f af -{ - UINT8 modrm = FETCH(); - INT64 result; - INT64 src, dst; - if( modrm >= 0xc0 ) { - src = (INT64)(INT32)LOAD_RM32(modrm); - CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = (INT64)(INT32)READ32(ea); - CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ - } - - dst = (INT64)(INT32)LOAD_REG32(modrm); - result = src * dst; - - STORE_REG32(modrm, (UINT32)result); - - cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); -} - -void I386_OPS_BASE::I386OP(imul_r32_rm32_i32)() // Opcode 0x69 -{ - UINT8 modrm = FETCH(); - INT64 result; - INT64 src, dst; - if( modrm >= 0xc0 ) { - dst = (INT64)(INT32)LOAD_RM32(modrm); - CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 4); - dst = (INT64)(INT32)READ32(ea); - CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ - } - - src = (INT64)(INT32)FETCH32(); - result = src * dst; - - STORE_REG32(modrm, (UINT32)result); - - cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); -} - -void I386_OPS_BASE::I386OP(imul_r32_rm32_i8)() // Opcode 0x6b -{ - UINT8 modrm = FETCH(); - INT64 result; - INT64 src, dst; - if( modrm >= 0xc0 ) { - dst = (INT64)(INT32)LOAD_RM32(modrm); - CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0, 4); - dst = (INT64)(INT32)READ32(ea); - CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ - } - - src = (INT64)(INT8)FETCH(); - result = src * dst; - - STORE_REG32(modrm, (UINT32)result); - - cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); -} - -void I386_OPS_BASE::I386OP(in_eax_i8)() // Opcode 0xe5 -{ - UINT16 port = FETCH(); - UINT32 data = READPORT32( port); - REG32(EAX) = data; - CYCLES(CYCLES_IN_VAR); -} - -void I386_OPS_BASE::I386OP(in_eax_dx)() // Opcode 0xed -{ - UINT16 port = REG16(DX); - UINT32 data = READPORT32( port); - REG32(EAX) = data; - CYCLES(CYCLES_IN); -} - -void I386_OPS_BASE::I386OP(inc_eax)() // Opcode 0x40 -{ - REG32(EAX) = INC32( REG32(EAX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_ecx)() // Opcode 0x41 -{ - REG32(ECX) = INC32( REG32(ECX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_edx)() // Opcode 0x42 -{ - REG32(EDX) = INC32( REG32(EDX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_ebx)() // Opcode 0x43 -{ - REG32(EBX) = INC32( REG32(EBX) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_esp)() // Opcode 0x44 -{ - REG32(ESP) = INC32( REG32(ESP) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_ebp)() // Opcode 0x45 -{ - REG32(EBP) = INC32( REG32(EBP) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_esi)() // Opcode 0x46 -{ - REG32(ESI) = INC32( REG32(ESI) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(inc_edi)() // Opcode 0x47 -{ - REG32(EDI) = INC32( REG32(EDI) ); - CYCLES(CYCLES_INC_REG); -} - -void I386_OPS_BASE::I386OP(iret32)() // Opcode 0xcf -{ - if( PROTECTED_MODE ) - { - i386_protected_mode_iret(1); - } - else - { - /* TODO: #SS(0) exception */ - /* TODO: #GP(0) exception */ - cpustate->eip = POP32(); - cpustate->sreg[CS].selector = POP32() & 0xffff; - set_flags( POP32() ); - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_IRET); -} - -void I386_OPS_BASE::I386OP(ja_rel32)() // Opcode 0x0f 87 -{ - INT32 disp = FETCH32(); - if( cpustate->CF == 0 && cpustate->ZF == 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jbe_rel32)() // Opcode 0x0f 86 -{ - INT32 disp = FETCH32(); - if( cpustate->CF != 0 || cpustate->ZF != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jc_rel32)() // Opcode 0x0f 82 -{ - INT32 disp = FETCH32(); - if( cpustate->CF != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jg_rel32)() // Opcode 0x0f 8f -{ - INT32 disp = FETCH32(); - if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jge_rel32)() // Opcode 0x0f 8d -{ - INT32 disp = FETCH32(); - if(cpustate->SF == cpustate->OF) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jl_rel32)() // Opcode 0x0f 8c -{ - INT32 disp = FETCH32(); - if( (cpustate->SF != cpustate->OF) ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jle_rel32)() // Opcode 0x0f 8e -{ - INT32 disp = FETCH32(); - if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnc_rel32)() // Opcode 0x0f 83 -{ - INT32 disp = FETCH32(); - if( cpustate->CF == 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jno_rel32)() // Opcode 0x0f 81 -{ - INT32 disp = FETCH32(); - if( cpustate->OF == 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnp_rel32)() // Opcode 0x0f 8b -{ - INT32 disp = FETCH32(); - if( cpustate->PF == 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jns_rel32)() // Opcode 0x0f 89 -{ - INT32 disp = FETCH32(); - if( cpustate->SF == 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnz_rel32)() // Opcode 0x0f 85 -{ - INT32 disp = FETCH32(); - if( cpustate->ZF == 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jo_rel32)() // Opcode 0x0f 80 -{ - INT32 disp = FETCH32(); - if( cpustate->OF != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jp_rel32)() // Opcode 0x0f 8a -{ - INT32 disp = FETCH32(); - if( cpustate->PF != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(js_rel32)() // Opcode 0x0f 88 -{ - INT32 disp = FETCH32(); - if( cpustate->SF != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jz_rel32)() // Opcode 0x0f 84 -{ - INT32 disp = FETCH32(); - if( cpustate->ZF != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jcxz32)() // Opcode 0xe3 -{ - INT8 disp = FETCH(); - int val = (cpustate->address_size)?(REG32(ECX) == 0):(REG16(CX) == 0); - if( val ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */ - } else { - CYCLES(CYCLES_JCXZ_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jmp_rel32)() // Opcode 0xe9 -{ - UINT32 disp = FETCH32(); - /* TODO: Segment limit */ - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */ -} - -void I386_OPS_BASE::I386OP(jmp_abs32)() // Opcode 0xea -{ - UINT32 address = FETCH32(); - UINT16 segment = FETCH16(); - - if( PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_jump(segment,address,0,1); - } - else - { - cpustate->eip = address; - cpustate->sreg[CS].selector = segment; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor(CS); - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_JMP_INTERSEG); -} - -void I386_OPS_BASE::I386OP(lea32)() // Opcode 0x8d -{ - UINT8 modrm = FETCH(); - UINT32 ea = GetNonTranslatedEA(modrm,NULL); - if (!cpustate->address_size) - { - ea &= 0xffff; - } - STORE_REG32(modrm, ea); - CYCLES(CYCLES_LEA); -} - -void I386_OPS_BASE::I386OP(enter32)() // Opcode 0xc8 -{ - UINT16 framesize = FETCH16(); - UINT8 level = FETCH() % 32; - UINT8 x; - UINT32 frameptr; - PUSH32(REG32(EBP)); - if(!STACK_32BIT) - frameptr = REG16(SP); - else - frameptr = REG32(ESP); - - if(level > 0) - { - for(x=1;xsegment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 ); - } - REG32(EAX) = READ32(eas); - BUMP_SI(4); - CYCLES(CYCLES_LODS); -} - -void I386_OPS_BASE::I386OP(loop32)() // Opcode 0xe2 -{ - INT8 disp = FETCH(); - INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX); - if( reg != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */ -} - -void I386_OPS_BASE::I386OP(loopne32)() // Opcode 0xe0 -{ - INT8 disp = FETCH(); - INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX); - if( reg != 0 && cpustate->ZF == 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ -} - -void I386_OPS_BASE::I386OP(loopz32)() // Opcode 0xe1 -{ - INT8 disp = FETCH(); - INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX); - if( reg != 0 && cpustate->ZF != 0 ) { - cpustate->eip += disp; - CHANGE_PC(cpustate->eip); - } - CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ -} - -void I386_OPS_BASE::I386OP(mov_rm32_r32)() // Opcode 0x89 -{ - UINT32 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - STORE_RM32(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - src = LOAD_REG32(modrm); - WRITE32(ea, src); - CYCLES(CYCLES_MOV_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_r32_rm32)() // Opcode 0x8b -{ - UINT32 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOV_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(mov_rm32_i32)() // Opcode 0xc7 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 value = FETCH32(); - STORE_RM32(modrm, value); - CYCLES(CYCLES_MOV_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - UINT32 value = FETCH32(); - WRITE32(ea, value); - CYCLES(CYCLES_MOV_IMM_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_eax_m32)() // Opcode 0xa1 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 0,4 ); - } else { - ea = i386_translate( DS, offset, 0,4 ); - } - REG32(EAX) = READ32(ea); - CYCLES(CYCLES_MOV_MEM_ACC); -} - -void I386_OPS_BASE::I386OP(mov_m32_eax)() // Opcode 0xa3 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 1, 4 ); - } else { - ea = i386_translate( DS, offset, 1, 4 ); - } - WRITE32( ea, REG32(EAX) ); - CYCLES(CYCLES_MOV_ACC_MEM); -} - -void I386_OPS_BASE::I386OP(mov_eax_i32)() // Opcode 0xb8 -{ - REG32(EAX) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_ecx_i32)() // Opcode 0xb9 -{ - REG32(ECX) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_edx_i32)() // Opcode 0xba -{ - REG32(EDX) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_ebx_i32)() // Opcode 0xbb -{ - REG32(EBX) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_esp_i32)() // Opcode 0xbc -{ - REG32(ESP) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_ebp_i32)() // Opcode 0xbd -{ - REG32(EBP) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_esi_i32)() // Opcode 0xbe -{ - REG32(ESI) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_edi_i32)() // Opcode 0xbf -{ - REG32(EDI) = FETCH32(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(movsd)() // Opcode 0xa5 -{ - UINT32 eas, ead, v; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 ); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 ); - v = READ32(eas); - WRITE32(ead, v); - BUMP_SI(4); - BUMP_DI(4); - CYCLES(CYCLES_MOVS); -} - -void I386_OPS_BASE::I386OP(movsx_r32_rm8)() // Opcode 0x0f be -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - INT32 src = (INT8)LOAD_RM8(modrm); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVSX_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 1); - INT32 src = (INT8)READ8(ea); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVSX_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(movsx_r32_rm16)() // Opcode 0x0f bf -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - INT32 src = (INT16)LOAD_RM16(modrm); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVSX_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - INT32 src = (INT16)READ16(ea); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVSX_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(movzx_r32_rm8)() // Opcode 0x0f b6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 src = (UINT8)LOAD_RM8(modrm); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVZX_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 1); - UINT32 src = (UINT8)READ8(ea); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVZX_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(movzx_r32_rm16)() // Opcode 0x0f b7 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 src = (UINT16)LOAD_RM16(modrm); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVZX_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 2); - UINT32 src = (UINT16)READ16(ea); - STORE_REG32(modrm, src); - CYCLES(CYCLES_MOVZX_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(or_rm32_r32)() // Opcode 0x09 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = OR32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = OR32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(or_r32_rm32)() // Opcode 0x0b -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - dst = OR32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - dst = OR32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(or_eax_i32)() // Opcode 0x0d -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - dst = OR32(dst, src); - REG32(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(out_eax_i8)() // Opcode 0xe7 -{ - UINT16 port = FETCH(); - UINT32 data = REG32(EAX); - WRITEPORT32( port, data); - CYCLES(CYCLES_OUT_VAR); -} - -void I386_OPS_BASE::I386OP(out_eax_dx)() // Opcode 0xef -{ - UINT16 port = REG16(DX); - UINT32 data = REG32(EAX); - WRITEPORT32( port, data); - CYCLES(CYCLES_OUT); -} - -void I386_OPS_BASE::I386OP(pop_eax)() // Opcode 0x58 -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(EAX) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_ecx)() // Opcode 0x59 -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(ECX) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_edx)() // Opcode 0x5a -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(EDX) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_ebx)() // Opcode 0x5b -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(EBX) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_esp)() // Opcode 0x5c -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(ESP) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_ebp)() // Opcode 0x5d -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(EBP) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_esi)() // Opcode 0x5e -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(ESI) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(pop_edi)() // Opcode 0x5f -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - REG32(EDI) = POP32(); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_REG_SHORT); -} - -bool I386_OPS_BASE::I386OP(pop_seg32)( int segment) -{ - UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - UINT32 value; - bool fault; - if(i386_limit_check(SS,offset, 4) == 0) - { - ea = i386_translate( SS, offset, 0, 4); - value = READ32( ea); - i386_sreg_load(value, segment, &fault); - if(fault) return false; - if(STACK_32BIT) - REG32(ESP) = offset + 4; - else - REG16(SP) = offset + 4; - } - else - { - cpustate->ext = 1; - i386_trap_with_error(FAULT_SS,0,0,0); - return false; - } - CYCLES(CYCLES_POP_SREG); - return true; -} - -void I386_OPS_BASE::I386OP(pop_ds32)() // Opcode 0x1f -{ - I386OP(pop_seg32)( DS); -} - -void I386_OPS_BASE::I386OP(pop_es32)() // Opcode 0x07 -{ - I386OP(pop_seg32)( ES); -} - -void I386_OPS_BASE::I386OP(pop_fs32)() // Opcode 0x0f a1 -{ - I386OP(pop_seg32)( FS); -} - -void I386_OPS_BASE::I386OP(pop_gs32)() // Opcode 0x0f a9 -{ - I386OP(pop_seg32)( GS); -} - -void I386_OPS_BASE::I386OP(pop_ss32)() // Opcode 0x17 -{ - if(!I386OP(pop_seg32)( SS)) return; - if(cpustate->IF != 0) // if external interrupts are enabled - { - cpustate->IF = 0; // reset IF for the next instruction - cpustate->delayed_interrupt_enable = 1; - } -} - -void I386_OPS_BASE::I386OP(pop_rm32)() // Opcode 0x8f -{ - UINT8 modrm = FETCH(); - UINT32 value; - UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 4) == 0) - { - // be careful here, if the write references the esp register - // it expects the post-pop value but esp must be wound back - // if the write faults - UINT32 temp_sp = REG32(ESP); - value = POP32(); - - if( modrm >= 0xc0 ) { - STORE_RM32(modrm, value); - } else { - ea = GetEA(modrm,1, 4); - try - { - WRITE32(ea, value); - } - catch(UINT64 e) - { - REG32(ESP) = temp_sp; - throw e; - } - } - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POP_RM); -} - -void I386_OPS_BASE::I386OP(popad)() // Opcode 0x61 -{ - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - if(i386_limit_check(SS,offset, 32) == 0) - { - REG32(EDI) = POP32(); - REG32(ESI) = POP32(); - REG32(EBP) = POP32(); - REG32(ESP) += 4; - REG32(EBX) = POP32(); - REG32(EDX) = POP32(); - REG32(ECX) = POP32(); - REG32(EAX) = POP32(); - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POPA); -} - -void I386_OPS_BASE::I386OP(popfd)() // Opcode 0x9d -{ - UINT32 value; - UINT32 current = get_flags(); - UINT8 IOPL = (current >> 12) & 0x03; - UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD - UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); - - // IOPL can only change if CPL is 0 - if(cpustate->CPL != 0) - mask &= ~0x00003000; - - // IF can only change if CPL is at least as privileged as IOPL - if(cpustate->CPL > IOPL) - mask &= ~0x00000200; - - if(V8086_MODE) - { - if(IOPL < 3) - { - logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc); - FAULT(FAULT_GP,0) // #GP(0) - } - mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode - } - - if(i386_limit_check(SS,offset, 4) == 0) - { - value = POP32(); - value &= ~0x00010000; // RF will always return zero - set_flags((current & ~mask) | (value & mask)); // mask out reserved bits - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_POPF); -} - -void I386_OPS_BASE::I386OP(push_eax)() // Opcode 0x50 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(EAX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_ecx)() // Opcode 0x51 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(ECX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_edx)() // Opcode 0x52 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(EDX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_ebx)() // Opcode 0x53 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(EBX) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_esp)() // Opcode 0x54 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(ESP) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_ebp)() // Opcode 0x55 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(EBP) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_esi)() // Opcode 0x56 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(ESI) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_edi)() // Opcode 0x57 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( REG32(EDI) ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_REG_SHORT); -} - -void I386_OPS_BASE::I386OP(push_cs32)() // Opcode 0x0e -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32SEG( cpustate->sreg[CS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_ds32)() // Opcode 0x1e -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32SEG( cpustate->sreg[DS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_es32)() // Opcode 0x06 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32SEG( cpustate->sreg[ES].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_fs32)() // Opcode 0x0f a0 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32SEG( cpustate->sreg[FS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_gs32)() // Opcode 0x0f a8 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32SEG( cpustate->sreg[GS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_ss32)() // Opcode 0x16 -{ - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( cpustate->sreg[SS].selector ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_SREG); -} - -void I386_OPS_BASE::I386OP(push_i32)() // Opcode 0x68 -{ - UINT32 value = FETCH32(); - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32(value); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSH_IMM); -} - -void I386_OPS_BASE::I386OP(pushad)() // Opcode 0x60 -{ - UINT32 temp = REG32(ESP); - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 32; - else - offset = (REG16(SP) - 32) & 0xffff; - if(i386_limit_check(SS,offset, 32) == 0) - { - PUSH32( REG32(EAX) ); - PUSH32( REG32(ECX) ); - PUSH32( REG32(EDX) ); - PUSH32( REG32(EBX) ); - PUSH32( temp ); - PUSH32( REG32(EBP) ); - PUSH32( REG32(ESI) ); - PUSH32( REG32(EDI) ); - } - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSHA); -} - -void I386_OPS_BASE::I386OP(pushfd)() // Opcode 0x9c -{ - if(!cpustate->IOP1 && !cpustate->IOP2 && V8086_MODE) - FAULT(FAULT_GP,0) - UINT32 offset; - if(STACK_32BIT) - offset = REG32(ESP) - 4; - else - offset = (REG16(SP) - 4) & 0xffff; - if(i386_limit_check(SS,offset, 4) == 0) - PUSH32( get_flags() & 0x00fcffff ); - else - FAULT(FAULT_SS,0) - CYCLES(CYCLES_PUSHF); -} - -void I386_OPS_BASE::I386OP(ret_near32_i16)() // Opcode 0xc2 -{ - INT16 disp = FETCH16(); - cpustate->eip = POP32(); - REG32(ESP) += disp; - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ -} - -void I386_OPS_BASE::I386OP(ret_near32)() // Opcode 0xc3 -{ - cpustate->eip = POP32(); - CHANGE_PC(cpustate->eip); - CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */ -} - -void I386_OPS_BASE::I386OP(sbb_rm32_r32)() // Opcode 0x19 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = SBB32( dst, src, cpustate->CF); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = SBB32( dst, src, cpustate->CF); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sbb_r32_rm32)() // Opcode 0x1b -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - dst = SBB32( dst, src, cpustate->CF); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0, 4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - dst = SBB32( dst, src, cpustate->CF); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sbb_eax_i32)() // Opcode 0x1d -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - dst = SBB32( dst, src, cpustate->CF); - REG32(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(scasd)() // Opcode 0xaf -{ - UINT32 eas, src, dst; - eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 4 ); - src = READ32(eas); - dst = REG32(EAX); - SUB32(dst, src); - BUMP_DI(4); - CYCLES(CYCLES_SCAS); -} - -void I386_OPS_BASE::I386OP(shld32_i8)() // Opcode 0x0f a4 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 31); - SetSZPF32(dst); - } - STORE_RM32(modrm, dst); - CYCLES(CYCLES_SHLD_REG); - } else { - UINT32 ea = GetEA(modrm,1, 4); - UINT32 dst = READ32(ea); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 31); - SetSZPF32(dst); - } - WRITE32(ea, dst); - CYCLES(CYCLES_SHLD_MEM); - } -} - -void I386_OPS_BASE::I386OP(shld32_cl)() // Opcode 0x0f a5 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 31); - SetSZPF32(dst); - } - STORE_RM32(modrm, dst); - CYCLES(CYCLES_SHLD_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; - dst = (dst << shift) | (upper >> (32-shift)); - cpustate->OF = cpustate->CF ^ (dst >> 31); - SetSZPF32(dst); - } - WRITE32(ea, dst); - CYCLES(CYCLES_SHLD_MEM); - } -} - -void I386_OPS_BASE::I386OP(shrd32_i8)() // Opcode 0x0f ac -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (32-shift)); - cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; - SetSZPF32(dst); - } - STORE_RM32(modrm, dst); - CYCLES(CYCLES_SHRD_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = FETCH(); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (32-shift)); - cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; - SetSZPF32(dst); - } - WRITE32(ea, dst); - CYCLES(CYCLES_SHRD_MEM); - } -} - -void I386_OPS_BASE::I386OP(shrd32_cl)() // Opcode 0x0f ad -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (32-shift)); - cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; - SetSZPF32(dst); - } - STORE_RM32(modrm, dst); - CYCLES(CYCLES_SHRD_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - UINT32 upper = LOAD_REG32(modrm); - UINT8 shift = REG8(CL); - shift &= 31; - if( shift == 0 ) { - } else { - cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; - dst = (dst >> shift) | (upper << (32-shift)); - cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; - SetSZPF32(dst); - } - WRITE32(ea, dst); - CYCLES(CYCLES_SHRD_MEM); - } -} - -void I386_OPS_BASE::I386OP(stosd)() // Opcode 0xab -{ - UINT32 eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 ); - WRITE32(eas, REG32(EAX)); - BUMP_DI(4); - CYCLES(CYCLES_STOS); -} - -void I386_OPS_BASE::I386OP(sub_rm32_r32)() // Opcode 0x29 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = SUB32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = SUB32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sub_r32_rm32)() // Opcode 0x2b -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - dst = SUB32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - dst = SUB32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sub_eax_i32)() // Opcode 0x2d -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - dst = SUB32(dst, src); - REG32(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_eax_i32)() // Opcode 0xa9 -{ - UINT32 src = FETCH32(); - UINT32 dst = REG32(EAX); - dst = src & dst; - SetSZPF32(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_rm32_r32)() // Opcode 0x85 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = src & dst; - SetSZPF32(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = src & dst; - SetSZPF32(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xchg_eax_ecx)() // Opcode 0x91 -{ - UINT32 temp; - temp = REG32(EAX); - REG32(EAX) = REG32(ECX); - REG32(ECX) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_eax_edx)() // Opcode 0x92 -{ - UINT32 temp; - temp = REG32(EAX); - REG32(EAX) = REG32(EDX); - REG32(EDX) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_eax_ebx)() // Opcode 0x93 -{ - UINT32 temp; - temp = REG32(EAX); - REG32(EAX) = REG32(EBX); - REG32(EBX) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_eax_esp)() // Opcode 0x94 -{ - UINT32 temp; - temp = REG32(EAX); - REG32(EAX) = REG32(ESP); - REG32(ESP) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_eax_ebp)() // Opcode 0x95 -{ - UINT32 temp; - temp = REG32(EAX); - REG32(EAX) = REG32(EBP); - REG32(EBP) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_eax_esi)() // Opcode 0x96 -{ - UINT32 temp; - temp = REG32(EAX); - REG32(EAX) = REG32(ESI); - REG32(ESI) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_eax_edi)() // Opcode 0x97 -{ - UINT32 temp; - temp = REG32(EAX); - REG32(EAX) = REG32(EDI); - REG32(EDI) = temp; - CYCLES(CYCLES_XCHG_REG_REG); -} - -void I386_OPS_BASE::I386OP(xchg_r32_rm32)() // Opcode 0x87 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 src = LOAD_RM32(modrm); - UINT32 dst = LOAD_REG32(modrm); - STORE_REG32(modrm, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_XCHG_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 src = READ32(ea); - UINT32 dst = LOAD_REG32(modrm); - WRITE32(ea, dst); - STORE_REG32(modrm, src); - CYCLES(CYCLES_XCHG_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_rm32_r32)() // Opcode 0x31 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG32(modrm); - dst = LOAD_RM32(modrm); - dst = XOR32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - src = LOAD_REG32(modrm); - dst = READ32(ea); - dst = XOR32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_r32_rm32)() // Opcode 0x33 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - dst = LOAD_REG32(modrm); - dst = XOR32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,4); - src = READ32(ea); - dst = LOAD_REG32(modrm); - dst = XOR32(dst, src); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(xor_eax_i32)() // Opcode 0x35 -{ - UINT32 src, dst; - src = FETCH32(); - dst = REG32(EAX); - dst = XOR32(dst, src); - REG32(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - - - -void I386_OPS_BASE::I386OP(group81_32)() // Opcode 0x81 -{ - UINT32 ea; - UINT32 src, dst; - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: // ADD Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - dst = ADD32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = FETCH32(); - dst = ADD32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 1: // OR Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - dst = OR32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = FETCH32(); - dst = OR32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 2: // ADC Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - dst = ADC32( dst, src, cpustate->CF); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = FETCH32(); - dst = ADC32( dst, src, cpustate->CF); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 3: // SBB Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - dst = SBB32( dst, src, cpustate->CF); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = FETCH32(); - dst = SBB32( dst, src, cpustate->CF); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 4: // AND Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - dst = AND32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = FETCH32(); - dst = AND32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 5: // SUB Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - dst = SUB32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = FETCH32(); - dst = SUB32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 6: // XOR Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - dst = XOR32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = FETCH32(); - dst = XOR32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 7: // CMP Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = FETCH32(); - SUB32(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - ea = GetEA(modrm,0,4); - dst = READ32(ea); - src = FETCH32(); - SUB32(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } - break; - } -} - -void I386_OPS_BASE::I386OP(group83_32)() // Opcode 0x83 -{ - UINT32 ea; - UINT32 src, dst; - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: // ADD Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = ADD32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = ADD32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 1: // OR Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = OR32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = OR32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 2: // ADC Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = ADC32( dst, src, cpustate->CF); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = ADC32( dst, src, cpustate->CF); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 3: // SBB Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = ((UINT32)(INT32)(INT8)FETCH()); - dst = SBB32( dst, src, cpustate->CF); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = ((UINT32)(INT32)(INT8)FETCH()); - dst = SBB32( dst, src, cpustate->CF); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 4: // AND Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = AND32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = AND32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 5: // SUB Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = SUB32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = SUB32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 6: // XOR Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = XOR32(dst, src); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,4); - dst = READ32(ea); - src = (UINT32)(INT32)(INT8)FETCH(); - dst = XOR32(dst, src); - WRITE32(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 7: // CMP Rm32, i32 - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - src = (UINT32)(INT32)(INT8)FETCH(); - SUB32(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - ea = GetEA(modrm,0,4); - dst = READ32(ea); - src = (UINT32)(INT32)(INT8)FETCH(); - SUB32(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupC1_32)() // Opcode 0xc1 -{ - UINT32 dst; - UINT8 modrm = FETCH(); - UINT8 shift; - - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate32( modrm, dst, shift); - STORE_RM32(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,4); - dst = READ32(ea); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate32( modrm, dst, shift); - WRITE32(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD1_32)() // Opcode 0xd1 -{ - UINT32 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - dst = i386_shift_rotate32( modrm, dst, 1); - STORE_RM32(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,4); - dst = READ32(ea); - dst = i386_shift_rotate32( modrm, dst, 1); - WRITE32(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD3_32)() // Opcode 0xd3 -{ - UINT32 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM32(modrm); - dst = i386_shift_rotate32( modrm, dst, REG8(CL)); - STORE_RM32(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,4); - dst = READ32(ea); - dst = i386_shift_rotate32( modrm, dst, REG8(CL)); - WRITE32(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupF7_32)() // Opcode 0xf7 -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* TEST Rm32, i32 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 src = FETCH32(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF32(dst); - CYCLES(CYCLES_TEST_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,0,4); - UINT32 dst = READ32(ea); - UINT32 src = FETCH32(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF32(dst); - CYCLES(CYCLES_TEST_IMM_MEM); - } - break; - case 2: /* NOT Rm32 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - dst = ~dst; - STORE_RM32(modrm, dst); - CYCLES(CYCLES_NOT_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - dst = ~dst; - WRITE32(ea, dst); - CYCLES(CYCLES_NOT_MEM); - } - break; - case 3: /* NEG Rm32 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - dst = SUB32( 0, dst ); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_NEG_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - dst = SUB32( 0, dst ); - WRITE32(ea, dst); - CYCLES(CYCLES_NEG_MEM); - } - break; - case 4: /* MUL EAX, Rm32 */ - { - UINT64 result; - UINT32 src, dst; - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - CYCLES(CYCLES_MUL32_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0,4); - src = READ32(ea); - CYCLES(CYCLES_MUL32_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = REG32(EAX); - result = (UINT64)src * (UINT64)dst; - REG32(EDX) = (UINT32)(result >> 32); - REG32(EAX) = (UINT32)result; - - cpustate->CF = cpustate->OF = (REG32(EDX) != 0); - } - break; - case 5: /* IMUL EAX, Rm32 */ - { - INT64 result; - INT64 src, dst; - if( modrm >= 0xc0 ) { - src = (INT64)(INT32)LOAD_RM32(modrm); - CYCLES(CYCLES_IMUL32_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0,4); - src = (INT64)(INT32)READ32(ea); - CYCLES(CYCLES_IMUL32_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = (INT64)(INT32)REG32(EAX); - result = src * dst; - - REG32(EDX) = (UINT32)(result >> 32); - REG32(EAX) = (UINT32)result; - - cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result); - } - break; - case 6: /* DIV EAX, Rm32 */ - { - UINT64 quotient, remainder, result; - UINT32 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - CYCLES(CYCLES_DIV32_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0,4); - src = READ32(ea); - CYCLES(CYCLES_DIV32_ACC_MEM); - } - - quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX)); - if( src ) { - remainder = quotient % (UINT64)src; - result = quotient / (UINT64)src; - if( result > 0xffffffff ) { - /* TODO: Divide error */ - } else { - REG32(EDX) = (UINT32)remainder; - REG32(EAX) = (UINT32)result; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - case 7: /* IDIV EAX, Rm32 */ - { - INT64 quotient, remainder, result; - UINT32 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - CYCLES(CYCLES_IDIV32_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0,4); - src = READ32(ea); - CYCLES(CYCLES_IDIV32_ACC_MEM); - } - - quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX)); - if( src ) { - remainder = quotient % (INT64)(INT32)src; - result = quotient / (INT64)(INT32)src; - if( result > 0xffffffff ) { - /* TODO: Divide error */ - } else { - REG32(EDX) = (UINT32)remainder; - REG32(EAX) = (UINT32)result; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupFF_32)() // Opcode 0xff -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* INC Rm32 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - dst = INC32(dst); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_INC_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - dst = INC32(dst); - WRITE32(ea, dst); - CYCLES(CYCLES_INC_MEM); - } - break; - case 1: /* DEC Rm32 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - dst = DEC32(dst); - STORE_RM32(modrm, dst); - CYCLES(CYCLES_DEC_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - dst = DEC32(dst); - WRITE32(ea, dst); - CYCLES(CYCLES_DEC_MEM); - } - break; - case 2: /* CALL Rm32 */ - { - UINT32 address; - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ - } else { - UINT32 ea = GetEA(modrm,0,4); - address = READ32(ea); - CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ - } - PUSH32( cpustate->eip ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - break; - case 3: /* CALL FAR Rm32 */ - { - UINT16 selector; - UINT32 address; - - if( modrm >= 0xc0 ) - { - report_invalid_modrm( "groupFF_32", modrm); - } - else - { - UINT32 ea = GetEA(modrm,0,6); - address = READ32(ea + 0); - selector = READ16(ea + 4); - CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_call(selector,address,1,1); - } - else - { - PUSH32SEG( cpustate->sreg[CS].selector ); - PUSH32( cpustate->eip ); - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor( CS ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - } - } - break; - case 4: /* JMP Rm32 */ - { - UINT32 address; - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ - } else { - UINT32 ea = GetEA(modrm,0,4); - address = READ32(ea); - CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ - } - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - break; - case 5: /* JMP FAR Rm32 */ - { - UINT16 selector; - UINT32 address; - - if( modrm >= 0xc0 ) - { - report_invalid_modrm( "groupFF_32", modrm); - } - else - { - UINT32 ea = GetEA(modrm,0,6); - address = READ32(ea + 0); - selector = READ16(ea + 4); - CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_jump(selector,address,1,1); - } - else - { - cpustate->sreg[CS].selector = selector; - cpustate->performed_intersegment_jump = 1; - i386_load_segment_descriptor( CS ); - cpustate->eip = address; - CHANGE_PC(cpustate->eip); - } - } - } - break; - case 6: /* PUSH Rm32 */ - { - UINT32 value; - if( modrm >= 0xc0 ) { - value = LOAD_RM32(modrm); - } else { - UINT32 ea = GetEA(modrm,0,4); - value = READ32(ea); - } - PUSH32(value); - CYCLES(CYCLES_PUSH_RM); - } - break; - default: - report_invalid_modrm( "groupFF_32", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(group0F00_32)() // Opcode 0x0f 00 -{ - UINT32 address, ea; - UINT8 modrm = FETCH(); - I386_SREG seg; - UINT8 result; - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* SLDT */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if( modrm >= 0xc0 ) { - STORE_RM32(modrm, cpustate->ldtr.segment); - CYCLES(CYCLES_SLDT_REG); - } else { - ea = GetEA(modrm,1,2); - WRITE16( ea, cpustate->ldtr.segment); - CYCLES(CYCLES_SLDT_MEM); - } - } - else - { - i386_trap(6, 0, 0); - } - break; - case 1: /* STR */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if( modrm >= 0xc0 ) { - STORE_RM32(modrm, cpustate->task.segment); - CYCLES(CYCLES_STR_REG); - } else { - ea = GetEA(modrm,1,2); - WRITE16( ea, cpustate->task.segment); - CYCLES(CYCLES_STR_MEM); - } - } - else - { - i386_trap(6, 0, 0); - } - break; - case 2: /* LLDT */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if(cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - cpustate->ldtr.segment = address; - CYCLES(CYCLES_LLDT_REG); - } else { - ea = GetEA(modrm,0,4); - cpustate->ldtr.segment = READ32(ea); - CYCLES(CYCLES_LLDT_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = cpustate->ldtr.segment; - i386_load_protected_mode_segment(&seg,NULL); - cpustate->ldtr.limit = seg.limit; - cpustate->ldtr.base = seg.base; - cpustate->ldtr.flags = seg.flags; - } - else - { - i386_trap(6, 0, 0); - } - break; - - case 3: /* LTR */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if(cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - cpustate->task.segment = address; - CYCLES(CYCLES_LTR_REG); - } else { - ea = GetEA(modrm,0,4); - cpustate->task.segment = READ32(ea); - CYCLES(CYCLES_LTR_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = cpustate->task.segment; - i386_load_protected_mode_segment(&seg,NULL); - - UINT32 addr = ((seg.selector & 4) ? cpustate->ldtr.base : cpustate->gdtr.base) + (seg.selector & ~7) + 5; - i386_translate_address( TRANSLATE_READ, &addr, NULL); - cpustate->program->write_data8(addr, (seg.flags & 0xff) | 2); - - cpustate->task.limit = seg.limit; - cpustate->task.base = seg.base; - cpustate->task.flags = seg.flags | 2; - } - else - { - i386_trap(6, 0, 0); - } - break; - - case 4: /* VERR */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - CYCLES(CYCLES_VERR_REG); - } else { - ea = GetEA(modrm,0,4); - address = READ32(ea); - CYCLES(CYCLES_VERR_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = address; - result = i386_load_protected_mode_segment(&seg,NULL); - // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) - if(!(seg.flags & 0x10)) - result = 0; - // check that the segment is readable - if(seg.flags & 0x10) // is code or data segment - { - if(seg.flags & 0x08) // is code segment, so check if it's readable - { - if(!(seg.flags & 0x02)) - { - result = 0; - } - else - { // check if conforming, these are always readable, regardless of privilege - if(!(seg.flags & 0x04)) - { - // if not conforming, then we must check privilege levels (TODO: current privilege level check) - if(((seg.flags >> 5) & 0x03) < (address & 0x03)) - result = 0; - } - } - } - } - // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) - SetZF(result); - } - else - { - i386_trap(6, 0, 0); - logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n"); - } - break; - - case 5: /* VERW */ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - CYCLES(CYCLES_VERW_REG); - } else { - ea = GetEA(modrm,0,2); - address = READ16(ea); - CYCLES(CYCLES_VERW_MEM); - } - memset(&seg, 0, sizeof(seg)); - seg.selector = address; - result = i386_load_protected_mode_segment(&seg,NULL); - // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) - if(!(seg.flags & 0x10)) - result = 0; - // check that the segment is writable - if(seg.flags & 0x10) // is code or data segment - { - if(seg.flags & 0x08) // is code segment (and thus, not writable) - { - result = 0; - } - else - { // is data segment - if(!(seg.flags & 0x02)) - result = 0; - } - } - // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) - if(((seg.flags >> 5) & 0x03) < (address & 0x03)) - result = 0; - SetZF(result); - } - else - { - i386_trap(6, 0, 0); - logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n"); - } - break; - - default: - report_invalid_modrm( "group0F00_32", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(group0F01_32)() // Opcode 0x0f 01 -{ - UINT8 modrm = FETCH(); - UINT32 address, ea; - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* SGDT */ - { - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } else { - ea = GetEA(modrm,1,6); - } - WRITE16(ea, cpustate->gdtr.limit); - WRITE32(ea + 2, cpustate->gdtr.base); - CYCLES(CYCLES_SGDT); - break; - } - case 1: /* SIDT */ - { - if (modrm >= 0xc0) - { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } - else - { - ea = GetEA(modrm,1,6); - } - WRITE16(ea, cpustate->idtr.limit); - WRITE32(ea + 2, cpustate->idtr.base); - CYCLES(CYCLES_SIDT); - break; - } - case 2: /* LGDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm,0,6); - } - cpustate->gdtr.limit = READ16(ea); - cpustate->gdtr.base = READ32(ea + 2); - CYCLES(CYCLES_LGDT); - break; - } - case 3: /* LIDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm,0,6); - } - cpustate->idtr.limit = READ16(ea); - cpustate->idtr.base = READ32(ea + 2); - CYCLES(CYCLES_LIDT); - break; - } - case 4: /* SMSW */ - { - if( modrm >= 0xc0 ) { - // smsw stores all of cr0 into register - STORE_RM32(modrm, cpustate->cr[0]); - CYCLES(CYCLES_SMSW_REG); - } else { - /* always 16-bit memory operand */ - ea = GetEA(modrm,1,2); - WRITE16(ea, cpustate->cr[0]); - CYCLES(CYCLES_SMSW_MEM); - } - break; - } - case 6: /* LMSW */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - UINT16 b; - if( modrm >= 0xc0 ) { - b = LOAD_RM16(modrm); - CYCLES(CYCLES_LMSW_REG); - } else { - ea = GetEA(modrm,0,2); - CYCLES(CYCLES_LMSW_MEM); - b = READ16(ea); - } - if(PROTECTED_MODE) - b |= 0x0001; // cannot return to real mode using this instruction. - cpustate->cr[0] &= ~0x0000000f; - cpustate->cr[0] |= b & 0x0000000f; - break; - } - default: - report_invalid_modrm( "group0F01_32", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(group0FBA_32)() // Opcode 0x0f ba -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 4: /* BT Rm32, i8 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,0,4); - UINT32 dst = READ32(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - - CYCLES(CYCLES_BT_IMM_MEM); - } - break; - case 5: /* BTS Rm32, i8 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << bit); - - STORE_RM32(modrm, dst); - CYCLES(CYCLES_BTS_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst |= (1 << bit); - - WRITE32(ea, dst); - CYCLES(CYCLES_BTS_IMM_MEM); - } - break; - case 6: /* BTR Rm32, i8 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << bit); - - STORE_RM32(modrm, dst); - CYCLES(CYCLES_BTR_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst &= ~(1 << bit); - - WRITE32(ea, dst); - CYCLES(CYCLES_BTR_IMM_MEM); - } - break; - case 7: /* BTC Rm32, i8 */ - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << bit); - - STORE_RM32(modrm, dst); - CYCLES(CYCLES_BTC_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1,4); - UINT32 dst = READ32(ea); - UINT8 bit = FETCH(); - - if( dst & (1 << bit) ) - cpustate->CF = 1; - else - cpustate->CF = 0; - dst ^= (1 << bit); - - WRITE32(ea, dst); - CYCLES(CYCLES_BTC_IMM_MEM); - } - break; - default: - report_invalid_modrm( "group0FBA_32", modrm); - break; - } -} - -void I386_OPS_BASE::I386OP(lar_r32_rm32)() // Opcode 0x0f 0x02 -{ - UINT8 modrm = FETCH(); - I386_SREG seg; - UINT8 type; - - if(PROTECTED_MODE && !V8086_MODE) - { - memset(&seg,0,sizeof(seg)); - if(modrm >= 0xc0) - { - seg.selector = LOAD_RM32(modrm); - CYCLES(CYCLES_LAR_REG); - } - else - { - UINT32 ea = GetEA(modrm,0,4); - seg.selector = READ32(ea); - CYCLES(CYCLES_LAR_MEM); - } - if(seg.selector == 0) - { - SetZF(0); // not a valid segment - } - else - { - UINT64 desc; - if(!i386_load_protected_mode_segment(&seg,&desc)) - { - SetZF(0); - return; - } - UINT8 DPL = (seg.flags >> 5) & 3; - if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) - { - SetZF(0); - return; - } - if(!(seg.flags & 0x10)) // special segment - { - // check for invalid segment types - type = seg.flags & 0x000f; - if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d) - { - SetZF(0); // invalid segment type - } - else - { - STORE_REG32(modrm,(desc>>32) & 0x00ffff00); - SetZF(1); - } - } - else - { - STORE_REG32(modrm,(desc>>32) & 0x00ffff00); - SetZF(1); - } - } - } - else - { - // illegal opcode - i386_trap(6,0, 0); - logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n"); - } -} - -void I386_OPS_BASE::I386OP(lsl_r32_rm32)() // Opcode 0x0f 0x03 -{ - UINT8 modrm = FETCH(); - UINT32 limit; - I386_SREG seg; - - if(PROTECTED_MODE && !V8086_MODE) - { - memset(&seg, 0, sizeof(seg)); - if(modrm >= 0xc0) - { - seg.selector = LOAD_RM32(modrm); - } - else - { - UINT32 ea = GetEA(modrm,0,4); - seg.selector = READ32(ea); - } - if(seg.selector == 0) - { - SetZF(0); // not a valid segment - } - else - { - UINT8 type; - if(!i386_load_protected_mode_segment(&seg,NULL)) - { - SetZF(0); - return; - } - UINT8 DPL = (seg.flags >> 5) & 3; - if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) - { - SetZF(0); - return; - } - type = seg.flags & 0x1f; - switch(type) - { - case 0: - case 4: - case 5: - case 6: - case 7: - case 8: - case 10: - case 12: - case 13: - case 14: - case 15: - SetZF(0); - return; - default: - limit = seg.limit; - STORE_REG32(modrm,limit); - SetZF(1); - } - } - } - else - i386_trap(6, 0, 0); -} - -void I386_OPS_BASE::I386OP(bound_r32_m32_m32)() // Opcode 0x62 -{ - UINT8 modrm; - INT32 val, low, high; - - modrm = FETCH(); - - if (modrm >= 0xc0) - { - low = high = LOAD_RM32(modrm); - } - else - { - UINT32 ea = GetEA(modrm,0,8); - low = READ32(ea + 0); - high = READ32(ea + 4); - } - val = LOAD_REG32(modrm); - - if ((val < low) || (val > high)) - { - CYCLES(CYCLES_BOUND_OUT_RANGE); - i386_trap(5, 0, 0); - } - else - { - CYCLES(CYCLES_BOUND_IN_RANGE); - } -} - -void I386_OPS_BASE::I386OP(retf32)() // Opcode 0xcb -{ - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_retf(0,1); - } - else - { - cpustate->eip = POP32(); - cpustate->sreg[CS].selector = POP32(); - i386_load_segment_descriptor( CS ); - CHANGE_PC(cpustate->eip); - } - - CYCLES(CYCLES_RET_INTERSEG); -} - -void I386_OPS_BASE::I386OP(retf_i32)() // Opcode 0xca -{ - UINT16 count = FETCH16(); - - if(PROTECTED_MODE && !V8086_MODE) - { - i386_protected_mode_retf(count,1); - } - else - { - cpustate->eip = POP32(); - cpustate->sreg[CS].selector = POP32(); - i386_load_segment_descriptor( CS ); - CHANGE_PC(cpustate->eip); - REG32(ESP) += count; - } - - CYCLES(CYCLES_RET_IMM_INTERSEG); -} - -void I386_OPS_BASE::I386OP(load_far_pointer32)( int s) -{ - UINT8 modrm = FETCH(); - UINT16 selector; - - if( modrm >= 0xc0 ) { - report_invalid_modrm( "load_far_pointer32", modrm); - } else { - UINT32 ea = GetEA(modrm,0,6); - STORE_REG32(modrm, READ32(ea + 0)); - selector = READ16(ea + 4); - i386_sreg_load(selector,s,NULL); - } -} - -void I386_OPS_BASE::I386OP(lds32)() // Opcode 0xc5 -{ - I386OP(load_far_pointer32)( DS); - CYCLES(CYCLES_LDS); -} - -void I386_OPS_BASE::I386OP(lss32)() // Opcode 0x0f 0xb2 -{ - I386OP(load_far_pointer32)( SS); - CYCLES(CYCLES_LSS); -} - -void I386_OPS_BASE::I386OP(les32)() // Opcode 0xc4 -{ - I386OP(load_far_pointer32)( ES); - CYCLES(CYCLES_LES); -} - -void I386_OPS_BASE::I386OP(lfs32)() // Opcode 0x0f 0xb4 -{ - I386OP(load_far_pointer32)( FS); - CYCLES(CYCLES_LFS); -} - -void I386_OPS_BASE::I386OP(lgs32)() // Opcode 0x0f 0xb5 -{ - I386OP(load_far_pointer32)( GS); - CYCLES(CYCLES_LGS); -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.cpp deleted file mode 100644 index 8154856ad..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.cpp +++ /dev/null @@ -1,5211 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -#include "./i386_opdef.h" - -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} - - -#if 1 -UINT8 I386_OPS_BASE::I386OP(shift_rotate8)( UINT8 modrm, UINT32 value, UINT8 shift) -{ - UINT32 src = value & 0xff; - UINT8 dst = value; - - if( shift == 0 ) { - CYCLES_RM(modrm, 3, 7); - } else if( shift == 1 ) { - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm8, 1 */ - cpustate->CF = (src & 0x80) ? 1 : 0; - dst = (src << 1) + cpustate->CF; - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm8, 1 */ - cpustate->CF = (src & 0x1) ? 1 : 0; - dst = (cpustate->CF << 7) | (src >> 1); - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm8, 1 */ - dst = (src << 1) + cpustate->CF; - cpustate->CF = (src & 0x80) ? 1 : 0; - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm8, 1 */ - dst = (cpustate->CF << 7) | (src >> 1); - cpustate->CF = src & 0x1; - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm8, 1 */ - case 6: - dst = src << 1; - cpustate->CF = (src & 0x80) ? 1 : 0; - cpustate->OF = (((cpustate->CF << 7) ^ dst) & 0x80) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm8, 1 */ - dst = src >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = (dst & 0x80) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm8, 1 */ - dst = (INT8)(src) >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - - } else { - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm8, i8 */ - if(!(shift & 7)) - { - if(shift & 0x18) - { - cpustate->CF = src & 1; - cpustate->OF = (src & 1) ^ ((src >> 7) & 1); - } - break; - } - shift &= 7; - dst = ((src & ((UINT8)0xff >> shift)) << shift) | - ((src & ((UINT8)0xff << (8-shift))) >> (8-shift)); - cpustate->CF = dst & 0x1; - cpustate->OF = (dst & 1) ^ (dst >> 7); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm8, i8 */ - if(!(shift & 7)) - { - if(shift & 0x18) - { - cpustate->CF = (src >> 7) & 1; - cpustate->OF = ((src >> 7) & 1) ^ ((src >> 6) & 1); - } - break; - } - shift &= 7; - dst = ((src & ((UINT8)0xff << shift)) >> shift) | - ((src & ((UINT8)0xff >> (8-shift))) << (8-shift)); - cpustate->CF = (dst >> 7) & 1; - cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm8, i8 */ - shift %= 9; - dst = ((src & ((UINT8)0xff >> shift)) << shift) | - ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) | - (cpustate->CF << (shift-1)); - if(shift) cpustate->CF = (src >> (8-shift)) & 0x1; - cpustate->OF = cpustate->CF ^ ((dst >> 7) & 1); - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm8, i8 */ - shift %= 9; - dst = ((src & ((UINT8)0xff << shift)) >> shift) | - ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) | - (cpustate->CF << (8-shift)); - if(shift) cpustate->CF = (src >> (shift-1)) & 0x1; - cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm8, i8 */ - case 6: - shift &= 31; - dst = src << shift; - cpustate->CF = (shift <= 8) && ((src >> (8 - shift)) & 1); - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm8, i8 */ - shift &= 31; - dst = src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm8, i8 */ - shift &= 31; - dst = (INT8)src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - } - - return dst; -} - - - -void I386_OPS_BASE::I386OP(adc_rm8_r8)() // Opcode 0x10 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = ADC8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = ADC8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(adc_r8_rm8)() // Opcode 0x12 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = ADC8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = ADC8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(adc_al_i8)() // Opcode 0x14 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = ADC8( dst, src, cpustate->CF); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(add_rm8_r8)() // Opcode 0x00 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = ADD8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = ADD8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(add_r8_rm8)() // Opcode 0x02 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = ADD8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = ADD8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(add_al_i8)() // Opcode 0x04 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = ADD8(dst, src); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(and_rm8_r8)() // Opcode 0x20 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = AND8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = AND8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(and_r8_rm8)() // Opcode 0x22 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = AND8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = AND8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(and_al_i8)() // Opcode 0x24 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = AND8(dst, src); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(clc)() // Opcode 0xf8 -{ - cpustate->CF = 0; - CYCLES(CYCLES_CLC); -} - -void I386_OPS_BASE::I386OP(cld)() // Opcode 0xfc -{ - cpustate->DF = 0; - CYCLES(CYCLES_CLD); -} - -void I386_OPS_BASE::I386OP(cli)() // Opcode 0xfa -{ - if(PROTECTED_MODE) - { - UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); - if(cpustate->CPL > IOPL) - FAULT(FAULT_GP,0); - } - cpustate->IF = 0; - CYCLES(CYCLES_CLI); -} - -void I386_OPS_BASE::I386OP(cmc)() // Opcode 0xf5 -{ - cpustate->CF ^= 1; - CYCLES(CYCLES_CMC); -} - -void I386_OPS_BASE::I386OP(cmp_rm8_r8)() // Opcode 0x38 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(cmp_r8_rm8)() // Opcode 0x3a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - SUB8(dst, src); - CYCLES(CYCLES_CMP_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(cmp_al_i8)() // Opcode 0x3c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - SUB8(dst, src); - CYCLES(CYCLES_CMP_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(cmpsb)() // Opcode 0xa6 -{ - UINT32 eas, ead; - UINT8 src, dst; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 1 ); - src = READ8(eas); - dst = READ8(ead); - SUB8(src, dst); - BUMP_SI(1); - BUMP_DI(1); - CYCLES(CYCLES_CMPS); -} - -void I386_OPS_BASE::I386OP(in_al_i8)() // Opcode 0xe4 -{ - UINT16 port = FETCH(); - UINT8 data = READPORT8( port); - REG8(AL) = data; - CYCLES(CYCLES_IN_VAR); -} - -void I386_OPS_BASE::I386OP(in_al_dx)() // Opcode 0xec -{ - UINT16 port = REG16(DX); - UINT8 data = READPORT8( port); - REG8(AL) = data; - CYCLES(CYCLES_IN); -} - -void I386_OPS_BASE::I386OP(ja_rel8)() // Opcode 0x77 -{ - INT8 disp = FETCH(); - if( cpustate->CF == 0 && cpustate->ZF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jbe_rel8)() // Opcode 0x76 -{ - INT8 disp = FETCH(); - if( cpustate->CF != 0 || cpustate->ZF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jc_rel8)() // Opcode 0x72 -{ - INT8 disp = FETCH(); - if( cpustate->CF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jg_rel8)() // Opcode 0x7f -{ - INT8 disp = FETCH(); - if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jge_rel8)() // Opcode 0x7d -{ - INT8 disp = FETCH(); - if(cpustate->SF == cpustate->OF) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jl_rel8)() // Opcode 0x7c -{ - INT8 disp = FETCH(); - if( (cpustate->SF != cpustate->OF) ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jle_rel8)() // Opcode 0x7e -{ - INT8 disp = FETCH(); - if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnc_rel8)() // Opcode 0x73 -{ - INT8 disp = FETCH(); - if( cpustate->CF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jno_rel8)() // Opcode 0x71 -{ - INT8 disp = FETCH(); - if( cpustate->OF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnp_rel8)() // Opcode 0x7b -{ - INT8 disp = FETCH(); - if( cpustate->PF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jns_rel8)() // Opcode 0x79 -{ - INT8 disp = FETCH(); - if( cpustate->SF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnz_rel8)() // Opcode 0x75 -{ - INT8 disp = FETCH(); - if( cpustate->ZF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jo_rel8)() // Opcode 0x70 -{ - INT8 disp = FETCH(); - if( cpustate->OF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jp_rel8)() // Opcode 0x7a -{ - INT8 disp = FETCH(); - if( cpustate->PF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(js_rel8)() // Opcode 0x78 -{ - INT8 disp = FETCH(); - if( cpustate->SF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jz_rel8)() // Opcode 0x74 -{ - INT8 disp = FETCH(); - if( cpustate->ZF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jmp_rel8)() // Opcode 0xeb -{ - INT8 disp = FETCH(); - NEAR_BRANCH(disp); - CYCLES(CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */ -} - -void I386_OPS_BASE::I386OP(lahf)() // Opcode 0x9f -{ - REG8(AH) = get_flags() & 0xd7; - CYCLES(CYCLES_LAHF); -} - -void I386_OPS_BASE::I386OP(lodsb)() // Opcode 0xac -{ - UINT32 eas; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } - REG8(AL) = READ8(eas); - BUMP_SI(1); - CYCLES(CYCLES_LODS); -} - -void I386_OPS_BASE::I386OP(mov_rm8_r8)() // Opcode 0x88 -{ - UINT8 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - STORE_RM8(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - WRITE8(ea, src); - CYCLES(CYCLES_MOV_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_r8_rm8)() // Opcode 0x8a -{ - UINT8 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - STORE_REG8(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - STORE_REG8(modrm, src); - CYCLES(CYCLES_MOV_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(mov_rm8_i8)() // Opcode 0xc6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 value = FETCH(); - STORE_RM8(modrm, value); - CYCLES(CYCLES_MOV_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 value = FETCH(); - WRITE8(ea, value); - CYCLES(CYCLES_MOV_IMM_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_r32_cr)() // Opcode 0x0f 20 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 cr = (modrm >> 3) & 0x7; - - STORE_RM32(modrm, cpustate->cr[cr]); - CYCLES(CYCLES_MOV_CR_REG); -} - -void I386_OPS_BASE::I386OP(mov_r32_dr)() // Opcode 0x0f 21 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 dr = (modrm >> 3) & 0x7; - - STORE_RM32(modrm, cpustate->dr[dr]); - switch(dr) - { - case 0: - case 1: - case 2: - case 3: - CYCLES(CYCLES_MOV_REG_DR0_3); - break; - case 6: - case 7: - CYCLES(CYCLES_MOV_REG_DR6_7); - break; - } -} - -void I386_OPS_BASE::I386OP(mov_cr_r32)() // Opcode 0x0f 22 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 cr = (modrm >> 3) & 0x7; - UINT32 data = LOAD_RM32(modrm); - switch(cr) - { - case 0: - data &= 0xfffeffff; // wp not supported on 386 - CYCLES(CYCLES_MOV_REG_CR0); -// if (PROTECTED_MODE != BIT(data, 0)) -// debugger_privilege_hook(); - break; - case 2: CYCLES(CYCLES_MOV_REG_CR2); break; - case 3: - CYCLES(CYCLES_MOV_REG_CR3); - vtlb_flush_dynamic(cpustate->vtlb); - break; - case 4: CYCLES(1); break; // TODO - default: - logerror("i386: mov_cr_r32 CR%d!\n", cr); - return; - } - cpustate->cr[cr] = data; -} - -void I386_OPS_BASE::I386OP(mov_dr_r32)() // Opcode 0x0f 23 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 dr = (modrm >> 3) & 0x7; - - cpustate->dr[dr] = LOAD_RM32(modrm); - switch(dr) - { - case 0: - case 1: - case 2: - case 3: - CYCLES(CYCLES_MOV_DR0_3_REG); - break; - case 6: - case 7: - CYCLES(CYCLES_MOV_DR6_7_REG); - break; - default: - logerror("i386: mov_dr_r32 DR%d!\n", dr); - return; - } -} - -void I386_OPS_BASE::I386OP(mov_al_m8)() // Opcode 0xa0 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - /* TODO: Not sure if this is correct... */ - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 0, 1 ); - } else { - ea = i386_translate( DS, offset, 0, 1 ); - } - REG8(AL) = READ8(ea); - CYCLES(CYCLES_MOV_IMM_MEM); -} - -void I386_OPS_BASE::I386OP(mov_m8_al)() // Opcode 0xa2 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - /* TODO: Not sure if this is correct... */ - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 1, 1 ); - } else { - ea = i386_translate( DS, offset, 1, 1 ); - } - WRITE8( ea, REG8(AL) ); - CYCLES(CYCLES_MOV_MEM_ACC); -} - -void I386_OPS_BASE::I386OP(mov_rm16_sreg)() // Opcode 0x8c -{ - UINT8 modrm = FETCH(); - int s = (modrm >> 3) & 0x7; - - if( modrm >= 0xc0 ) { - if(cpustate->operand_size) - STORE_RM32(modrm, cpustate->sreg[s].selector); - else - STORE_RM16(modrm, cpustate->sreg[s].selector); - CYCLES(CYCLES_MOV_SREG_REG); - } else { - UINT32 ea = GetEA(modrm,1,2); - WRITE16(ea, cpustate->sreg[s].selector); - CYCLES(CYCLES_MOV_SREG_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_sreg_rm16)() // Opcode 0x8e -{ - UINT16 selector; - UINT8 modrm = FETCH(); - bool fault; - int s = (modrm >> 3) & 0x7; - - if( modrm >= 0xc0 ) { - selector = LOAD_RM16(modrm); - CYCLES(CYCLES_MOV_REG_SREG); - } else { - UINT32 ea = GetEA(modrm,0,2); - selector = READ16(ea); - CYCLES(CYCLES_MOV_MEM_SREG); - } - - i386_sreg_load(selector,s,&fault); - if((s == SS) && !fault) - { - if(cpustate->IF != 0) // if external interrupts are enabled - { - cpustate->IF = 0; // reset IF for the next instruction - cpustate->delayed_interrupt_enable = 1; - } - } -} - -void I386_OPS_BASE::I386OP(mov_al_i8)() // Opcode 0xb0 -{ - REG8(AL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_cl_i8)() // Opcode 0xb1 -{ - REG8(CL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_dl_i8)() // Opcode 0xb2 -{ - REG8(DL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_bl_i8)() // Opcode 0xb3 -{ - REG8(BL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_ah_i8)() // Opcode 0xb4 -{ - REG8(AH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_ch_i8)() // Opcode 0xb5 -{ - REG8(CH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_dh_i8)() // Opcode 0xb6 -{ - REG8(DH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_bh_i8)() // Opcode 0xb7 -{ - REG8(BH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(movsb)() // Opcode 0xa4 -{ - UINT32 eas, ead; - UINT8 v; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 ); - v = READ8(eas); - WRITE8(ead, v); - BUMP_SI(1); - BUMP_DI(1); - CYCLES(CYCLES_MOVS); -} - -void I386_OPS_BASE::I386OP(or_rm8_r8)() // Opcode 0x08 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = OR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = OR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(or_r8_rm8)() // Opcode 0x0a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = OR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = OR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(or_al_i8)() // Opcode 0x0c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = OR8(dst, src); - REG8(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(out_al_i8)() // Opcode 0xe6 -{ - UINT16 port = FETCH(); - UINT8 data = REG8(AL); - WRITEPORT8( port, data); - CYCLES(CYCLES_OUT_VAR); -} - -void I386_OPS_BASE::I386OP(out_al_dx)() // Opcode 0xee -{ - UINT16 port = REG16(DX); - UINT8 data = REG8(AL); - WRITEPORT8( port, data); - CYCLES(CYCLES_OUT); -} - - -void I386_OPS_BASE::I386OP(arpl)() // Opcode 0x63 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - UINT8 flag = 0; - - if(PROTECTED_MODE && !V8086_MODE) - { - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - if( (dst&0x3) < (src&0x3) ) { - dst = (dst&0xfffc) | (src&0x3); - flag = 1; - STORE_RM16(modrm, dst); - } - } else { - UINT32 ea = GetEA( modrm,1,2); - src = LOAD_REG16(modrm); - dst = READ16( ea); - if( (dst&0x3) < (src&0x3) ) { - dst = (dst&0xfffc) | (src&0x3); - flag = 1; - WRITE16( ea, dst); - } - } - SetZF(flag); - } - else - i386_trap( 6, 0, 0); // invalid opcode in real mode or v8086 mode -} - -void I386_OPS_BASE::I386OP(push_i8)() // Opcode 0x6a -{ - UINT8 value = FETCH(); - PUSH8(value); - CYCLES(CYCLES_PUSH_IMM); -} - -void I386_OPS_BASE::I386OP(ins_generic)( int size) -{ - UINT32 ead; - UINT8 vb; - UINT16 vw; - UINT32 vd; - - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, size); - - switch(size) { - case 1: - vb = READPORT8( REG16(DX)); - WRITE8(ead, vb); - break; - case 2: - vw = READPORT16( REG16(DX)); - WRITE16(ead, vw); - break; - case 4: - vd = READPORT32( REG16(DX)); - WRITE32(ead, vd); - break; - } - - if(cpustate->address_size) - REG32(EDI) += ((cpustate->DF) ? -1 : 1) * size; - else - REG16(DI) += ((cpustate->DF) ? -1 : 1) * size; - CYCLES(CYCLES_INS); // TODO: Confirm this value -} - -void I386_OPS_BASE::I386OP(insb)() // Opcode 0x6c -{ - I386OP(ins_generic)( 1); -} - -void I386_OPS_BASE::I386OP(insw)() // Opcode 0x6d -{ - I386OP(ins_generic)( 2); -} - -void I386_OPS_BASE::I386OP(insd)() // Opcode 0x6d -{ - I386OP(ins_generic)( 4); -} - -void I386_OPS_BASE::I386OP(outs_generic)( int size) -{ - UINT32 eas; - UINT8 vb; - UINT16 vw; - UINT32 vd; - - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size ); - } - - switch(size) { - case 1: - vb = READ8(eas); - WRITEPORT8( REG16(DX), vb); - break; - case 2: - vw = READ16(eas); - WRITEPORT16( REG16(DX), vw); - break; - case 4: - vd = READ32(eas); - WRITEPORT32( REG16(DX), vd); - break; - } - - if(cpustate->address_size) - REG32(ESI) += ((cpustate->DF) ? -1 : 1) * size; - else - REG16(SI) += ((cpustate->DF) ? -1 : 1) * size; - CYCLES(CYCLES_OUTS); // TODO: Confirm this value -} - -void I386_OPS_BASE::I386OP(outsb)() // Opcode 0x6e -{ - I386OP(outs_generic)( 1); -} - -void I386_OPS_BASE::I386OP(outsw)() // Opcode 0x6f -{ - I386OP(outs_generic)( 2); -} - -void I386_OPS_BASE::I386OP(outsd)() // Opcode 0x6f -{ - I386OP(outs_generic)( 4); -} - -void I386_OPS_BASE::I386OP(repeat)( int invert_flag) -{ - UINT32 repeated_eip = cpustate->eip; - UINT32 repeated_pc = cpustate->pc; - UINT8 opcode; // = FETCH(); -// UINT32 eas, ead; - UINT32 count; - INT32 cycle_base = 0, cycle_adjustment = 0; - UINT8 prefix_flag=1; - UINT8 *flag = NULL; - - - do { - repeated_eip = cpustate->eip; - repeated_pc = cpustate->pc; - opcode = FETCH(); - switch(opcode) { - case 0x0f: - if (invert_flag == 0) - I386OP(decode_three_bytef3)(); // sse f3 0f - else - I386OP(decode_three_bytef2)(); // sse f2 0f - return; - case 0x26: - cpustate->segment_override=ES; - cpustate->segment_prefix=1; - break; - case 0x2e: - cpustate->segment_override=CS; - cpustate->segment_prefix=1; - break; - case 0x36: - cpustate->segment_override=SS; - cpustate->segment_prefix=1; - break; - case 0x3e: - cpustate->segment_override=DS; - cpustate->segment_prefix=1; - break; - case 0x64: - cpustate->segment_override=FS; - cpustate->segment_prefix=1; - break; - case 0x65: - cpustate->segment_override=GS; - cpustate->segment_prefix=1; - break; - case 0x66: - cpustate->operand_size ^= 1; - cpustate->xmm_operand_size ^= 1; - break; - case 0x67: - cpustate->address_size ^= 1; - break; - default: - prefix_flag=0; - } - } while (prefix_flag); - - - if( cpustate->segment_prefix ) { - // FIXME: the following does not work if both address override and segment override are used - i386_translate( cpustate->segment_override, cpustate->sreg[cpustate->segment_prefix].d ? REG32(ESI) : REG16(SI), -1, 1 ); - } else { - //eas = - i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), -1, 1 ); - } - i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), -1, 1 ); - - switch(opcode) - { - case 0x6c: - case 0x6d: - /* INSB, INSW, INSD */ - // TODO: cycle count - cycle_base = 8; - cycle_adjustment = -4; - flag = NULL; - break; - - case 0x6e: - case 0x6f: - /* OUTSB, OUTSW, OUTSD */ - // TODO: cycle count - cycle_base = 8; - cycle_adjustment = -4; - flag = NULL; - break; - - case 0xa4: - case 0xa5: - /* MOVSB, MOVSW, MOVSD */ - cycle_base = 8; - cycle_adjustment = -4; - flag = NULL; - break; - - case 0xa6: - case 0xa7: - /* CMPSB, CMPSW, CMPSD */ - cycle_base = 5; - cycle_adjustment = -1; - flag = &cpustate->ZF; - break; - - case 0xac: - case 0xad: - /* LODSB, LODSW, LODSD */ - cycle_base = 5; - cycle_adjustment = 1; - flag = NULL; - break; - - case 0xaa: - case 0xab: - /* STOSB, STOSW, STOSD */ - cycle_base = 5; - cycle_adjustment = 0; - flag = NULL; - break; - - case 0xae: - case 0xaf: - /* SCASB, SCASW, SCASD */ - cycle_base = 5; - cycle_adjustment = 0; - flag = &cpustate->ZF; - break; - - case 0x90: - CYCLES(CYCLES_NOP); - return; - - case 0xc2: // sigh - case 0xc3: - cpustate->pc--; - return; - - default: - logerror("i386: Invalid REP/opcode %02X combination at %08x\n",opcode, cpustate->pc - 2); - cpustate->pc--; - break; - } - - if( cpustate->address_size ) { - if( REG32(ECX) == 0 ) - return; - } else { - if( REG16(CX) == 0 ) - return; - } - - /* now actually perform the repeat */ - CYCLES_NUM(cycle_base); - do - { - cpustate->eip = repeated_eip; - cpustate->pc = repeated_pc; - try - { - I386OP(decode_opcode)(); - } - catch (UINT64 e) - { - cpustate->eip = cpustate->prev_eip; - throw e; - } - - CYCLES_NUM(cycle_adjustment); - - if (cpustate->address_size) - count = --REG32(ECX); - else - count = --REG16(CX); - if (cpustate->cycles <= 0) - goto outofcycles; - } - while( count && (!flag || (invert_flag ? !*flag : *flag)) ); - return; - -outofcycles: - /* if we run out of cycles to execute, and we are still in the repeat, we need - * to exit this instruction in such a way to go right back into it when we have - * time to execute cycles */ - if(flag && (invert_flag ? *flag : !*flag)) - return; - cpustate->eip = cpustate->prev_eip; - CHANGE_PC(cpustate->eip); - CYCLES_NUM(-cycle_base); -} - -void I386_OPS_BASE::I386OP(rep)() // Opcode 0xf3 -{ - I386OP(repeat)( 0); -} - -void I386_OPS_BASE::I386OP(repne)() // Opcode 0xf2 -{ - I386OP(repeat)( 1); -} - -void I386_OPS_BASE::I386OP(sahf)() // Opcode 0x9e -{ - set_flags( (get_flags() & 0xffffff00) | (REG8(AH) & 0xd7) ); - CYCLES(CYCLES_SAHF); -} - -void I386_OPS_BASE::I386OP(sbb_rm8_r8)() // Opcode 0x18 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = SBB8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = SBB8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sbb_r8_rm8)() // Opcode 0x1a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = SBB8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = SBB8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sbb_al_i8)() // Opcode 0x1c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = SBB8( dst, src, cpustate->CF); - REG8(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(scasb)() // Opcode 0xae -{ - UINT32 eas; - UINT8 src, dst; - eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 1 ); - src = READ8(eas); - dst = REG8(AL); - SUB8(dst, src); - BUMP_DI(1); - CYCLES(CYCLES_SCAS); -} - -void I386_OPS_BASE::I386OP(setalc)() // Opcode 0xd6 (undocumented) -{ - if( cpustate->CF ) { - REG8(AL) = 0xff; - } else { - REG8(AL) = 0; - } - CYCLES(3); -} - -void I386_OPS_BASE::I386OP(seta_rm8)() // Opcode 0x0f 97 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF == 0 && cpustate->ZF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setbe_rm8)() // Opcode 0x0f 96 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF != 0 || cpustate->ZF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setc_rm8)() // Opcode 0x0f 92 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setg_rm8)() // Opcode 0x0f 9f -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setge_rm8)() // Opcode 0x0f 9d -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if(cpustate->SF == cpustate->OF) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setl_rm8)() // Opcode 0x0f 9c -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->SF != cpustate->OF ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setle_rm8)() // Opcode 0x0f 9e -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setnc_rm8)() // Opcode 0x0f 93 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setno_rm8)() // Opcode 0x0f 91 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->OF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setnp_rm8)() // Opcode 0x0f 9b -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->PF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setns_rm8)() // Opcode 0x0f 99 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->SF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setnz_rm8)() // Opcode 0x0f 95 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(seto_rm8)() // Opcode 0x0f 90 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->OF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setp_rm8)() // Opcode 0x0f 9a -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->PF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(sets_rm8)() // Opcode 0x0f 98 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->SF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setz_rm8)() // Opcode 0x0f 94 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(stc)() // Opcode 0xf9 -{ - cpustate->CF = 1; - CYCLES(CYCLES_STC); -} - -void I386_OPS_BASE::I386OP(std)() // Opcode 0xfd -{ - cpustate->DF = 1; - CYCLES(CYCLES_STD); -} - -void I386_OPS_BASE::I386OP(sti)() // Opcode 0xfb -{ - if(PROTECTED_MODE) - { - UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); - if(cpustate->CPL > IOPL) - FAULT(FAULT_GP,0); - } - cpustate->delayed_interrupt_enable = 1; // IF is set after the next instruction. - CYCLES(CYCLES_STI); -} - -void I386_OPS_BASE::I386OP(stosb)() // Opcode 0xaa -{ - UINT32 ead; - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 ); - WRITE8(ead, REG8(AL)); - BUMP_DI(1); - CYCLES(CYCLES_STOS); -} - -void I386_OPS_BASE::I386OP(sub_rm8_r8)() // Opcode 0x28 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = SUB8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = SUB8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sub_r8_rm8)() // Opcode 0x2a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = SUB8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = SUB8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sub_al_i8)() // Opcode 0x2c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(EAX); - dst = SUB8(dst, src); - REG8(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_al_i8)() // Opcode 0xa8 -{ - UINT8 src = FETCH(); - UINT8 dst = REG8(AL); - dst = src & dst; - SetSZPF8(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_rm8_r8)() // Opcode 0x84 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = src & dst; - SetSZPF8(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = src & dst; - SetSZPF8(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xchg_r8_rm8)() // Opcode 0x86 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 src = LOAD_RM8(modrm); - UINT8 dst = LOAD_REG8(modrm); - STORE_REG8(modrm, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_XCHG_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 src = READ8(ea); - UINT8 dst = LOAD_REG8(modrm); - WRITE8(ea, dst); - STORE_REG8(modrm, src); - CYCLES(CYCLES_XCHG_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_rm8_r8)() // Opcode 0x30 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = XOR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = XOR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_r8_rm8)() // Opcode 0x32 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = XOR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = XOR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(xor_al_i8)() // Opcode 0x34 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = XOR8(dst, src); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - - - -void I386_OPS_BASE::I386OP(group80_8)() // Opcode 0x80 -{ - UINT32 ea; - UINT8 src, dst; - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: // ADD Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = ADD8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,0,1); - dst = READ8(ea); - src = FETCH(); - dst = ADD8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 1: // OR Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = OR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = OR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 2: // ADC Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = ADC8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = ADC8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 3: // SBB Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = SBB8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = SBB8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 4: // AND Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = AND8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = AND8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 5: // SUB Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = SUB8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = SUB8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 6: // XOR Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = XOR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = XOR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 7: // CMP Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - ea = GetEA(modrm,0,1); - dst = READ8(ea); - src = FETCH(); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupC0_8)() // Opcode 0xc0 -{ - UINT8 dst; - UINT8 modrm = FETCH(); - UINT8 shift; - - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate8( modrm, dst, shift); - STORE_RM8(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,1); - dst = READ8(ea); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate8( modrm, dst, shift); - WRITE8(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD0_8)() // Opcode 0xd0 -{ - UINT8 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - dst = i386_shift_rotate8( modrm, dst, 1); - STORE_RM8(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,1); - dst = READ8(ea); - dst = i386_shift_rotate8( modrm, dst, 1); - WRITE8(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD2_8)() // Opcode 0xd2 -{ - UINT8 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - dst = i386_shift_rotate8( modrm, dst, REG8(CL)); - STORE_RM8(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,1); - dst = READ8(ea); - dst = i386_shift_rotate8( modrm, dst, REG8(CL)); - WRITE8(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupF6_8)() // Opcode 0xf6 -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* TEST Rm8, i8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - UINT8 src = FETCH(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF8(dst); - CYCLES(CYCLES_TEST_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - UINT8 dst = READ8(ea); - UINT8 src = FETCH(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF8(dst); - CYCLES(CYCLES_TEST_IMM_MEM); - } - break; - case 2: /* NOT Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = ~dst; - STORE_RM8(modrm, dst); - CYCLES(CYCLES_NOT_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = ~dst; - WRITE8(ea, dst); - CYCLES(CYCLES_NOT_MEM); - } - break; - case 3: /* NEG Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = SUB8( 0, dst ); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_NEG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = SUB8( 0, dst ); - WRITE8(ea, dst); - CYCLES(CYCLES_NEG_MEM); - } - break; - case 4: /* MUL AL, Rm8 */ - { - UINT16 result; - UINT8 src, dst; - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - CYCLES(CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - CYCLES(CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = REG8(AL); - result = (UINT16)src * (UINT16)dst; - REG16(AX) = (UINT16)result; - - cpustate->CF = cpustate->OF = (REG16(AX) > 0xff); - } - break; - case 5: /* IMUL AL, Rm8 */ - { - INT16 result; - INT16 src, dst; - if( modrm >= 0xc0 ) { - src = (INT16)(INT8)LOAD_RM8(modrm); - CYCLES(CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0,1); - src = (INT16)(INT8)READ8(ea); - CYCLES(CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = (INT16)(INT8)REG8(AL); - result = src * dst; - - REG16(AX) = (UINT16)result; - - cpustate->CF = cpustate->OF = !(result == (INT16)(INT8)result); - } - break; - case 6: /* DIV AL, Rm8 */ - { - UINT16 quotient, remainder, result; - UINT8 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - CYCLES(CYCLES_DIV8_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - CYCLES(CYCLES_DIV8_ACC_MEM); - } - - quotient = (UINT16)REG16(AX); - if( src ) { - remainder = quotient % (UINT16)src; - result = quotient / (UINT16)src; - if( result > 0xff ) { - /* TODO: Divide error */ - } else { - REG8(AH) = (UINT8)remainder & 0xff; - REG8(AL) = (UINT8)result & 0xff; - - // this flag is actually undefined, enable on non-cyrix - if (cpustate->cpuid_id0 != 0x69727943) - cpustate->CF = 1; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - case 7: /* IDIV AL, Rm8 */ - { - INT16 quotient, remainder, result; - UINT8 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - CYCLES(CYCLES_IDIV8_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - CYCLES(CYCLES_IDIV8_ACC_MEM); - } - - quotient = (INT16)REG16(AX); - if( src ) { - remainder = quotient % (INT16)(INT8)src; - result = quotient / (INT16)(INT8)src; - if( result > 0xff ) { - /* TODO: Divide error */ - } else { - REG8(AH) = (UINT8)remainder & 0xff; - REG8(AL) = (UINT8)result & 0xff; - - // this flag is actually undefined, enable on non-cyrix - if (cpustate->cpuid_id0 != 0x69727943) - cpustate->CF = 1; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupFE_8)() // Opcode 0xfe -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* INC Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = INC8(dst); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_INC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = INC8(dst); - WRITE8(ea, dst); - CYCLES(CYCLES_INC_MEM); - } - break; - case 1: /* DEC Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = DEC8(dst); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_DEC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = DEC8(dst); - WRITE8(ea, dst); - CYCLES(CYCLES_DEC_MEM); - } - break; - case 6: /* PUSH Rm8*/ - { - UINT8 value; - if( modrm >= 0xc0 ) { - value = LOAD_RM8(modrm); - } else { - UINT32 ea = GetEA(modrm,0,1); - value = READ8(ea); - } - if( cpustate->operand_size ) { - PUSH32(value); - } else { - PUSH16(value); - } - CYCLES(CYCLES_PUSH_RM); - } - break; - default: - report_invalid_modrm( "groupFE_8", modrm); - break; - } -} - - - -void I386_OPS_BASE::I386OP(segment_CS)() // Opcode 0x2e -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = CS; - - I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_DS)() // Opcode 0x3e -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = DS; - CYCLES(0); // TODO: Specify cycle count - I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_ES)() // Opcode 0x26 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = ES; - CYCLES(0); // TODO: Specify cycle count - I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_FS)() // Opcode 0x64 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = FS; - CYCLES(1); // TODO: Specify cycle count - I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_GS)() // Opcode 0x65 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = GS; - CYCLES(1); // TODO: Specify cycle count - I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_SS)() // Opcode 0x36 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = SS; - CYCLES(0); // TODO: Specify cycle count - I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(operand_size)() // Opcode prefix 0x66 -{ - if(cpustate->operand_prefix == 0) - { - cpustate->operand_size ^= 1; - cpustate->xmm_operand_size ^= 1; - cpustate->operand_prefix = 1; - } - cpustate->opcode = FETCH(); - if (cpustate->opcode == 0x0f) - I386OP(decode_three_byte66)(); - else - { - if( cpustate->operand_size ) - (this->*cpustate->opcode_table1_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table1_16[cpustate->opcode])(); - } -} - -void I386_OPS_BASE::I386OP(address_size)() // Opcode 0x67 -{ - if(cpustate->address_prefix == 0) - { - cpustate->address_size ^= 1; - cpustate->address_prefix = 1; - } - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(nop)() // Opcode 0x90 -{ - CYCLES(CYCLES_NOP); -} - -void I386_OPS_BASE::I386OP(int3)() // Opcode 0xcc -{ - CYCLES(CYCLES_INT3); - cpustate->ext = 0; // not an external interrupt - i386_trap(3, 1, 0); - cpustate->ext = 1; -} - -void I386_OPS_BASE::I386OP(_int)() // Opcode 0xcd -{ - int interrupt = FETCH(); - CYCLES(CYCLES_INT); - // Without pseudo BIOS. - cpustate->ext = 0; // not an external interrupt - i386_trap(interrupt, 1, 0); - cpustate->ext = 1; -} - -void I386_OPS_BASE::I386OP(into)() // Opcode 0xce -{ - if( cpustate->OF ) { - cpustate->ext = 0; - i386_trap(4, 1, 0); - cpustate->ext = 1; - CYCLES(CYCLES_INTO_OF1); - } - else - { - CYCLES(CYCLES_INTO_OF0); - } -} - -UINT32 i386_escape_ea; // hack around GCC 4.6 error because we need the side effects of GetEA() -void I386_OPS_BASE::I386OP(escape)() // Opcodes 0xd8 - 0xdf -{ - UINT8 modrm = FETCH(); - if(modrm < 0xc0) - { - i386_escape_ea = GetEA(modrm,0,1); - } - CYCLES(3); // TODO: confirm this - (void) LOAD_RM8(modrm); -} - -void I386_OPS_BASE::I386OP(hlt)() // Opcode 0xf4 -{ - if(PROTECTED_MODE && cpustate->CPL != 0) - FAULT(FAULT_GP,0); - cpustate->halted = 1; - CYCLES(CYCLES_HLT); - if (cpustate->cycles > 0) - cpustate->cycles = 0; -} - -void I386_OPS_BASE::I386OP(decimal_adjust)( int direction) -{ - UINT8 tmpAL = REG8(AL); - UINT8 tmpCF = cpustate->CF; - - if (cpustate->AF || ((REG8(AL) & 0xf) > 9)) - { - UINT16 t= (UINT16)REG8(AL) + (direction * 0x06); - REG8(AL) = (UINT8)t&0xff; - cpustate->AF = 1; - if (t & 0x100) - cpustate->CF = 1; - if (direction > 0) - tmpAL = REG8(AL); - } - - if (tmpCF || (tmpAL > 0x99)) - { - REG8(AL) += (direction * 0x60); - cpustate->CF = 1; - } - - SetSZPF8(REG8(AL)); -} - -void I386_OPS_BASE::I386OP(daa)() // Opcode 0x27 -{ - I386OP(decimal_adjust)( +1); - CYCLES(CYCLES_DAA); -} - -void I386_OPS_BASE::I386OP(das)() // Opcode 0x2f -{ - I386OP(decimal_adjust)( -1); - CYCLES(CYCLES_DAS); -} - -void I386_OPS_BASE::I386OP(aaa)() // Opcode 0x37 -{ - if( ( (REG8(AL) & 0x0f) > 9) || (cpustate->AF != 0) ) { - REG16(AX) = REG16(AX) + 6; - REG8(AH) = REG8(AH) + 1; - cpustate->AF = 1; - cpustate->CF = 1; - } else { - cpustate->AF = 0; - cpustate->CF = 0; - } - REG8(AL) = REG8(AL) & 0x0f; - CYCLES(CYCLES_AAA); -} - -void I386_OPS_BASE::I386OP(aas)() // Opcode 0x3f -{ - if (cpustate->AF || ((REG8(AL) & 0xf) > 9)) - { - REG16(AX) -= 6; - REG8(AH) -= 1; - cpustate->AF = 1; - cpustate->CF = 1; - } - else - { - cpustate->AF = 0; - cpustate->CF = 0; - } - REG8(AL) &= 0x0f; - CYCLES(CYCLES_AAS); -} - -void I386_OPS_BASE::I386OP(aad)() // Opcode 0xd5 -{ - UINT8 tempAL = REG8(AL); - UINT8 tempAH = REG8(AH); - UINT8 i = FETCH(); - - REG8(AL) = (tempAL + (tempAH * i)) & 0xff; - REG8(AH) = 0; - SetSZPF8( REG8(AL) ); - CYCLES(CYCLES_AAD); -} - -void I386_OPS_BASE::I386OP(aam)() // Opcode 0xd4 -{ - UINT8 tempAL = REG8(AL); - UINT8 i = FETCH(); - - if(!i) - { - i386_trap( 0, 0, 0); - return; - } - REG8(AH) = tempAL / i; - REG8(AL) = tempAL % i; - SetSZPF8( REG8(AL) ); - CYCLES(CYCLES_AAM); -} - -void I386_OPS_BASE::I386OP(clts)() // Opcode 0x0f 0x06 -{ - // Privileged instruction, CPL must be zero. Can be used in real or v86 mode. - if(PROTECTED_MODE && cpustate->CPL != 0) - FAULT(FAULT_GP,0) - cpustate->cr[0] &= ~0x08; /* clear TS bit */ - CYCLES(CYCLES_CLTS); -} - -void I386_OPS_BASE::I386OP(wait)() // Opcode 0x9B -{ - // TODO -} - -void I386_OPS_BASE::I386OP(lock)() // Opcode 0xf0 -{ - // lock doesn't depend on iopl on 386 - cpustate->lock = true; - CYCLES(CYCLES_LOCK); // TODO: Determine correct cycle count - I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(mov_r32_tr)() // Opcode 0x0f 24 -{ - FETCH(); - CYCLES(1); // TODO: correct cycle count -} - -void I386_OPS_BASE::I386OP(mov_tr_r32)() // Opcode 0x0f 26 -{ - FETCH(); - CYCLES(1); // TODO: correct cycle count -} - -void I386_OPS_BASE::I386OP(loadall)() // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented -{ - if(PROTECTED_MODE && (cpustate->CPL != 0)) - FAULT(FAULT_GP,0) - UINT32 ea = i386_translate( ES, REG32(EDI), 0, 204); - cpustate->cr[0] = READ32( ea) & 0xfffeffff; // wp not supported on 386 - set_flags( READ32( ea + 0x04)); - cpustate->eip = READ32( ea + 0x08); - REG32(EDI) = READ32( ea + 0x0c); - REG32(ESI) = READ32( ea + 0x10); - REG32(EBP) = READ32( ea + 0x14); - REG32(ESP) = READ32( ea + 0x18); - REG32(EBX) = READ32( ea + 0x1c); - REG32(EDX) = READ32( ea + 0x20); - REG32(ECX) = READ32( ea + 0x24); - REG32(EAX) = READ32( ea + 0x28); - cpustate->dr[6] = READ32( ea + 0x2c); - cpustate->dr[7] = READ32( ea + 0x30); - cpustate->task.segment = READ16( ea + 0x34); - cpustate->ldtr.segment = READ16( ea + 0x38); - cpustate->sreg[GS].selector = READ16( ea + 0x3c); - cpustate->sreg[FS].selector = READ16( ea + 0x40); - cpustate->sreg[DS].selector = READ16( ea + 0x44); - cpustate->sreg[SS].selector = READ16( ea + 0x48); - cpustate->sreg[CS].selector = READ16( ea + 0x4c); - cpustate->sreg[ES].selector = READ16( ea + 0x50); - cpustate->task.flags = READ32( ea + 0x54) >> 8; - cpustate->task.base = READ32( ea + 0x58); - cpustate->task.limit = READ32( ea + 0x5c); - cpustate->idtr.base = READ32( ea + 0x64); - cpustate->idtr.limit = READ32( ea + 0x68); - cpustate->gdtr.base = READ32( ea + 0x70); - cpustate->gdtr.limit = READ32( ea + 0x74); - cpustate->ldtr.flags = READ32( ea + 0x78) >> 8; - cpustate->ldtr.base = READ32( ea + 0x7c); - cpustate->ldtr.limit = READ32( ea + 0x80); - cpustate->sreg[GS].flags = READ32( ea + 0x84) >> 8; - cpustate->sreg[GS].base = READ32( ea + 0x88); - cpustate->sreg[GS].limit = READ32( ea + 0x8c); - cpustate->sreg[FS].flags = READ32( ea + 0x90) >> 8; - cpustate->sreg[FS].base = READ32( ea + 0x94); - cpustate->sreg[FS].limit = READ32( ea + 0x98); - cpustate->sreg[DS].flags = READ32( ea + 0x9c) >> 8; - cpustate->sreg[DS].base = READ32( ea + 0xa0); - cpustate->sreg[DS].limit = READ32( ea + 0xa4); - cpustate->sreg[SS].flags = READ32( ea + 0xa8) >> 8; - cpustate->sreg[SS].base = READ32( ea + 0xac); - cpustate->sreg[SS].limit = READ32( ea + 0xb0); - cpustate->sreg[CS].flags = READ32( ea + 0xb4) >> 8; - cpustate->sreg[CS].base = READ32( ea + 0xb8); - cpustate->sreg[CS].limit = READ32( ea + 0xbc); - cpustate->sreg[ES].flags = READ32( ea + 0xc0) >> 8; - cpustate->sreg[ES].base = READ32( ea + 0xc4); - cpustate->sreg[ES].limit = READ32( ea + 0xc8); - cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3; // cpl == dpl of ss - - for(int i = 0; i <= GS; i++) - { - cpustate->sreg[i].valid = (cpustate->sreg[i].flags & 0x80) ? true : false; - cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0; - } - CHANGE_PC( cpustate->eip); -} - -void I386_OPS_BASE::I386OP(invalid)() -{ - report_invalid_opcode(); - i386_trap( 6, 0, 0); -} - -void I386_OPS_BASE::I386OP(xlat)() // Opcode 0xd7 -{ - UINT32 ea; - if( cpustate->segment_prefix ) { - if(!cpustate->address_size) - { - ea = i386_translate( cpustate->segment_override, REG16(BX) + REG8(AL), 0, 1 ); - } - else - { - ea = i386_translate( cpustate->segment_override, REG32(EBX) + REG8(AL), 0, 1 ); - } - } else { - if(!cpustate->address_size) - { - ea = i386_translate( DS, REG16(BX) + REG8(AL), 0, 1 ); - } - else - { - ea = i386_translate( DS, REG32(EBX) + REG8(AL), 0, 1 ); - } - } - REG8(AL) = READ8(ea); - CYCLES(CYCLES_XLAT); -} - -#else -UINT8 I386_OPS_BASE::I386OP(shift_rotate8)( UINT8 modrm, UINT32 value, UINT8 shift) -{ - UINT32 src = value & 0xff; - UINT8 dst = value; - - if( shift == 0 ) { - CYCLES_RM(modrm, 3, 7); - } else if( shift == 1 ) { - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm8, 1 */ - cpustate->CF = (src & 0x80) ? 1 : 0; - dst = (src << 1) + cpustate->CF; - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm8, 1 */ - cpustate->CF = (src & 0x1) ? 1 : 0; - dst = (cpustate->CF << 7) | (src >> 1); - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm8, 1 */ - dst = (src << 1) + cpustate->CF; - cpustate->CF = (src & 0x80) ? 1 : 0; - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm8, 1 */ - dst = (cpustate->CF << 7) | (src >> 1); - cpustate->CF = src & 0x1; - cpustate->OF = ((src ^ dst) & 0x80) ? 1 : 0; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm8, 1 */ - case 6: - dst = src << 1; - cpustate->CF = (src & 0x80) ? 1 : 0; - cpustate->OF = (((cpustate->CF << 7) ^ dst) & 0x80) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm8, 1 */ - dst = src >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = (dst & 0x80) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm8, 1 */ - dst = (INT8)(src) >> 1; - cpustate->CF = src & 0x1; - cpustate->OF = 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - - } else { - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* ROL rm8, i8 */ - if(!(shift & 7)) - { - if(shift & 0x18) - { - cpustate->CF = src & 1; - cpustate->OF = (src & 1) ^ ((src >> 7) & 1); - } - break; - } - shift &= 7; - dst = ((src & ((UINT8)0xff >> shift)) << shift) | - ((src & ((UINT8)0xff << (8-shift))) >> (8-shift)); - cpustate->CF = dst & 0x1; - cpustate->OF = (dst & 1) ^ (dst >> 7); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 1: /* ROR rm8, i8 */ - if(!(shift & 7)) - { - if(shift & 0x18) - { - cpustate->CF = (src >> 7) & 1; - cpustate->OF = ((src >> 7) & 1) ^ ((src >> 6) & 1); - } - break; - } - shift &= 7; - dst = ((src & ((UINT8)0xff << shift)) >> shift) | - ((src & ((UINT8)0xff >> (8-shift))) << (8-shift)); - cpustate->CF = (dst >> 7) & 1; - cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 2: /* RCL rm8, i8 */ - shift %= 9; - dst = ((src & ((UINT8)0xff >> shift)) << shift) | - ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) | - (cpustate->CF << (shift-1)); - if(shift) cpustate->CF = (src >> (8-shift)) & 0x1; - cpustate->OF = cpustate->CF ^ ((dst >> 7) & 1); - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 3: /* RCR rm8, i8 */ - shift %= 9; - dst = ((src & ((UINT8)0xff << shift)) >> shift) | - ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) | - (cpustate->CF << (8-shift)); - if(shift) cpustate->CF = (src >> (shift-1)) & 0x1; - cpustate->OF = ((dst >> 7) ^ (dst >> 6)) & 1; - CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); - break; - case 4: /* SHL/SAL rm8, i8 */ - case 6: - shift &= 31; - dst = src << shift; - cpustate->CF = (shift <= 8) && ((src >> (8 - shift)) & 1); - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 5: /* SHR rm8, i8 */ - shift &= 31; - dst = src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - case 7: /* SAR rm8, i8 */ - shift &= 31; - dst = (INT8)src >> shift; - cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; - SetSZPF8(dst); - CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); - break; - } - } - - return dst; -} - - - -void I386_OPS_BASE::I386OP(adc_rm8_r8)() // Opcode 0x10 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = ADC8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = ADC8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(adc_r8_rm8)() // Opcode 0x12 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = ADC8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = ADC8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(adc_al_i8)() // Opcode 0x14 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = ADC8( dst, src, cpustate->CF); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(add_rm8_r8)() // Opcode 0x00 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = ADD8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = ADD8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(add_r8_rm8)() // Opcode 0x02 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = ADD8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = ADD8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(add_al_i8)() // Opcode 0x04 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = ADD8(dst, src); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(and_rm8_r8)() // Opcode 0x20 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = AND8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = AND8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(and_r8_rm8)() // Opcode 0x22 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = AND8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = AND8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(and_al_i8)() // Opcode 0x24 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = AND8(dst, src); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(clc)() // Opcode 0xf8 -{ - cpustate->CF = 0; - CYCLES(CYCLES_CLC); -} - -void I386_OPS_BASE::I386OP(cld)() // Opcode 0xfc -{ - cpustate->DF = 0; - CYCLES(CYCLES_CLD); -} - -void I386_OPS_BASE::I386OP(cli)() // Opcode 0xfa -{ - if(PROTECTED_MODE) - { - UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); - if(cpustate->CPL > IOPL) - FAULT(FAULT_GP,0); - } - cpustate->IF = 0; - CYCLES(CYCLES_CLI); -} - -void I386_OPS_BASE::I386OP(cmc)() // Opcode 0xf5 -{ - cpustate->CF ^= 1; - CYCLES(CYCLES_CMC); -} - -void I386_OPS_BASE::I386OP(cmp_rm8_r8)() // Opcode 0x38 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(cmp_r8_rm8)() // Opcode 0x3a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - SUB8(dst, src); - CYCLES(CYCLES_CMP_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(cmp_al_i8)() // Opcode 0x3c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - SUB8(dst, src); - CYCLES(CYCLES_CMP_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(cmpsb)() // Opcode 0xa6 -{ - UINT32 eas, ead; - UINT8 src, dst; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 1 ); - src = READ8(eas); - dst = READ8(ead); - SUB8(src, dst); - BUMP_SI(1); - BUMP_DI(1); - CYCLES(CYCLES_CMPS); -} - -void I386_OPS_BASE::I386OP(in_al_i8)() // Opcode 0xe4 -{ - UINT16 port = FETCH(); - UINT8 data = READPORT8( port); - REG8(AL) = data; - CYCLES(CYCLES_IN_VAR); -} - -void I386_OPS_BASE::I386OP(in_al_dx)() // Opcode 0xec -{ - UINT16 port = REG16(DX); - UINT8 data = READPORT8( port); - REG8(AL) = data; - CYCLES(CYCLES_IN); -} - -void I386_OPS_BASE::I386OP(ja_rel8)() // Opcode 0x77 -{ - INT8 disp = FETCH(); - if( cpustate->CF == 0 && cpustate->ZF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jbe_rel8)() // Opcode 0x76 -{ - INT8 disp = FETCH(); - if( cpustate->CF != 0 || cpustate->ZF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jc_rel8)() // Opcode 0x72 -{ - INT8 disp = FETCH(); - if( cpustate->CF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jg_rel8)() // Opcode 0x7f -{ - INT8 disp = FETCH(); - if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jge_rel8)() // Opcode 0x7d -{ - INT8 disp = FETCH(); - if(cpustate->SF == cpustate->OF) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jl_rel8)() // Opcode 0x7c -{ - INT8 disp = FETCH(); - if( (cpustate->SF != cpustate->OF) ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jle_rel8)() // Opcode 0x7e -{ - INT8 disp = FETCH(); - if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnc_rel8)() // Opcode 0x73 -{ - INT8 disp = FETCH(); - if( cpustate->CF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jno_rel8)() // Opcode 0x71 -{ - INT8 disp = FETCH(); - if( cpustate->OF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnp_rel8)() // Opcode 0x7b -{ - INT8 disp = FETCH(); - if( cpustate->PF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jns_rel8)() // Opcode 0x79 -{ - INT8 disp = FETCH(); - if( cpustate->SF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jnz_rel8)() // Opcode 0x75 -{ - INT8 disp = FETCH(); - if( cpustate->ZF == 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jo_rel8)() // Opcode 0x70 -{ - INT8 disp = FETCH(); - if( cpustate->OF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jp_rel8)() // Opcode 0x7a -{ - INT8 disp = FETCH(); - if( cpustate->PF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(js_rel8)() // Opcode 0x78 -{ - INT8 disp = FETCH(); - if( cpustate->SF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jz_rel8)() // Opcode 0x74 -{ - INT8 disp = FETCH(); - if( cpustate->ZF != 0 ) { - NEAR_BRANCH(disp); - CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ - } else { - CYCLES(CYCLES_JCC_DISP8_NOBRANCH); - } -} - -void I386_OPS_BASE::I386OP(jmp_rel8)() // Opcode 0xeb -{ - INT8 disp = FETCH(); - NEAR_BRANCH(disp); - CYCLES(CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */ -} - -void I386_OPS_BASE::I386OP(lahf)() // Opcode 0x9f -{ - REG8(AH) = get_flags() & 0xd7; - CYCLES(CYCLES_LAHF); -} - -void I386_OPS_BASE::I386OP(lodsb)() // Opcode 0xac -{ - UINT32 eas; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } - REG8(AL) = READ8(eas); - BUMP_SI(1); - CYCLES(CYCLES_LODS); -} - -void I386_OPS_BASE::I386OP(mov_rm8_r8)() // Opcode 0x88 -{ - UINT8 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - STORE_RM8(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - WRITE8(ea, src); - CYCLES(CYCLES_MOV_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_r8_rm8)() // Opcode 0x8a -{ - UINT8 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - STORE_REG8(modrm, src); - CYCLES(CYCLES_MOV_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - STORE_REG8(modrm, src); - CYCLES(CYCLES_MOV_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(mov_rm8_i8)() // Opcode 0xc6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 value = FETCH(); - STORE_RM8(modrm, value); - CYCLES(CYCLES_MOV_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 value = FETCH(); - WRITE8(ea, value); - CYCLES(CYCLES_MOV_IMM_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_r32_cr)() // Opcode 0x0f 20 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 cr = (modrm >> 3) & 0x7; - - STORE_RM32(modrm, cpustate->cr[cr]); - CYCLES(CYCLES_MOV_CR_REG); -} - -void I386_OPS_BASE::I386OP(mov_r32_dr)() // Opcode 0x0f 21 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 dr = (modrm >> 3) & 0x7; - - STORE_RM32(modrm, cpustate->dr[dr]); - switch(dr) - { - case 0: - case 1: - case 2: - case 3: - CYCLES(CYCLES_MOV_REG_DR0_3); - break; - case 6: - case 7: - CYCLES(CYCLES_MOV_REG_DR6_7); - break; - } -} - -void I386_OPS_BASE::I386OP(mov_cr_r32)() // Opcode 0x0f 22 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 cr = (modrm >> 3) & 0x7; - UINT32 data = LOAD_RM32(modrm); - switch(cr) - { - case 0: - data &= 0xfffeffff; // wp not supported on 386 - CYCLES(CYCLES_MOV_REG_CR0); - break; - case 2: CYCLES(CYCLES_MOV_REG_CR2); break; - case 3: - CYCLES(CYCLES_MOV_REG_CR3); - vtlb_flush_dynamic(cpustate->vtlb); - break; - case 4: CYCLES(1); break; // TODO - default: - logerror("i386: mov_cr_r32 CR%d!\n", cr); - return; - } - cpustate->cr[cr] = data; -} - -void I386_OPS_BASE::I386OP(mov_dr_r32)() // Opcode 0x0f 23 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 dr = (modrm >> 3) & 0x7; - - cpustate->dr[dr] = LOAD_RM32(modrm); - switch(dr) - { - case 0: - case 1: - case 2: - case 3: - CYCLES(CYCLES_MOV_DR0_3_REG); - break; - case 6: - case 7: - CYCLES(CYCLES_MOV_DR6_7_REG); - break; - default: - logerror("i386: mov_dr_r32 DR%d!\n", dr); - return; - } -} - -void I386_OPS_BASE::I386OP(mov_al_m8)() // Opcode 0xa0 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - /* TODO: Not sure if this is correct... */ - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 0, 1 ); - } else { - ea = i386_translate( DS, offset, 0, 1 ); - } - REG8(AL) = READ8(ea); - CYCLES(CYCLES_MOV_IMM_MEM); -} - -void I386_OPS_BASE::I386OP(mov_m8_al)() // Opcode 0xa2 -{ - UINT32 offset, ea; - if( cpustate->address_size ) { - offset = FETCH32(); - } else { - offset = FETCH16(); - } - /* TODO: Not sure if this is correct... */ - if( cpustate->segment_prefix ) { - ea = i386_translate( cpustate->segment_override, offset, 1, 1 ); - } else { - ea = i386_translate( DS, offset, 1, 1 ); - } - WRITE8( ea, REG8(AL) ); - CYCLES(CYCLES_MOV_MEM_ACC); -} - -void I386_OPS_BASE::I386OP(mov_rm16_sreg)() // Opcode 0x8c -{ - UINT8 modrm = FETCH(); - int s = (modrm >> 3) & 0x7; - - if( modrm >= 0xc0 ) { - if(cpustate->operand_size) - STORE_RM32(modrm, cpustate->sreg[s].selector); - else - STORE_RM16(modrm, cpustate->sreg[s].selector); - CYCLES(CYCLES_MOV_SREG_REG); - } else { - UINT32 ea = GetEA(modrm,1,2); - WRITE16(ea, cpustate->sreg[s].selector); - CYCLES(CYCLES_MOV_SREG_MEM); - } -} - -void I386_OPS_BASE::I386OP(mov_sreg_rm16)() // Opcode 0x8e -{ - UINT16 selector; - UINT8 modrm = FETCH(); - bool fault; - int s = (modrm >> 3) & 0x7; - - if( modrm >= 0xc0 ) { - selector = LOAD_RM16(modrm); - CYCLES(CYCLES_MOV_REG_SREG); - } else { - UINT32 ea = GetEA(modrm,0,2); - selector = READ16(ea); - CYCLES(CYCLES_MOV_MEM_SREG); - } - - i386_sreg_load(selector,s,&fault); - if((s == SS) && !fault) - { - if(cpustate->IF != 0) // if external interrupts are enabled - { - cpustate->IF = 0; // reset IF for the next instruction - cpustate->delayed_interrupt_enable = 1; - } - } -} - -void I386_OPS_BASE::I386OP(mov_al_i8)() // Opcode 0xb0 -{ - REG8(AL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_cl_i8)() // Opcode 0xb1 -{ - REG8(CL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_dl_i8)() // Opcode 0xb2 -{ - REG8(DL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_bl_i8)() // Opcode 0xb3 -{ - REG8(BL) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_ah_i8)() // Opcode 0xb4 -{ - REG8(AH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_ch_i8)() // Opcode 0xb5 -{ - REG8(CH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_dh_i8)() // Opcode 0xb6 -{ - REG8(DH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(mov_bh_i8)() // Opcode 0xb7 -{ - REG8(BH) = FETCH(); - CYCLES(CYCLES_MOV_IMM_REG); -} - -void I386_OPS_BASE::I386OP(movsb)() // Opcode 0xa4 -{ - UINT32 eas, ead; - UINT8 v; - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 1 ); - } - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 ); - v = READ8(eas); - WRITE8(ead, v); - BUMP_SI(1); - BUMP_DI(1); - CYCLES(CYCLES_MOVS); -} - -void I386_OPS_BASE::I386OP(or_rm8_r8)() // Opcode 0x08 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = OR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = OR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(or_r8_rm8)() // Opcode 0x0a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = OR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = OR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(or_al_i8)() // Opcode 0x0c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = OR8(dst, src); - REG8(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(out_al_i8)() // Opcode 0xe6 -{ - UINT16 port = FETCH(); - UINT8 data = REG8(AL); - WRITEPORT8( port, data); - CYCLES(CYCLES_OUT_VAR); -} - -void I386_OPS_BASE::I386OP(out_al_dx)() // Opcode 0xee -{ - UINT16 port = REG16(DX); - UINT8 data = REG8(AL); - WRITEPORT8( port, data); - CYCLES(CYCLES_OUT); -} - - -void I386_OPS_BASE::I386OP(arpl)() // Opcode 0x63 -{ - UINT16 src, dst; - UINT8 modrm = FETCH(); - UINT8 flag = 0; - - if(PROTECTED_MODE && !V8086_MODE) - { - if( modrm >= 0xc0 ) { - src = LOAD_REG16(modrm); - dst = LOAD_RM16(modrm); - if( (dst&0x3) < (src&0x3) ) { - dst = (dst&0xfffc) | (src&0x3); - flag = 1; - STORE_RM16(modrm, dst); - } - } else { - UINT32 ea = GetEA( modrm,1,2); - src = LOAD_REG16(modrm); - dst = READ16( ea); - if( (dst&0x3) < (src&0x3) ) { - dst = (dst&0xfffc) | (src&0x3); - flag = 1; - WRITE16( ea, dst); - } - } - SetZF(flag); - } - else - i386_trap( 6, 0, 0); // invalid opcode in real mode or v8086 mode -} - -void I386_OPS_BASE::I386OP(push_i8)() // Opcode 0x6a -{ - UINT8 value = FETCH(); - PUSH8(value); - CYCLES(CYCLES_PUSH_IMM); -} - -void I386_OPS_BASE::I386OP(ins_generic)( int size) -{ - UINT32 ead; - UINT8 vb; - UINT16 vw; - UINT32 vd; - - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, size ); - - switch(size) { - case 1: - vb = READPORT8( REG16(DX)); - WRITE8(ead, vb); - break; - case 2: - vw = READPORT16( REG16(DX)); - WRITE16(ead, vw); - break; - case 4: - vd = READPORT32( REG16(DX)); - WRITE32(ead, vd); - break; - } - - if(cpustate->address_size) - REG32(EDI) += ((cpustate->DF) ? -1 : 1) * size; - else - REG16(DI) += ((cpustate->DF) ? -1 : 1) * size; - CYCLES(CYCLES_INS); // TODO: Confirm this value -} - -void I386_OPS_BASE::I386OP(insb)() // Opcode 0x6c -{ - I386_OPS_BASE::I386OP(ins_generic)( 1); -} - -void I386_OPS_BASE::I386OP(insw)() // Opcode 0x6d -{ - I386_OPS_BASE::I386OP(ins_generic)( 2); -} - -void I386_OPS_BASE::I386OP(insd)() // Opcode 0x6d -{ - I386_OPS_BASE::I386OP(ins_generic)( 4); -} - -void I386_OPS_BASE::I386OP(outs_generic)( int size) -{ - UINT32 eas; - UINT8 vb; - UINT16 vw; - UINT32 vd; - - if( cpustate->segment_prefix ) { - eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size ); - } else { - eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, size ); - } - - switch(size) { - case 1: - vb = READ8(eas); - WRITEPORT8( REG16(DX), vb); - break; - case 2: - vw = READ16(eas); - WRITEPORT16( REG16(DX), vw); - break; - case 4: - vd = READ32(eas); - WRITEPORT32( REG16(DX), vd); - break; - } - - if(cpustate->address_size) - REG32(ESI) += ((cpustate->DF) ? -1 : 1) * size; - else - REG16(SI) += ((cpustate->DF) ? -1 : 1) * size; - CYCLES(CYCLES_OUTS); // TODO: Confirm this value -} - -void I386_OPS_BASE::I386OP(outsb)() // Opcode 0x6e -{ - I386_OPS_BASE::I386OP(outs_generic)( 1); -} - -void I386_OPS_BASE::I386OP(outsw)() // Opcode 0x6f -{ - I386_OPS_BASE::I386OP(outs_generic)( 2); -} - -void I386_OPS_BASE::I386OP(outsd)() // Opcode 0x6f -{ - I386_OPS_BASE::I386OP(outs_generic)( 4); -} - -void I386_OPS_BASE::I386OP(repeat)( int invert_flag) -{ - UINT32 repeated_eip = cpustate->eip; - UINT32 repeated_pc = cpustate->pc; - UINT8 opcode; // = FETCH(); -// UINT32 eas, ead; - UINT32 count; - INT32 cycle_base = 0, cycle_adjustment = 0; - UINT8 prefix_flag=1; - UINT8 *flag = NULL; - - - do { - repeated_eip = cpustate->eip; - repeated_pc = cpustate->pc; - opcode = FETCH(); - switch(opcode) { - case 0x0f: - if (invert_flag == 0) - I386_OPS_BASE::I386OP(decode_three_bytef3)(); // sse f3 0f - else - I386_OPS_BASE::I386OP(decode_three_bytef2)(); // sse f2 0f - return; - case 0x26: - cpustate->segment_override=ES; - cpustate->segment_prefix=1; - break; - case 0x2e: - cpustate->segment_override=CS; - cpustate->segment_prefix=1; - break; - case 0x36: - cpustate->segment_override=SS; - cpustate->segment_prefix=1; - break; - case 0x3e: - cpustate->segment_override=DS; - cpustate->segment_prefix=1; - break; - case 0x64: - cpustate->segment_override=FS; - cpustate->segment_prefix=1; - break; - case 0x65: - cpustate->segment_override=GS; - cpustate->segment_prefix=1; - break; - case 0x66: - cpustate->operand_size ^= 1; - cpustate->xmm_operand_size ^= 1; - break; - case 0x67: - cpustate->address_size ^= 1; - break; - default: - prefix_flag=0; - } - } while (prefix_flag); - - - if( cpustate->segment_prefix ) { - // FIXME: the following does not work if both address override and segment override are used - i386_translate( cpustate->segment_override, cpustate->sreg[cpustate->segment_prefix].d ? REG32(ESI) : REG16(SI), -1, 1 ); - } else { - //eas = - i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), -1, 1 ); - } - i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), -1, 1 ); - - switch(opcode) - { - case 0x6c: - case 0x6d: - /* INSB, INSW, INSD */ - // TODO: cycle count - cycle_base = 8; - cycle_adjustment = -4; - flag = NULL; - break; - - case 0x6e: - case 0x6f: - /* OUTSB, OUTSW, OUTSD */ - // TODO: cycle count - cycle_base = 8; - cycle_adjustment = -4; - flag = NULL; - break; - - case 0xa4: - case 0xa5: - /* MOVSB, MOVSW, MOVSD */ - cycle_base = 8; - cycle_adjustment = -4; - flag = NULL; - break; - - case 0xa6: - case 0xa7: - /* CMPSB, CMPSW, CMPSD */ - cycle_base = 5; - cycle_adjustment = -1; - flag = &cpustate->ZF; - break; - - case 0xac: - case 0xad: - /* LODSB, LODSW, LODSD */ - cycle_base = 5; - cycle_adjustment = 1; - flag = NULL; - break; - - case 0xaa: - case 0xab: - /* STOSB, STOSW, STOSD */ - cycle_base = 5; - cycle_adjustment = 0; - flag = NULL; - break; - - case 0xae: - case 0xaf: - /* SCASB, SCASW, SCASD */ - cycle_base = 5; - cycle_adjustment = 0; - flag = &cpustate->ZF; - break; - - case 0x90: - CYCLES(CYCLES_NOP); - return; - - case 0xc2: // sigh - case 0xc3: - cpustate->pc--; - return; - - default: - logerror("i386: Invalid REP/opcode %02X combination at %08x\n",opcode, cpustate->pc - 2); - cpustate->pc--; - break; - } - - if( cpustate->address_size ) { - if( REG32(ECX) == 0 ) - return; - } else { - if( REG16(CX) == 0 ) - return; - } - - /* now actually perform the repeat */ - CYCLES_NUM(cycle_base); - do - { - cpustate->eip = repeated_eip; - cpustate->pc = repeated_pc; - try - { - I386_OPS_BASE::I386OP(decode_opcode)(); - } - catch (UINT64 e) - { - cpustate->eip = cpustate->prev_eip; - throw e; - } - - CYCLES_NUM(cycle_adjustment); - - if (cpustate->address_size) - count = --REG32(ECX); - else - count = --REG16(CX); - if (cpustate->cycles <= 0) - goto outofcycles; - } - while( count && (!flag || (invert_flag ? !*flag : *flag)) ); - return; - -outofcycles: - /* if we run out of cycles to execute, and we are still in the repeat, we need - * to exit this instruction in such a way to go right back into it when we have - * time to execute cycles */ - if(flag && (invert_flag ? *flag : !*flag)) - return; - cpustate->eip = cpustate->prev_eip; - CHANGE_PC(cpustate->eip); - CYCLES_NUM(-cycle_base); -} - -void I386_OPS_BASE::I386OP(rep)() // Opcode 0xf3 -{ - I386_OPS_BASE::I386OP(repeat)( 0); -} - -void I386_OPS_BASE::I386OP(repne)() // Opcode 0xf2 -{ - I386_OPS_BASE::I386OP(repeat)( 1); -} - -void I386_OPS_BASE::I386OP(sahf)() // Opcode 0x9e -{ - set_flags( (get_flags() & 0xffffff00) | (REG8(AH) & 0xd7) ); - CYCLES(CYCLES_SAHF); -} - -void I386_OPS_BASE::I386OP(sbb_rm8_r8)() // Opcode 0x18 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = SBB8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = SBB8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sbb_r8_rm8)() // Opcode 0x1a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = SBB8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = SBB8( dst, src, cpustate->CF); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sbb_al_i8)() // Opcode 0x1c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = SBB8( dst, src, cpustate->CF); - REG8(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(scasb)() // Opcode 0xae -{ - UINT32 eas; - UINT8 src, dst; - eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0 , 1); - src = READ8(eas); - dst = REG8(AL); - SUB8(dst, src); - BUMP_DI(1); - CYCLES(CYCLES_SCAS); -} - -void I386_OPS_BASE::I386OP(setalc)() // Opcode 0xd6 (undocumented) -{ - if( cpustate->CF ) { - REG8(AL) = 0xff; - } else { - REG8(AL) = 0; - } - CYCLES(3); -} - -void I386_OPS_BASE::I386OP(seta_rm8)() // Opcode 0x0f 97 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF == 0 && cpustate->ZF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setbe_rm8)() // Opcode 0x0f 96 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF != 0 || cpustate->ZF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setc_rm8)() // Opcode 0x0f 92 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setg_rm8)() // Opcode 0x0f 9f -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setge_rm8)() // Opcode 0x0f 9d -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if(cpustate->SF == cpustate->OF) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setl_rm8)() // Opcode 0x0f 9c -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->SF != cpustate->OF ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setle_rm8)() // Opcode 0x0f 9e -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setnc_rm8)() // Opcode 0x0f 93 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->CF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setno_rm8)() // Opcode 0x0f 91 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->OF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setnp_rm8)() // Opcode 0x0f 9b -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->PF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setns_rm8)() // Opcode 0x0f 99 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->SF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setnz_rm8)() // Opcode 0x0f 95 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF == 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(seto_rm8)() // Opcode 0x0f 90 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->OF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setp_rm8)() // Opcode 0x0f 9a -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->PF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(sets_rm8)() // Opcode 0x0f 98 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->SF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(setz_rm8)() // Opcode 0x0f 94 -{ - UINT8 modrm = FETCH(); - UINT8 value = 0; - if( cpustate->ZF != 0 ) { - value = 1; - } - if( modrm >= 0xc0 ) { - STORE_RM8(modrm, value); - CYCLES(CYCLES_SETCC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - WRITE8(ea, value); - CYCLES(CYCLES_SETCC_MEM); - } -} - -void I386_OPS_BASE::I386OP(stc)() // Opcode 0xf9 -{ - cpustate->CF = 1; - CYCLES(CYCLES_STC); -} - -void I386_OPS_BASE::I386OP(std)() // Opcode 0xfd -{ - cpustate->DF = 1; - CYCLES(CYCLES_STD); -} - -void I386_OPS_BASE::I386OP(sti)() // Opcode 0xfb -{ - if(PROTECTED_MODE) - { - UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); - if(cpustate->CPL > IOPL) - FAULT(FAULT_GP,0); - } - cpustate->delayed_interrupt_enable = 1; // IF is set after the next instruction. - CYCLES(CYCLES_STI); -} - -void I386_OPS_BASE::I386OP(stosb)() // Opcode 0xaa -{ - UINT32 ead; - ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 1 ); - WRITE8(ead, REG8(AL)); - BUMP_DI(1); - CYCLES(CYCLES_STOS); -} - -void I386_OPS_BASE::I386OP(sub_rm8_r8)() // Opcode 0x28 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = SUB8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = SUB8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(sub_r8_rm8)() // Opcode 0x2a -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = SUB8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = SUB8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(sub_al_i8)() // Opcode 0x2c -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(EAX); - dst = SUB8(dst, src); - REG8(EAX) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_al_i8)() // Opcode 0xa8 -{ - UINT8 src = FETCH(); - UINT8 dst = REG8(AL); - dst = src & dst; - SetSZPF8(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_ALU_IMM_ACC); -} - -void I386_OPS_BASE::I386OP(test_rm8_r8)() // Opcode 0x84 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = src & dst; - SetSZPF8(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = src & dst; - SetSZPF8(dst); - cpustate->CF = 0; - cpustate->OF = 0; - CYCLES(CYCLES_TEST_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xchg_r8_rm8)() // Opcode 0x86 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 src = LOAD_RM8(modrm); - UINT8 dst = LOAD_REG8(modrm); - STORE_REG8(modrm, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_XCHG_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 src = READ8(ea); - UINT8 dst = LOAD_REG8(modrm); - WRITE8(ea, dst); - STORE_REG8(modrm, src); - CYCLES(CYCLES_XCHG_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_rm8_r8)() // Opcode 0x30 -{ - UINT8 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_REG8(modrm); - dst = LOAD_RM8(modrm); - dst = XOR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - src = LOAD_REG8(modrm); - dst = READ8(ea); - dst = XOR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } -} - -void I386_OPS_BASE::I386OP(xor_r8_rm8)() // Opcode 0x32 -{ - UINT32 src, dst; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - dst = LOAD_REG8(modrm); - dst = XOR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - dst = LOAD_REG8(modrm); - dst = XOR8(dst, src); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_ALU_MEM_REG); - } -} - -void I386_OPS_BASE::I386OP(xor_al_i8)() // Opcode 0x34 -{ - UINT8 src, dst; - src = FETCH(); - dst = REG8(AL); - dst = XOR8(dst, src); - REG8(AL) = dst; - CYCLES(CYCLES_ALU_IMM_ACC); -} - - - -void I386_OPS_BASE::I386OP(group80_8)() // Opcode 0x80 -{ - UINT32 ea; - UINT8 src, dst; - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: // ADD Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = ADD8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,0,1); - dst = READ8(ea); - src = FETCH(); - dst = ADD8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 1: // OR Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = OR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = OR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 2: // ADC Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = ADC8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = ADC8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 3: // SBB Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = SBB8( dst, src, cpustate->CF); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = SBB8( dst, src, cpustate->CF); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 4: // AND Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = AND8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = AND8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 5: // SUB Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = SUB8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = SUB8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 6: // XOR Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - dst = XOR8(dst, src); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_ALU_REG_REG); - } else { - ea = GetEA(modrm,1,1); - dst = READ8(ea); - src = FETCH(); - dst = XOR8(dst, src); - WRITE8(ea, dst); - CYCLES(CYCLES_ALU_REG_MEM); - } - break; - case 7: // CMP Rm8, i8 - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - src = FETCH(); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_REG); - } else { - ea = GetEA(modrm,0,1); - dst = READ8(ea); - src = FETCH(); - SUB8(dst, src); - CYCLES(CYCLES_CMP_REG_MEM); - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupC0_8)() // Opcode 0xc0 -{ - UINT8 dst; - UINT8 modrm = FETCH(); - UINT8 shift; - - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate8( modrm, dst, shift); - STORE_RM8(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,1); - dst = READ8(ea); - shift = FETCH() & 0x1f; - dst = i386_shift_rotate8( modrm, dst, shift); - WRITE8(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD0_8)() // Opcode 0xd0 -{ - UINT8 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - dst = i386_shift_rotate8( modrm, dst, 1); - STORE_RM8(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,1); - dst = READ8(ea); - dst = i386_shift_rotate8( modrm, dst, 1); - WRITE8(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupD2_8)() // Opcode 0xd2 -{ - UINT8 dst; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) { - dst = LOAD_RM8(modrm); - dst = i386_shift_rotate8( modrm, dst, REG8(CL)); - STORE_RM8(modrm, dst); - } else { - UINT32 ea = GetEA(modrm,1,1); - dst = READ8(ea); - dst = i386_shift_rotate8( modrm, dst, REG8(CL)); - WRITE8(ea, dst); - } -} - -void I386_OPS_BASE::I386OP(groupF6_8)() // Opcode 0xf6 -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* TEST Rm8, i8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - UINT8 src = FETCH(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF8(dst); - CYCLES(CYCLES_TEST_IMM_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - UINT8 dst = READ8(ea); - UINT8 src = FETCH(); - dst &= src; - cpustate->CF = cpustate->OF = cpustate->AF = 0; - SetSZPF8(dst); - CYCLES(CYCLES_TEST_IMM_MEM); - } - break; - case 2: /* NOT Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = ~dst; - STORE_RM8(modrm, dst); - CYCLES(CYCLES_NOT_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = ~dst; - WRITE8(ea, dst); - CYCLES(CYCLES_NOT_MEM); - } - break; - case 3: /* NEG Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = SUB8( 0, dst ); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_NEG_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = SUB8( 0, dst ); - WRITE8(ea, dst); - CYCLES(CYCLES_NEG_MEM); - } - break; - case 4: /* MUL AL, Rm8 */ - { - UINT16 result; - UINT8 src, dst; - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - CYCLES(CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - CYCLES(CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = REG8(AL); - result = (UINT16)src * (UINT16)dst; - REG16(AX) = (UINT16)result; - - cpustate->CF = cpustate->OF = (REG16(AX) > 0xff); - } - break; - case 5: /* IMUL AL, Rm8 */ - { - INT16 result; - INT16 src, dst; - if( modrm >= 0xc0 ) { - src = (INT16)(INT8)LOAD_RM8(modrm); - CYCLES(CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */ - } else { - UINT32 ea = GetEA(modrm,0,1); - src = (INT16)(INT8)READ8(ea); - CYCLES(CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */ - } - - dst = (INT16)(INT8)REG8(AL); - result = src * dst; - - REG16(AX) = (UINT16)result; - - cpustate->CF = cpustate->OF = !(result == (INT16)(INT8)result); - } - break; - case 6: /* DIV AL, Rm8 */ - { - UINT16 quotient, remainder, result; - UINT8 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - CYCLES(CYCLES_DIV8_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - CYCLES(CYCLES_DIV8_ACC_MEM); - } - - quotient = (UINT16)REG16(AX); - if( src ) { - remainder = quotient % (UINT16)src; - result = quotient / (UINT16)src; - if( result > 0xff ) { - /* TODO: Divide error */ - } else { - REG8(AH) = (UINT8)remainder & 0xff; - REG8(AL) = (UINT8)result & 0xff; - - // this flag is actually undefined, enable on non-cyrix - if (cpustate->cpuid_id0 != 0x69727943) - cpustate->CF = 1; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - case 7: /* IDIV AL, Rm8 */ - { - INT16 quotient, remainder, result; - UINT8 src; - if( modrm >= 0xc0 ) { - src = LOAD_RM8(modrm); - CYCLES(CYCLES_IDIV8_ACC_REG); - } else { - UINT32 ea = GetEA(modrm,0,1); - src = READ8(ea); - CYCLES(CYCLES_IDIV8_ACC_MEM); - } - - quotient = (INT16)REG16(AX); - if( src ) { - remainder = quotient % (INT16)(INT8)src; - result = quotient / (INT16)(INT8)src; - if( result > 0xff ) { - /* TODO: Divide error */ - } else { - REG8(AH) = (UINT8)remainder & 0xff; - REG8(AL) = (UINT8)result & 0xff; - - // this flag is actually undefined, enable on non-cyrix - if (cpustate->cpuid_id0 != 0x69727943) - cpustate->CF = 1; - } - } else { - i386_trap( 0, 0, 0); - } - } - break; - } -} - -void I386_OPS_BASE::I386OP(groupFE_8)() // Opcode 0xfe -{ - UINT8 modrm = FETCH(); - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* INC Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = INC8(dst); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_INC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = INC8(dst); - WRITE8(ea, dst); - CYCLES(CYCLES_INC_MEM); - } - break; - case 1: /* DEC Rm8 */ - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - dst = DEC8(dst); - STORE_RM8(modrm, dst); - CYCLES(CYCLES_DEC_REG); - } else { - UINT32 ea = GetEA(modrm,1,1); - UINT8 dst = READ8(ea); - dst = DEC8(dst); - WRITE8(ea, dst); - CYCLES(CYCLES_DEC_MEM); - } - break; - case 6: /* PUSH Rm8*/ - { - UINT8 value; - if( modrm >= 0xc0 ) { - value = LOAD_RM8(modrm); - } else { - UINT32 ea = GetEA(modrm,0,1); - value = READ8(ea); - } - if( cpustate->operand_size ) { - PUSH32(value); - } else { - PUSH16(value); - } - CYCLES(CYCLES_PUSH_RM); - } - break; - default: - report_invalid_modrm( "groupFE_8", modrm); - break; - } -} - - - -void I386_OPS_BASE::I386OP(segment_CS)() // Opcode 0x2e -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = CS; - - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_DS)() // Opcode 0x3e -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = DS; - CYCLES(0); // TODO: Specify cycle count - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_ES)() // Opcode 0x26 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = ES; - CYCLES(0); // TODO: Specify cycle count - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_FS)() // Opcode 0x64 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = FS; - CYCLES(1); // TODO: Specify cycle count - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_GS)() // Opcode 0x65 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = GS; - CYCLES(1); // TODO: Specify cycle count - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(segment_SS)() // Opcode 0x36 -{ - cpustate->segment_prefix = 1; - cpustate->segment_override = SS; - CYCLES(0); // TODO: Specify cycle count - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(operand_size)() // Opcode prefix 0x66 -{ - if(cpustate->operand_prefix == 0) - { - cpustate->operand_size ^= 1; - cpustate->xmm_operand_size ^= 1; - cpustate->operand_prefix = 1; - } - cpustate->opcode = FETCH(); - if (cpustate->opcode == 0x0f) - I386_OPS_BASE::I386OP(decode_three_byte66)(); - else - { - if( cpustate->operand_size ) - (this->*cpustate->opcode_table1_32[cpustate->opcode])(); - else - (this->*cpustate->opcode_table1_16[cpustate->opcode])(); - } -} - -void I386_OPS_BASE::I386OP(address_size)() // Opcode 0x67 -{ - if(cpustate->address_prefix == 0) - { - cpustate->address_size ^= 1; - cpustate->address_prefix = 1; - } - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(nop)() // Opcode 0x90 -{ - CYCLES(CYCLES_NOP); -} - -void I386_OPS_BASE::I386OP(int3)() // Opcode 0xcc -{ - CYCLES(CYCLES_INT3); - cpustate->ext = 0; // not an external interrupt - i386_trap(3, 1, 0); - cpustate->ext = 1; -} - -void I386_OPS_BASE::I386OP(int)() // Opcode 0xcd -{ - int interrupt = FETCH(); - CYCLES(CYCLES_INT); - // Without pseudo BIOS. - cpustate->ext = 0; // not an external interrupt - i386_trap(interrupt, 1, 0); - cpustate->ext = 1; -} - -void I386_OPS_BASE::I386OP(into)() // Opcode 0xce -{ - if( cpustate->OF ) { - cpustate->ext = 0; - i386_trap(4, 1, 0); - cpustate->ext = 1; - CYCLES(CYCLES_INTO_OF1); - } - else - { - CYCLES(CYCLES_INTO_OF0); - } -} - -void I386_OPS_BASE::I386OP(escape)() // Opcodes 0xd8 - 0xdf -{ - UINT8 modrm = FETCH(); - if(modrm < 0xc0) - { - i386_escape_ea = GetEA(modrm,0,1); - } - CYCLES(3); // TODO: confirm this - (void) LOAD_RM8(modrm); -} - -void I386_OPS_BASE::I386OP(hlt)() // Opcode 0xf4 -{ - if(PROTECTED_MODE && cpustate->CPL != 0) - FAULT(FAULT_GP,0); - cpustate->halted = 1; - CYCLES(CYCLES_HLT); - if (cpustate->cycles > 0) - cpustate->cycles = 0; -} - -void I386_OPS_BASE::I386OP(decimal_adjust)(int direction) -{ - UINT8 tmpAL = REG8(AL); - UINT8 tmpCF = cpustate->CF; - - if (cpustate->AF || ((REG8(AL) & 0xf) > 9)) - { - UINT16 t= (UINT16)REG8(AL) + (direction * 0x06); - REG8(AL) = (UINT8)t&0xff; - cpustate->AF = 1; - if (t & 0x100) - cpustate->CF = 1; - if (direction > 0) - tmpAL = REG8(AL); - } - - if (tmpCF || (tmpAL > 0x99)) - { - REG8(AL) += (direction * 0x60); - cpustate->CF = 1; - } - - SetSZPF8(REG8(AL)); -} - -void I386_OPS_BASE::I386OP(daa)() // Opcode 0x27 -{ - I386_OPS_BASE::I386OP(decimal_adjust)( +1); - CYCLES(CYCLES_DAA); -} - -void I386_OPS_BASE::I386OP(das)() // Opcode 0x2f -{ - I386_OPS_BASE::I386OP(decimal_adjust)( -1); - CYCLES(CYCLES_DAS); -} - -void I386_OPS_BASE::I386OP(aaa)() // Opcode 0x37 -{ - if( ( (REG8(AL) & 0x0f) > 9) || (cpustate->AF != 0) ) { - REG16(AX) = REG16(AX) + 6; - REG8(AH) = REG8(AH) + 1; - cpustate->AF = 1; - cpustate->CF = 1; - } else { - cpustate->AF = 0; - cpustate->CF = 0; - } - REG8(AL) = REG8(AL) & 0x0f; - CYCLES(CYCLES_AAA); -} - -void I386_OPS_BASE::I386OP(aas)() // Opcode 0x3f -{ - if (cpustate->AF || ((REG8(AL) & 0xf) > 9)) - { - REG16(AX) -= 6; - REG8(AH) -= 1; - cpustate->AF = 1; - cpustate->CF = 1; - } - else - { - cpustate->AF = 0; - cpustate->CF = 0; - } - REG8(AL) &= 0x0f; - CYCLES(CYCLES_AAS); -} - -void I386_OPS_BASE::I386OP(aad)() // Opcode 0xd5 -{ - UINT8 tempAL = REG8(AL); - UINT8 tempAH = REG8(AH); - UINT8 i = FETCH(); - - REG8(AL) = (tempAL + (tempAH * i)) & 0xff; - REG8(AH) = 0; - SetSZPF8( REG8(AL) ); - CYCLES(CYCLES_AAD); -} - -void I386_OPS_BASE::I386OP(aam)() // Opcode 0xd4 -{ - UINT8 tempAL = REG8(AL); - UINT8 i = FETCH(); - - if(!i) - { - i386_trap( 0, 0, 0); - return; - } - REG8(AH) = tempAL / i; - REG8(AL) = tempAL % i; - SetSZPF8( REG8(AL) ); - CYCLES(CYCLES_AAM); -} - -void I386_OPS_BASE::I386OP(clts)() // Opcode 0x0f 0x06 -{ - // Privileged instruction, CPL must be zero. Can be used in real or v86 mode. - if(PROTECTED_MODE && cpustate->CPL != 0) - FAULT(FAULT_GP,0) - cpustate->cr[0] &= ~0x08; /* clear TS bit */ - CYCLES(CYCLES_CLTS); -} - -void I386_OPS_BASE::I386OP(wait)() // Opcode 0x9B -{ - // TODO -} - -void I386_OPS_BASE::I386OP(lock)() // Opcode 0xf0 -{ - // lock doesn't depend on iopl on 386 - cpustate->lock = true; - CYCLES(CYCLES_LOCK); // TODO: Determine correct cycle count - I386_OPS_BASE::I386OP(decode_opcode)(); -} - -void I386_OPS_BASE::I386OP(mov_r32_tr)() // Opcode 0x0f 24 -{ - FETCH(); - CYCLES(1); // TODO: correct cycle count -} - -void I386_OPS_BASE::I386OP(mov_tr_r32)() // Opcode 0x0f 26 -{ - FETCH(); - CYCLES(1); // TODO: correct cycle count -} - -void I386_OPS_BASE::I386OP(loadall)() // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented -{ - if(PROTECTED_MODE && (cpustate->CPL != 0)) - FAULT(FAULT_GP,0) - UINT32 ea = i386_translate(ES, REG32(EDI), 0, 204); - cpustate->cr[0] = READ32(ea) & 0xfffeffff; // wp not supported on 386 - set_flags(READ32(ea + 0x04)); - cpustate->eip = READ32( ea + 0x08); - REG32(EDI) = READ32( ea + 0x0c); - REG32(ESI) = READ32( ea + 0x10); - REG32(EBP) = READ32( ea + 0x14); - REG32(ESP) = READ32( ea + 0x18); - REG32(EBX) = READ32( ea + 0x1c); - REG32(EDX) = READ32( ea + 0x20); - REG32(ECX) = READ32( ea + 0x24); - REG32(EAX) = READ32( ea + 0x28); - cpustate->dr[6] = READ32( ea + 0x2c); - cpustate->dr[7] = READ32( ea + 0x30); - cpustate->task.segment = READ16(ea + 0x34); - cpustate->ldtr.segment = READ16(ea + 0x38); - cpustate->sreg[GS].selector = READ16(ea + 0x3c); - cpustate->sreg[FS].selector = READ16(ea + 0x40); - cpustate->sreg[DS].selector = READ16(ea + 0x44); - cpustate->sreg[SS].selector = READ16(ea + 0x48); - cpustate->sreg[CS].selector = READ16(ea + 0x4c); - cpustate->sreg[ES].selector = READ16(ea + 0x50); - cpustate->task.flags = READ32( ea + 0x54) >> 8; - cpustate->task.base = READ32( ea + 0x58); - cpustate->task.limit = READ32( ea + 0x5c); - cpustate->idtr.base = READ32( ea + 0x64); - cpustate->idtr.limit = READ32( ea + 0x68); - cpustate->gdtr.base = READ32( ea + 0x70); - cpustate->gdtr.limit = READ32( ea + 0x74); - cpustate->ldtr.flags = READ32( ea + 0x78) >> 8; - cpustate->ldtr.base = READ32( ea + 0x7c); - cpustate->ldtr.limit = READ32( ea + 0x80); - cpustate->sreg[GS].flags = READ32( ea + 0x84) >> 8; - cpustate->sreg[GS].base = READ32( ea + 0x88); - cpustate->sreg[GS].limit = READ32( ea + 0x8c); - cpustate->sreg[FS].flags = READ32( ea + 0x90) >> 8; - cpustate->sreg[FS].base = READ32( ea + 0x94); - cpustate->sreg[FS].limit = READ32( ea + 0x98); - cpustate->sreg[DS].flags = READ32( ea + 0x9c) >> 8; - cpustate->sreg[DS].base = READ32( ea + 0xa0); - cpustate->sreg[DS].limit = READ32( ea + 0xa4); - cpustate->sreg[SS].flags = READ32( ea + 0xa8) >> 8; - cpustate->sreg[SS].base = READ32( ea + 0xac); - cpustate->sreg[SS].limit = READ32( ea + 0xb0); - cpustate->sreg[CS].flags = READ32( ea + 0xb4) >> 8; - cpustate->sreg[CS].base = READ32( ea + 0xb8); - cpustate->sreg[CS].limit = READ32( ea + 0xbc); - cpustate->sreg[ES].flags = READ32( ea + 0xc0) >> 8; - cpustate->sreg[ES].base = READ32( ea + 0xc4); - cpustate->sreg[ES].limit = READ32( ea + 0xc8); - cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3; // cpl == dpl of ss - - for(int i = 0; i <= GS; i++) - { - cpustate->sreg[i].valid = (cpustate->sreg[i].flags & 0x80) ? true : false; - cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0; - } - CHANGE_PC(cpustate->eip); -} - -void I386_OPS_BASE::I386OP(invalid)() -{ - report_invalid_opcode(); - i386_trap( 6, 0, 0); -} - -void I386_OPS_BASE::I386OP(xlat)() // Opcode 0xd7 -{ - UINT32 ea; - if( cpustate->segment_prefix ) { - if(!cpustate->address_size) - { - ea = i386_translate( cpustate->segment_override, REG16(BX) + REG8(AL), 0, 1); - } - else - { - ea = i386_translate( cpustate->segment_override, REG32(EBX) + REG8(AL), 0, 1); - } - } else { - if(!cpustate->address_size) - { - ea = i386_translate( DS, REG16(BX) + REG8(AL), 0, 1); - } - else - { - ea = i386_translate( DS, REG32(EBX) + REG8(AL), 0, 1); - } - } - REG8(AL) = READ8(ea); - CYCLES(CYCLES_XLAT); -} -#endif diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.h b/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.h deleted file mode 100644 index d53599f41..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386ops.h +++ /dev/null @@ -1,36 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -#ifndef __LIB_I386_OPS_OPS_H__ -#define __LIB_I386_OPS_OPS_H__ -class I386_OPS_BASE; -typedef struct X86_OPCODE { - UINT8 opcode; - UINT32 flags; - void (I386_OPS_BASE::*handler16)(); - void (I386_OPS_BASE::*handler32)(); - bool lockable; -}; - -#define OP_I386 0x1 -#define OP_FPU 0x2 -#define OP_I486 0x4 -#define OP_PENTIUM 0x8 -#define OP_MMX 0x10 -#define OP_PPRO 0x20 -#define OP_SSE 0x40 -#define OP_SSE2 0x80 -#define OP_SSE3 0x100 -#define OP_CYRIX 0x8000 -#define OP_2BYTE 0x80000000 -#define OP_3BYTE66 0x40000000 -#define OP_3BYTEF2 0x20000000 -#define OP_3BYTEF3 0x10000000 -#define OP_3BYTE38 0x08000000 -#define OP_3BYTE3A 0x04000000 -#define OP_4BYTE3866 0x02000000 -#define OP_4BYTE3A66 0x01000000 -#define OP_4BYTE38F2 0x00800000 -#define OP_4BYTE3AF2 0x00400000 -#define OP_4BYTE38F3 0x00200000 - -#endif diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i386priv.h b/source/src/vm/libcpu_newdev/libcpu_i386/i386priv.h deleted file mode 100644 index eab4405ec..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i386priv.h +++ /dev/null @@ -1,675 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -#pragma once - -#ifndef __LIB_I386_PRIV_H__ -#define __LIB_I386_PRIV_H__ -#include "../../../common.h" - -#define INLINE inline - -// Translation intentions -const int TRANSLATE_TYPE_MASK = 0x03; // read write or fetch -const int TRANSLATE_USER_MASK = 0x04; // user mode or fully privileged -const int TRANSLATE_DEBUG_MASK = 0x08; // debug mode (no side effects) - -const int TRANSLATE_READ = 0; // translate for read -const int TRANSLATE_WRITE = 1; // translate for write -const int TRANSLATE_FETCH = 2; // translate for instruction fetch -const int TRANSLATE_READ_USER = (TRANSLATE_READ | TRANSLATE_USER_MASK); -const int TRANSLATE_WRITE_USER = (TRANSLATE_WRITE | TRANSLATE_USER_MASK); -const int TRANSLATE_FETCH_USER = (TRANSLATE_FETCH | TRANSLATE_USER_MASK); -const int TRANSLATE_READ_DEBUG = (TRANSLATE_READ | TRANSLATE_DEBUG_MASK); -const int TRANSLATE_WRITE_DEBUG = (TRANSLATE_WRITE | TRANSLATE_DEBUG_MASK); -const int TRANSLATE_FETCH_DEBUG = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MASK); - -/*****************************************************************************/ -/* 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/emumem.h */ - -// helpers for checking address alignment -#define WORD_ALIGNED(a) (((a) & 1) == 0) -#define DWORD_ALIGNED(a) (((a) & 3) == 0) -#define QWORD_ALIGNED(a) (((a) & 7) == 0) - -/*****************************************************************************/ -/* src/emu/memory.h */ - -// address spaces -enum address_spacenum -{ - AS_0, // first address space - AS_1, // second address space - AS_2, // third address space - AS_3, // fourth address space - ADDRESS_SPACES, // maximum number of address spaces - - // alternate address space names for common use - AS_PROGRAM = AS_0, // program address space - AS_DATA = AS_1, // data address space - AS_IO = AS_2 // I/O address space -}; - -// 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])) - -#include "../libcpu_softfloat/milieu.h" -#include "../libcpu_softfloat/softfloat.h" -#include "./vtlb.h" -#include - -//#define DEBUG_MISSING_OPCODE - -#define I386OP(XX) I386_OPS_BASE::i386_##XX -#define I486OP(XX) I386_OPS_BASE::i486_##XX -#define PENTIUMOP(XX) I386_OPS_BASE::pentium_##XX -#define MMXOP(XX) I386_OPS_BASE::mmx_##XX -#define SSEOP(XX) I386_OPS_BASE::sse_##XX - -#define I386OP_D(XX) i386_##XX -#define I486OP_D(XX) i486_##XX -#define PENTIUMOP_D(XX) pentium_##XX -#define MMXOP_D(XX) mmx_##XX -#define SSEOP_D(XX) sse_##XX - -//extern int i386_dasm_one(_TCHAR *buffer, UINT32 pc, const UINT8 *oprom, int mode); - -enum SREGS { ES, CS, SS, DS, FS, GS }; - -enum BREGS -{ - AL = NATIVE_ENDIAN_VALUE_LE_BE(0,3), - AH = NATIVE_ENDIAN_VALUE_LE_BE(1,2), - CL = NATIVE_ENDIAN_VALUE_LE_BE(4,7), - CH = NATIVE_ENDIAN_VALUE_LE_BE(5,6), - DL = NATIVE_ENDIAN_VALUE_LE_BE(8,11), - DH = NATIVE_ENDIAN_VALUE_LE_BE(9,10), - BL = NATIVE_ENDIAN_VALUE_LE_BE(12,15), - BH = NATIVE_ENDIAN_VALUE_LE_BE(13,14) -}; - -enum WREGS -{ - AX = NATIVE_ENDIAN_VALUE_LE_BE(0,1), - CX = NATIVE_ENDIAN_VALUE_LE_BE(2,3), - DX = NATIVE_ENDIAN_VALUE_LE_BE(4,5), - BX = NATIVE_ENDIAN_VALUE_LE_BE(6,7), - SP = NATIVE_ENDIAN_VALUE_LE_BE(8,9), - BP = NATIVE_ENDIAN_VALUE_LE_BE(10,11), - SI = NATIVE_ENDIAN_VALUE_LE_BE(12,13), - DI = NATIVE_ENDIAN_VALUE_LE_BE(14,15) -}; - -enum DREGS { EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI }; - -enum -{ - I386_PC = 0, - - /* 8-bit registers */ - I386_AL, - I386_AH, - I386_BL, - I386_BH, - I386_CL, - I386_CH, - I386_DL, - I386_DH, - - /* 16-bit registers */ - I386_AX, - I386_BX, - I386_CX, - I386_DX, - I386_BP, - I386_SP, - I386_SI, - I386_DI, - I386_IP, - - /* 32-bit registers */ - I386_EAX, - I386_ECX, - I386_EDX, - I386_EBX, - I386_EBP, - I386_ESP, - I386_ESI, - I386_EDI, - I386_EIP, - - /* segment registers */ - I386_CS, - I386_CS_BASE, - I386_CS_LIMIT, - I386_CS_FLAGS, - I386_SS, - I386_SS_BASE, - I386_SS_LIMIT, - I386_SS_FLAGS, - I386_DS, - I386_DS_BASE, - I386_DS_LIMIT, - I386_DS_FLAGS, - I386_ES, - I386_ES_BASE, - I386_ES_LIMIT, - I386_ES_FLAGS, - I386_FS, - I386_FS_BASE, - I386_FS_LIMIT, - I386_FS_FLAGS, - I386_GS, - I386_GS_BASE, - I386_GS_LIMIT, - I386_GS_FLAGS, - - /* other */ - I386_EFLAGS, - - I386_CR0, - I386_CR1, - I386_CR2, - I386_CR3, - I386_CR4, - - I386_DR0, - I386_DR1, - I386_DR2, - I386_DR3, - I386_DR4, - I386_DR5, - I386_DR6, - I386_DR7, - - I386_TR6, - I386_TR7, - - I386_GDTR_BASE, - I386_GDTR_LIMIT, - I386_IDTR_BASE, - I386_IDTR_LIMIT, - I386_TR, - I386_TR_BASE, - I386_TR_LIMIT, - I386_TR_FLAGS, - I386_LDTR, - I386_LDTR_BASE, - I386_LDTR_LIMIT, - I386_LDTR_FLAGS, - - I386_CPL, - - X87_CTRL, - X87_STATUS, - X87_TAG, - X87_ST0, - X87_ST1, - X87_ST2, - X87_ST3, - X87_ST4, - X87_ST5, - X87_ST6, - X87_ST7, - - SSE_XMM0, - SSE_XMM1, - SSE_XMM2, - SSE_XMM3, - SSE_XMM4, - SSE_XMM5, - SSE_XMM6, - SSE_XMM7 -}; - -enum -{ - /* mmx registers aliased to x87 ones */ - MMX_MM0=X87_ST0, - MMX_MM1=X87_ST1, - MMX_MM2=X87_ST2, - MMX_MM3=X87_ST3, - MMX_MM4=X87_ST4, - MMX_MM5=X87_ST5, - MMX_MM6=X87_ST6, - MMX_MM7=X87_ST7 -}; - -enum smram -{ - SMRAM_SMBASE = 0xF8, - SMRAM_SMREV = 0xFC, - SMRAM_IORSRT = 0x100, - SMRAM_AHALT = 0x102, - SMRAM_IOEDI = 0x104, - SMRAM_IOECX = 0x108, - SMRAM_IOESI = 0x10C, - - SMRAM_ES = 0x1A8, - SMRAM_CS = 0x1AC, - SMRAM_SS = 0x1B0, - SMRAM_DS = 0x1B4, - SMRAM_FS = 0x1B8, - SMRAM_GS = 0x1BC, - SMRAM_LDTR = 0x1C0, - SMRAM_TR = 0x1C4, - SMRAM_DR7 = 0x1C8, - SMRAM_DR6 = 0x1CC, - SMRAM_EAX = 0x1D0, - SMRAM_ECX = 0x1D4, - SMRAM_EDX = 0x1D8, - SMRAM_EBX = 0x1DC, - SMRAM_ESP = 0x1E0, - SMRAM_EBP = 0x1E4, - SMRAM_ESI = 0x1E8, - SMRAM_EDI = 0x1EC, - SMRAM_EIP = 0x1F0, - SMRAM_EFLAGS = 0x1F4, - SMRAM_CR3 = 0x1F8, - SMRAM_CR0 = 0x1FC, -}; - -enum smram_intel_p5 -{ - SMRAM_IP5_IOEIP = 0x110, - SMRAM_IP5_CR4 = 0x128, - SMRAM_IP5_ESLIM = 0x130, - SMRAM_IP5_ESBASE = 0x134, - SMRAM_IP5_ESACC = 0x138, - SMRAM_IP5_CSLIM = 0x13C, - SMRAM_IP5_CSBASE = 0x140, - SMRAM_IP5_CSACC = 0x144, - SMRAM_IP5_SSLIM = 0x148, - SMRAM_IP5_SSBASE = 0x14C, - SMRAM_IP5_SSACC = 0x150, - SMRAM_IP5_DSLIM = 0x154, - SMRAM_IP5_DSBASE = 0x158, - SMRAM_IP5_DSACC = 0x15C, - SMRAM_IP5_FSLIM = 0x160, - SMRAM_IP5_FSBASE = 0x164, - SMRAM_IP5_FSACC = 0x168, - SMRAM_IP5_GSLIM = 0x16C, - SMRAM_IP5_GSBASE = 0x170, - SMRAM_IP5_GSACC = 0x174, - SMRAM_IP5_LDTLIM = 0x178, - SMRAM_IP5_LDTBASE = 0x17C, - SMRAM_IP5_LDTACC = 0x180, - SMRAM_IP5_GDTLIM = 0x184, - SMRAM_IP5_GDTBASE = 0x188, - SMRAM_IP5_GDTACC = 0x18C, - SMRAM_IP5_IDTLIM = 0x190, - SMRAM_IP5_IDTBASE = 0x194, - SMRAM_IP5_IDTACC = 0x198, - SMRAM_IP5_TRLIM = 0x19C, - SMRAM_IP5_TRBASE = 0x1A0, - SMRAM_IP5_TRACC = 0x1A4, -}; - -/* Protected mode exceptions */ -#defile FAULT_DE 0 // F -#defile FAULT_DB 1 // DEBUG -#defile FAULT_NMI 2 // NMI -#defile FAULT_BP 3 // -#defile FAULT_OF 4 // -#defile FAULT_BR 5 // -#define FAULT_UD 6 // Invalid Opcode -#define FAULT_NM 7 // Coprocessor not available -#define FAULT_DF 8 // Double Fault -#define FAULT_TS 10 // Invalid TSS -#define FAULT_NP 11 // Segment or Gate not present -#define FAULT_SS 12 // Stack fault -#define FAULT_GP 13 // General Protection Fault -#define FAULT_PF 14 // Page Fault -#define FAULT_RSV 15 // *Reserved* -#define FAULT_MF 16 // Match (Coprocessor) Fault -#define FAULT_AC 17 // -#define FAULT_MC 18 // -#define FAULT_XF 19 // - -/* MXCSR Control and Status Register */ -#define MXCSR_IE (1<<0) // Invalid Operation Flag -#define MXCSR_DE (1<<1) // Denormal Flag -#define MXCSR_ZE (1<<2) // Divide-by-Zero Flag -#define MXCSR_OE (1<<3) // Overflow Flag -#define MXCSR_UE (1<<4) // Underflow Flag -#define MXCSR_PE (1<<5) // Precision Flag -#define MXCSR_DAZ (1<<6) // Denormals Are Zeros -#define MXCSR_IM (1<<7) // Invalid Operation Mask -#define MXCSR_DM (1<<8) // Denormal Operation Mask -#define MXCSR_ZM (1<<9) // Divide-by-Zero Mask -#define MXCSR_OM (1<<10) // Overflow Mask -#define MXCSR_UM (1<<11) // Underflow Mask -#define MXCSR_PM (1<<12) // Precision Mask -#define MXCSR_RC (3<<13) // Rounding Control -#define MXCSR_FZ (1<<15) // Flush to Zero - -struct I386_SREG { - UINT16 selector; - UINT16 flags; - UINT32 base; - UINT32 limit; - int d; // Operand size - bool valid; -}; - -struct I386_CALL_GATE -{ - UINT16 segment; - UINT16 selector; - UINT32 offset; - UINT8 ar; // access rights - UINT8 dpl; - UINT8 dword_count; - UINT8 present; -}; - -struct I386_SYS_TABLE { - UINT32 base; - UINT16 limit; -}; - -struct I386_SEG_DESC { - UINT16 segment; - UINT16 flags; - UINT32 base; - UINT32 limit; -}; - -union I386_GPR { - UINT32 d[8]; - UINT16 w[16]; - UINT8 b[32]; -}; - -union MMX_REG { - UINT32 d[2]; - INT32 i[2]; - UINT16 w[4]; - INT16 s[4]; - UINT8 b[8]; - INT8 c[8]; - float f[2]; - UINT64 q; - INT64 l; -}; - -union XMM_REG { - UINT8 b[16]; - UINT16 w[8]; - UINT32 d[4]; - UINT64 q[2]; - INT8 c[16]; - INT16 s[8]; - INT32 i[4]; - INT64 l[2]; - float f[4]; - double f64[2]; -}; - -struct vtlb_state; -class EMU; -class DEBUGGER; -class DEVICE; -class I386_OPS_BASE; -struct i386_state -{ - I386_GPR reg; - I386_SREG sreg[6]; - UINT32 eip; - UINT32 pc; - UINT32 prev_eip; - UINT32 prev_pc; - UINT32 eflags; - UINT32 eflags_mask; - UINT8 CF; - UINT8 DF; - UINT8 SF; - UINT8 OF; - UINT8 ZF; - UINT8 PF; - UINT8 AF; - UINT8 IF; - UINT8 TF; - UINT8 IOP1; - UINT8 IOP2; - UINT8 NT; - UINT8 RF; - UINT8 VM; - UINT8 AC; - UINT8 VIF; - UINT8 VIP; - UINT8 ID; - - UINT8 CPL; // current privilege level - - UINT8 performed_intersegment_jump; - UINT8 delayed_interrupt_enable; - - UINT32 cr[5]; // Control registers - UINT32 dr[8]; // Debug registers - UINT32 tr[8]; // Test registers - - I386_SYS_TABLE gdtr; // Global Descriptor Table Register - I386_SYS_TABLE idtr; // Interrupt Descriptor Table Register - I386_SEG_DESC task; // Task register - I386_SEG_DESC ldtr; // Local Descriptor Table Register - - UINT8 ext; // external interrupt - - int halted; - int busreq; - int shutdown; - - int operand_size; - int xmm_operand_size; - int address_size; - int operand_prefix; - int address_prefix; - - int segment_prefix; - int segment_override; - - uint64_t total_cycles; - uint64_t prev_total_cycles; - - int cycles; - int extra_cycles; - int base_cycles; - UINT8 opcode; - - UINT8 irq_state; - DEVICE *pic; - DEVICE *program; - DEVICE *io; -//#ifdef I386_PSEUDO_BIOS - DEVICE *bios; -//#endif -//#ifdef SINGLE_MODE_DMA - DEVICE *dma; -//#endif -//#ifdef USE_DEBUGGER - EMU *emu; - DEBUGGER *debugger; - DEVICE *program_stored; - DEVICE *io_stored; -//#endif - UINT32 a20_mask; - - int cpuid_max_input_value_eax; - UINT32 cpuid_id0, cpuid_id1, cpuid_id2; - UINT32 cpu_version; - UINT32 feature_flags; - UINT64 tsc; - UINT64 perfctr[2]; - - // FPU - floatx80 x87_reg[8]; - - UINT16 x87_cw; - UINT16 x87_sw; - UINT16 x87_tw; - UINT64 x87_data_ptr; - UINT64 x87_inst_ptr; - UINT16 x87_opcode; - - void (I386_OPS_BASE::*opcode_table_x87_d8[256])(UINT8 modrm); - void (I386_OPS_BASE::*opcode_table_x87_d9[256])(UINT8 modrm); - void (I386_OPS_BASE::*opcode_table_x87_da[256])(UINT8 modrm); - void (I386_OPS_BASE::*opcode_table_x87_db[256])(UINT8 modrm); - void (I386_OPS_BASE::*opcode_table_x87_dc[256])(UINT8 modrm); - void (I386_OPS_BASE::*opcode_table_x87_dd[256])(UINT8 modrm); - void (I386_OPS_BASE::*opcode_table_x87_de[256])(UINT8 modrm); - void (I386_OPS_BASE::*opcode_table_x87_df[256])(UINT8 modrm); - - // SSE - XMM_REG sse_reg[8]; - UINT32 mxcsr; - - void (I386_OPS_BASE::*opcode_table1_16[256])(); - void (I386_OPS_BASE::*opcode_table1_32[256])(); - void (I386_OPS_BASE::*opcode_table2_16[256])(); - void (I386_OPS_BASE::*opcode_table2_32[256])(); - void (I386_OPS_BASE::*opcode_table338_16[256])(); - void (I386_OPS_BASE::*opcode_table338_32[256])(); - void (I386_OPS_BASE::*opcode_table33a_16[256])(); - void (I386_OPS_BASE::*opcode_table33a_32[256])(); - void (I386_OPS_BASE::*opcode_table366_16[256])(); - void (I386_OPS_BASE::*opcode_table366_32[256])(); - void (I386_OPS_BASE::*opcode_table3f2_16[256])(); - void (I386_OPS_BASE::*opcode_table3f2_32[256])(); - void (I386_OPS_BASE::*opcode_table3f3_16[256])(); - void (I386_OPS_BASE::*opcode_table3f3_32[256])(); - void (I386_OPS_BASE::*opcode_table46638_16[256])(); - void (I386_OPS_BASE::*opcode_table46638_32[256])(); - void (I386_OPS_BASE::*opcode_table4f238_16[256])(); - void (I386_OPS_BASE::*opcode_table4f238_32[256])(); - void (I386_OPS_BASE::*opcode_table4f338_16[256])(); - void (I386_OPS_BASE::*opcode_table4f338_32[256])(); - void (I386_OPS_BASE::*opcode_table4663a_16[256])(); - void (I386_OPS_BASE::*opcode_table4663a_32[256])(); - void (I386_OPS_BASE::*opcode_table4f23a_16[256])(); - void (I386_OPS_BASE::*opcode_table4f23a_32[256])(); - - bool lock_table[2][256]; - - UINT8 *cycle_table_pm; - UINT8 *cycle_table_rm; - - vtlb_state *vtlb; - - bool smm; - bool smi; - bool smi_latched; - bool nmi_masked; - bool nmi_latched; - UINT32 smbase; -// devcb_resolved_write_line smiact; - bool lock; - - // bytes in current opcode, debug only -#ifdef DEBUG_MISSING_OPCODE - UINT8 opcode_bytes[16]; - UINT32 opcode_pc; - int opcode_bytes_length; -#endif -}; - - -#define FAULT_THROW(fault,error) { throw (UINT64)(fault | (UINT64)error << 32); } -#define PF_THROW(error) { cpustate->cr[2] = address; FAULT_THROW(FAULT_PF,error); } - -#define PROTECTED_MODE (cpustate->cr[0] & 0x1) -#define STACK_32BIT (cpustate->sreg[SS].d) -#define V8086_MODE (cpustate->VM) -#define NESTED_TASK (cpustate->NT) -#define WP (cpustate->cr[0] & 0x10000) - -#define SetOF_Add32(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0) -#define SetOF_Add16(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0) -#define SetOF_Add8(r,s,d) (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? 1 : 0) - -#define SetOF_Sub32(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0) -#define SetOF_Sub16(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0) -#define SetOF_Sub8(r,s,d) (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0) - -#define SetCF8(x) {cpustate->CF = ((x) & 0x100) ? 1 : 0; } -#define SetCF16(x) {cpustate->CF = ((x) & 0x10000) ? 1 : 0; } -#define SetCF32(x) {cpustate->CF = ((x) & (((UINT64)1) << 32)) ? 1 : 0; } - -#define SetSF(x) (cpustate->SF = (x)) -#define SetZF(x) (cpustate->ZF = (x)) -#define SetAF(x,y,z) (cpustate->AF = (((x) ^ ((y) ^ (z))) & 0x10) ? 1 : 0) -#define SetPF(x) (cpustate->PF = i386_parity_table[(x) & 0xFF]) - -#define SetSZPF8(x) {cpustate->ZF = ((UINT8)(x)==0); cpustate->SF = ((x)&0x80) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; } -#define SetSZPF16(x) {cpustate->ZF = ((UINT16)(x)==0); cpustate->SF = ((x)&0x8000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; } -#define SetSZPF32(x) {cpustate->ZF = ((UINT32)(x)==0); cpustate->SF = ((x)&0x80000000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; } - -#define MMX(n) (*((MMX_REG *)(&cpustate->x87_reg[(n)].low))) -#define XMM(n) cpustate->sse_reg[(n)] - -/***********************************************************************************/ - -struct MODRM_TABLE { - struct { - int b; - int w; - int d; - } reg; - struct { - int b; - int w; - int d; - } rm; -}; - -#define REG8(x) (cpustate->reg.b[x]) -#define REG16(x) (cpustate->reg.w[x]) -#define REG32(x) (cpustate->reg.d[x]) - -#define LOAD_REG8(x) (REG8(i386_MODRM_table[x].reg.b)) -#define LOAD_REG16(x) (REG16(i386_MODRM_table[x].reg.w)) -#define LOAD_REG32(x) (REG32(i386_MODRM_table[x].reg.d)) -#define LOAD_RM8(x) (REG8(i386_MODRM_table[x].rm.b)) -#define LOAD_RM16(x) (REG16(i386_MODRM_table[x].rm.w)) -#define LOAD_RM32(x) (REG32(i386_MODRM_table[x].rm.d)) - -#define STORE_REG8(x, value) (REG8(i386_MODRM_table[x].reg.b) = value) -#define STORE_REG16(x, value) (REG16(i386_MODRM_table[x].reg.w) = value) -#define STORE_REG32(x, value) (REG32(i386_MODRM_table[x].reg.d) = value) -#define STORE_RM8(x, value) (REG8(i386_MODRM_table[x].rm.b) = value) -#define STORE_RM16(x, value) (REG16(i386_MODRM_table[x].rm.w) = value) -#define STORE_RM32(x, value) (REG32(i386_MODRM_table[x].rm.d) = value) - -#define SWITCH_ENDIAN_32(x) (((((x) << 24) & (0xff << 24)) | (((x) << 8) & (0xff << 16)) | (((x) >> 8) & (0xff << 8)) | (((x) >> 24) & (0xff << 0)))) - - -#endif /* __I386_H__ */ diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/i486ops.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/i486ops.cpp deleted file mode 100644 index a8287cc0d..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/i486ops.cpp +++ /dev/null @@ -1,528 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -// Intel 486+ specific opcodes -#include "./i386_opdef.h" - -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} - -void I386_OPS_BASE::I486OP(cpuid)() // Opcode 0x0F A2 -{ - if (cpustate->cpuid_id0 == 0) - { - // this 486 doesn't support the CPUID instruction - logerror("CPUID not supported at %08x!\n", cpustate->eip); - i386_trap( 6, 0, 0); - } - else - { - switch (REG32(EAX)) - { - case 0: - { - REG32(EAX) = cpustate->cpuid_max_input_value_eax; - REG32(EBX) = cpustate->cpuid_id0; - REG32(ECX) = cpustate->cpuid_id2; - REG32(EDX) = cpustate->cpuid_id1; - CYCLES(CYCLES_CPUID); - break; - } - - case 1: - { - REG32(EAX) = cpustate->cpu_version; - REG32(EDX) = cpustate->feature_flags; - CYCLES(CYCLES_CPUID_EAX1); - break; - } - } - } -} - -void I386_OPS_BASE::I486OP(invd)() // Opcode 0x0f 08 -{ - // Nothing to do ? - CYCLES(CYCLES_INVD); -} - -void I386_OPS_BASE::I486OP(wbinvd)() // Opcode 0x0f 09 -{ - // Nothing to do ? -} - -void I386_OPS_BASE::I486OP(cmpxchg_rm8_r8)() // Opcode 0x0f b0 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - UINT8 src = LOAD_REG8(modrm); - - if( REG8(AL) == dst ) { - STORE_RM8(modrm, src); - cpustate->ZF = 1; - CYCLES(CYCLES_CMPXCHG_REG_REG_T); - } else { - REG8(AL) = dst; - cpustate->ZF = 0; - CYCLES(CYCLES_CMPXCHG_REG_REG_F); - } - } else { - // TODO: Check write if needed - UINT32 ea = GetEA(modrm, 0, 1); - UINT8 dst = READ8(ea); - UINT8 src = LOAD_REG8(modrm); - - if( REG8(AL) == dst ) { - WRITE8(ea, src); - cpustate->ZF = 1; - CYCLES(CYCLES_CMPXCHG_REG_MEM_T); - } else { - REG8(AL) = dst; - cpustate->ZF = 0; - CYCLES(CYCLES_CMPXCHG_REG_MEM_F); - } - } -} - -void I386_OPS_BASE::I486OP(cmpxchg_rm16_r16)() // Opcode 0x0f b1 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 src = LOAD_REG16(modrm); - - if( REG16(AX) == dst ) { - STORE_RM16(modrm, src); - cpustate->ZF = 1; - CYCLES(CYCLES_CMPXCHG_REG_REG_T); - } else { - REG16(AX) = dst; - cpustate->ZF = 0; - CYCLES(CYCLES_CMPXCHG_REG_REG_F); - } - } else { - UINT32 ea = GetEA(modrm, 0, 2); - UINT16 dst = READ16(ea); - UINT16 src = LOAD_REG16(modrm); - - if( REG16(AX) == dst ) { - WRITE16(ea, src); - cpustate->ZF = 1; - CYCLES(CYCLES_CMPXCHG_REG_MEM_T); - } else { - REG16(AX) = dst; - cpustate->ZF = 0; - CYCLES(CYCLES_CMPXCHG_REG_MEM_F); - } - } -} - -void I386_OPS_BASE::I486OP(cmpxchg_rm32_r32)() // Opcode 0x0f b1 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 src = LOAD_REG32(modrm); - - if( REG32(EAX) == dst ) { - STORE_RM32(modrm, src); - cpustate->ZF = 1; - CYCLES(CYCLES_CMPXCHG_REG_REG_T); - } else { - REG32(EAX) = dst; - cpustate->ZF = 0; - CYCLES(CYCLES_CMPXCHG_REG_REG_F); - } - } else { - UINT32 ea = GetEA(modrm, 0, 4); - UINT32 dst = READ32(ea); - UINT32 src = LOAD_REG32(modrm); - - if( REG32(EAX) == dst ) { - WRITE32(ea, src); - cpustate->ZF = 1; - CYCLES(CYCLES_CMPXCHG_REG_MEM_T); - } else { - REG32(EAX) = dst; - cpustate->ZF = 0; - CYCLES(CYCLES_CMPXCHG_REG_MEM_F); - } - } -} - -void I386_OPS_BASE::I486OP(xadd_rm8_r8)() // Opcode 0x0f c0 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 dst = LOAD_RM8(modrm); - UINT8 src = LOAD_REG8(modrm); - UINT8 sum = ADD8(dst, src); - STORE_REG8(modrm, dst); - STORE_RM8(modrm, sum); - CYCLES(CYCLES_XADD_REG_REG); - } else { - UINT32 ea = GetEA(modrm, 1, 1); - UINT8 dst = READ8(ea); - UINT8 src = LOAD_REG8(modrm); - UINT8 sum = ADD8(dst, src); - WRITE8(ea, sum); - STORE_REG8(modrm, dst); - CYCLES(CYCLES_XADD_REG_MEM); - } -} - -void I386_OPS_BASE::I486OP(xadd_rm16_r16)() // Opcode 0x0f c1 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 dst = LOAD_RM16(modrm); - UINT16 src = LOAD_REG16(modrm); - UINT16 sum = ADD16(dst, src); - STORE_REG16(modrm, dst); - STORE_RM16(modrm, sum); - CYCLES(CYCLES_XADD_REG_REG); - } else { - UINT32 ea = GetEA(modrm, 1, 2); - UINT16 dst = READ16(ea); - UINT16 src = LOAD_REG16(modrm); - UINT16 sum = ADD16(dst, src); - WRITE16(ea, sum); - STORE_REG16(modrm, dst); - CYCLES(CYCLES_XADD_REG_MEM); - } -} - -void I386_OPS_BASE::I486OP(xadd_rm32_r32)() // Opcode 0x0f c1 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 dst = LOAD_RM32(modrm); - UINT32 src = LOAD_REG32(modrm); - UINT32 sum = ADD32(dst, src); - STORE_REG32(modrm, dst); - STORE_RM32(modrm, sum); - CYCLES(CYCLES_XADD_REG_REG); - } else { - UINT32 ea = GetEA(modrm, 1, 4); - UINT32 dst = READ32(ea); - UINT32 src = LOAD_REG32(modrm); - UINT32 sum = ADD32(dst, src); - WRITE32(ea, sum); - STORE_REG32(modrm, dst); - CYCLES(CYCLES_XADD_REG_MEM); - } -} - -void I386_OPS_BASE::I486OP(group0F01_16)() // Opcode 0x0f 01 -{ - UINT8 modrm = FETCH(); - UINT16 address; - UINT32 ea; - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* SGDT */ - { - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } else { - ea = GetEA(modrm, 1, 6); - } - WRITE16(ea, cpustate->gdtr.limit); - WRITE32(ea + 2, cpustate->gdtr.base); - CYCLES(CYCLES_SGDT); - break; - } - case 1: /* SIDT */ - { - if (modrm >= 0xc0) - { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } - else - { - ea = GetEA(modrm, 1, 6); - } - WRITE16(ea, cpustate->idtr.limit); - WRITE32(ea + 2, cpustate->idtr.base); - CYCLES(CYCLES_SIDT); - break; - } - case 2: /* LGDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm, 0, 6); - } - cpustate->gdtr.limit = READ16(ea); - cpustate->gdtr.base = READ32(ea + 2) & 0xffffff; - CYCLES(CYCLES_LGDT); - break; - } - case 3: /* LIDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM16(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm, 0, 6); - } - cpustate->idtr.limit = READ16(ea); - cpustate->idtr.base = READ32(ea + 2) & 0xffffff; - CYCLES(CYCLES_LIDT); - break; - } - case 4: /* SMSW */ - { - if( modrm >= 0xc0 ) { - STORE_RM16(modrm, cpustate->cr[0]); - CYCLES(CYCLES_SMSW_REG); - } else { - ea = GetEA(modrm, 1, 2); - WRITE16(ea, cpustate->cr[0]); - CYCLES(CYCLES_SMSW_MEM); - } - break; - } - case 6: /* LMSW */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - UINT16 b; - if( modrm >= 0xc0 ) { - b = LOAD_RM16(modrm); - CYCLES(CYCLES_LMSW_REG); - } else { - ea = GetEA(modrm, 0, 2); - CYCLES(CYCLES_LMSW_MEM); - b = READ16(ea); - } - if(PROTECTED_MODE) - b |= 0x0001; // cannot return to real mode using this instruction. - cpustate->cr[0] &= ~0x0000000f; - cpustate->cr[0] |= b & 0x0000000f; - break; - } - case 7: /* INVLPG */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if(modrm >= 0xc0) - { - logerror("i486: invlpg with modrm %02X\n", modrm); - FAULT(FAULT_UD,0) - } - ea = GetEA(modrm, -1, 1); - CYCLES(25); // TODO: add to cycles.h - vtlb_flush_address(cpustate->vtlb, ea); - break; - } - default: - report_invalid_modrm( "group0F01_16", modrm); - break; - } -} - -void I386_OPS_BASE::I486OP(group0F01_32)() // Opcode 0x0f 01 -{ - UINT8 modrm = FETCH(); - UINT32 address, ea; - - switch( (modrm >> 3) & 0x7 ) - { - case 0: /* SGDT */ - { - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } else { - ea = GetEA(modrm, 1, 6); - } - WRITE16(ea, cpustate->gdtr.limit); - WRITE32(ea + 2, cpustate->gdtr.base); - CYCLES(CYCLES_SGDT); - break; - } - case 1: /* SIDT */ - { - if (modrm >= 0xc0) - { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 1, 6 ); - } - else - { - ea = GetEA(modrm, 1, 6); - } - WRITE16(ea, cpustate->idtr.limit); - WRITE32(ea + 2, cpustate->idtr.base); - CYCLES(CYCLES_SIDT); - break; - } - case 2: /* LGDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm, 0, 6); - } - cpustate->gdtr.limit = READ16(ea); - cpustate->gdtr.base = READ32(ea + 2); - CYCLES(CYCLES_LGDT); - break; - } - case 3: /* LIDT */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if( modrm >= 0xc0 ) { - address = LOAD_RM32(modrm); - ea = i386_translate( CS, address, 0, 6 ); - } else { - ea = GetEA(modrm, 0, 6); - } - cpustate->idtr.limit = READ16(ea); - cpustate->idtr.base = READ32(ea + 2); - CYCLES(CYCLES_LIDT); - break; - } - case 4: /* SMSW */ - { - if( modrm >= 0xc0 ) { - STORE_RM32(modrm, cpustate->cr[0] & 0xffff); - CYCLES(CYCLES_SMSW_REG); - } else { - /* always 16-bit memory operand */ - ea = GetEA(modrm, 1, 2); - WRITE16(ea, cpustate->cr[0]); - CYCLES(CYCLES_SMSW_MEM); - } - break; - } - case 6: /* LMSW */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - UINT16 b; - if( modrm >= 0xc0 ) { - b = LOAD_RM16(modrm); - CYCLES(CYCLES_LMSW_REG); - } else { - ea = GetEA(modrm, 0, 2); - CYCLES(CYCLES_LMSW_MEM); - b = READ16(ea); - } - if(PROTECTED_MODE) - b |= 0x0001; // cannot return to real mode using this instruction. - cpustate->cr[0] &= ~0x0000000f; - cpustate->cr[0] |= b & 0x0000000f; - break; - } - case 7: /* INVLPG */ - { - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP,0) - if(modrm >= 0xc0) - { - logerror("i486: invlpg with modrm %02X\n", modrm); - FAULT(FAULT_UD,0) - } - ea = GetEA(modrm, -1, 1); - CYCLES(25); // TODO: add to cycles.h - vtlb_flush_address(cpustate->vtlb, ea); - break; - } - default: - report_invalid_modrm( "group0F01_32", modrm); - break; - } -} - -void I386_OPS_BASE::I486OP(bswap_eax)() // Opcode 0x0f 38 -{ - REG32(EAX) = SWITCH_ENDIAN_32(REG32(EAX)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(bswap_ecx)() // Opcode 0x0f 39 -{ - REG32(ECX) = SWITCH_ENDIAN_32(REG32(ECX)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(bswap_edx)() // Opcode 0x0f 3A -{ - REG32(EDX) = SWITCH_ENDIAN_32(REG32(EDX)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(bswap_ebx)() // Opcode 0x0f 3B -{ - REG32(EBX) = SWITCH_ENDIAN_32(REG32(EBX)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(bswap_esp)() // Opcode 0x0f 3C -{ - REG32(ESP) = SWITCH_ENDIAN_32(REG32(ESP)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(bswap_ebp)() // Opcode 0x0f 3D -{ - REG32(EBP) = SWITCH_ENDIAN_32(REG32(EBP)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(bswap_esi)() // Opcode 0x0f 3E -{ - REG32(ESI) = SWITCH_ENDIAN_32(REG32(ESI)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(bswap_edi)() // Opcode 0x0f 3F -{ - REG32(EDI) = SWITCH_ENDIAN_32(REG32(EDI)); - CYCLES(1); // TODO -} - -void I386_OPS_BASE::I486OP(mov_cr_r32)() // Opcode 0x0f 22 -{ - if(PROTECTED_MODE && cpustate->CPL) - FAULT(FAULT_GP, 0); - UINT8 modrm = FETCH(); - UINT8 cr = (modrm >> 3) & 0x7; - UINT32 oldcr = cpustate->cr[cr]; - UINT32 data = LOAD_RM32(modrm); - switch(cr) - { - case 0: - CYCLES(CYCLES_MOV_REG_CR0); - if((oldcr ^ cpustate->cr[cr]) & 0x80010000) - vtlb_flush_dynamic(cpustate->vtlb); -// if (PROTECTED_MODE != BIT(data, 0)) -// debugger_privilege_hook(); - break; - case 2: CYCLES(CYCLES_MOV_REG_CR2); break; - case 3: - CYCLES(CYCLES_MOV_REG_CR3); - vtlb_flush_dynamic(cpustate->vtlb); - break; - case 4: CYCLES(1); break; // TODO - default: - logerror("i386: mov_cr_r32 CR%d!\n", cr); - return; - } - cpustate->cr[cr] = data; -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/pentops.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/pentops.cpp deleted file mode 100644 index 22073566e..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/pentops.cpp +++ /dev/null @@ -1,6578 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett -// Pentium+ specific opcodes -#include "./i386_opdef.h" - -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} - -extern flag float32_is_nan( float32 a ); // since its not defined in softfloat.h -extern flag float64_is_nan( float64 a ); // since its not defined in softfloat.h - -void I386_OPS_BASE::PENTIUMOP(rdmsr)() // Opcode 0x0f 32 -{ - UINT64 data; - UINT8 valid_msr = 0; - - data = MSR_READ(REG32(ECX),&valid_msr); - - if(cpustate->CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized ... - FAULT(FAULT_GP,0) // ... throw a general exception fault - else - { - REG32(EDX) = data >> 32; - REG32(EAX) = data & 0xffffffff; - } - - CYCLES(CYCLES_RDMSR); -} - - void I386_OPS_BASE::PENTIUMOP(wrmsr)() // Opcode 0x0f 30 -{ - UINT64 data; - UINT8 valid_msr = 0; - - data = (UINT64)REG32(EAX); - data |= (UINT64)(REG32(EDX)) << 32; - - MSR_WRITE(REG32(ECX),data,&valid_msr); - - if(cpustate->CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized - FAULT(FAULT_GP,0) // ... throw a general exception fault - - CYCLES(1); // TODO: correct cycle count (~30-45) -} - - void I386_OPS_BASE::PENTIUMOP(rdtsc)() // Opcode 0x0f 31 -{ - UINT64 ts = cpustate->tsc + (cpustate->base_cycles - cpustate->cycles); - REG32(EAX) = (UINT32)(ts); - REG32(EDX) = (UINT32)(ts >> 32); - - CYCLES(CYCLES_RDTSC); -} - - void I386_OPS_BASE::PENTIUMOP(ud2)() // Opcode 0x0f 0b -{ - i386_trap( 6, 0, 0); -} - - void I386_OPS_BASE::PENTIUMOP(rsm)() -{ - UINT32 smram_state = cpustate->smbase + 0xfe00; - if(!cpustate->smm) - { - logerror("i386: Invalid RSM outside SMM at %08X\n", cpustate->pc - 1); - i386_trap( 6, 0, 0); - return; - } - - // load state, no sanity checks anywhere - cpustate->smbase = READ32(smram_state+SMRAM_SMBASE); - cpustate->cr[4] = READ32(smram_state+SMRAM_IP5_CR4); - cpustate->sreg[ES].limit = READ32(smram_state+SMRAM_IP5_ESLIM); - cpustate->sreg[ES].base = READ32(smram_state+SMRAM_IP5_ESBASE); - cpustate->sreg[ES].flags = READ32(smram_state+SMRAM_IP5_ESACC); - cpustate->sreg[CS].limit = READ32(smram_state+SMRAM_IP5_CSLIM); - cpustate->sreg[CS].base = READ32(smram_state+SMRAM_IP5_CSBASE); - cpustate->sreg[CS].flags = READ32(smram_state+SMRAM_IP5_CSACC); - cpustate->sreg[SS].limit = READ32(smram_state+SMRAM_IP5_SSLIM); - cpustate->sreg[SS].base = READ32(smram_state+SMRAM_IP5_SSBASE); - cpustate->sreg[SS].flags = READ32(smram_state+SMRAM_IP5_SSACC); - cpustate->sreg[DS].limit = READ32(smram_state+SMRAM_IP5_DSLIM); - cpustate->sreg[DS].base = READ32(smram_state+SMRAM_IP5_DSBASE); - cpustate->sreg[DS].flags = READ32(smram_state+SMRAM_IP5_DSACC); - cpustate->sreg[FS].limit = READ32(smram_state+SMRAM_IP5_FSLIM); - cpustate->sreg[FS].base = READ32(smram_state+SMRAM_IP5_FSBASE); - cpustate->sreg[FS].flags = READ32(smram_state+SMRAM_IP5_FSACC); - cpustate->sreg[GS].limit = READ32(smram_state+SMRAM_IP5_GSLIM); - cpustate->sreg[GS].base = READ32(smram_state+SMRAM_IP5_GSBASE); - cpustate->sreg[GS].flags = READ32(smram_state+SMRAM_IP5_GSACC); - cpustate->ldtr.flags = READ32(smram_state+SMRAM_IP5_LDTACC); - cpustate->ldtr.limit = READ32(smram_state+SMRAM_IP5_LDTLIM); - cpustate->ldtr.base = READ32(smram_state+SMRAM_IP5_LDTBASE); - cpustate->gdtr.limit = READ32(smram_state+SMRAM_IP5_GDTLIM); - cpustate->gdtr.base = READ32(smram_state+SMRAM_IP5_GDTBASE); - cpustate->idtr.limit = READ32(smram_state+SMRAM_IP5_IDTLIM); - cpustate->idtr.base = READ32(smram_state+SMRAM_IP5_IDTBASE); - cpustate->task.limit = READ32(smram_state+SMRAM_IP5_TRLIM); - cpustate->task.base = READ32(smram_state+SMRAM_IP5_TRBASE); - cpustate->task.flags = READ32(smram_state+SMRAM_IP5_TRACC); - - cpustate->sreg[ES].selector = READ32(smram_state+SMRAM_ES); - cpustate->sreg[CS].selector = READ32(smram_state+SMRAM_CS); - cpustate->sreg[SS].selector = READ32(smram_state+SMRAM_SS); - cpustate->sreg[DS].selector = READ32(smram_state+SMRAM_DS); - cpustate->sreg[FS].selector = READ32(smram_state+SMRAM_FS); - cpustate->sreg[GS].selector = READ32(smram_state+SMRAM_GS); - cpustate->ldtr.segment = READ32(smram_state+SMRAM_LDTR); - cpustate->task.segment = READ32(smram_state+SMRAM_TR); - - cpustate->dr[7] = READ32(smram_state+SMRAM_DR7); - cpustate->dr[6] = READ32(smram_state+SMRAM_DR6); - REG32(EAX) = READ32(smram_state+SMRAM_EAX); - REG32(ECX) = READ32(smram_state+SMRAM_ECX); - REG32(EDX) = READ32(smram_state+SMRAM_EDX); - REG32(EBX) = READ32(smram_state+SMRAM_EBX); - REG32(ESP) = READ32(smram_state+SMRAM_ESP); - REG32(EBP) = READ32(smram_state+SMRAM_EBP); - REG32(ESI) = READ32(smram_state+SMRAM_ESI); - REG32(EDI) = READ32(smram_state+SMRAM_EDI); - cpustate->eip = READ32(smram_state+SMRAM_EIP); - cpustate->eflags = READ32(smram_state+SMRAM_EFLAGS); - cpustate->cr[3] = READ32(smram_state+SMRAM_CR3); - cpustate->cr[0] = READ32(smram_state+SMRAM_CR0); - - cpustate->CPL = (cpustate->sreg[SS].flags >> 13) & 3; // cpl == dpl of ss - - for(int i = 0; i <= GS; i++) - { - if(PROTECTED_MODE && !V8086_MODE) - { - cpustate->sreg[i].valid = cpustate->sreg[i].selector ? true : false; - cpustate->sreg[i].d = (cpustate->sreg[i].flags & 0x4000) ? 1 : 0; - } - else - cpustate->sreg[i].valid = true; - } - -// if(!cpustate->smiact.isnull()) -// cpustate->smiact(false); - cpustate->smm = false; - - CHANGE_PC(cpustate->eip); - cpustate->nmi_masked = false; - if(cpustate->smi_latched) - { - pentium_smi(); - return; - } - if(cpustate->nmi_latched) - { - cpustate->nmi_latched = false; - i386_trap( 2, 1, 0); - } -} - - void I386_OPS_BASE::PENTIUMOP(prefetch_m8)() // Opcode 0x0f 18 -{ - UINT8 modrm = FETCH(); - UINT32 ea = GetEA(modrm, 0, 1); - CYCLES(1+(ea & 1)); // TODO: correct cycle count -} - - void I386_OPS_BASE::PENTIUMOP(cmovo_r16_rm16)() // Opcode 0x0f 40 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->OF == 1) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->OF == 1) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovo_r32_rm32)() // Opcode 0x0f 40 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->OF == 1) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->OF == 1) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovno_r16_rm16)() // Opcode 0x0f 41 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->OF == 0) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->OF == 0) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovno_r32_rm32)() // Opcode 0x0f 41 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->OF == 0) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->OF == 0) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovb_r16_rm16)() // Opcode 0x0f 42 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->CF == 1) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->CF == 1) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovb_r32_rm32)() // Opcode 0x0f 42 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->CF == 1) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->CF == 1) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovae_r16_rm16)() // Opcode 0x0f 43 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->CF == 0) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->CF == 0) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovae_r32_rm32)() // Opcode 0x0f 43 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->CF == 0) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->CF == 0) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmove_r16_rm16)() // Opcode 0x0f 44 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->ZF == 1) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->ZF == 1) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmove_r32_rm32)() // Opcode 0x0f 44 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->ZF == 1) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->ZF == 1) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovne_r16_rm16)() // Opcode 0x0f 45 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->ZF == 0) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->ZF == 0) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovne_r32_rm32)() // Opcode 0x0f 45 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->ZF == 0) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->ZF == 0) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovbe_r16_rm16)() // Opcode 0x0f 46 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->CF == 1) || (cpustate->ZF == 1)) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if ((cpustate->CF == 1) || (cpustate->ZF == 1)) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovbe_r32_rm32)() // Opcode 0x0f 46 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->CF == 1) || (cpustate->ZF == 1)) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if ((cpustate->CF == 1) || (cpustate->ZF == 1)) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmova_r16_rm16)() // Opcode 0x0f 47 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->CF == 0) && (cpustate->ZF == 0)) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if ((cpustate->CF == 0) && (cpustate->ZF == 0)) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmova_r32_rm32)() // Opcode 0x0f 47 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->CF == 0) && (cpustate->ZF == 0)) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if ((cpustate->CF == 0) && (cpustate->ZF == 0)) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovs_r16_rm16)() // Opcode 0x0f 48 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF == 1) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->SF == 1) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovs_r32_rm32)() // Opcode 0x0f 48 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF == 1) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->SF == 1) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovns_r16_rm16)() // Opcode 0x0f 49 -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF == 0) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->SF == 0) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovns_r32_rm32)() // Opcode 0x0f 49 -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF == 0) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->SF == 0) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovp_r16_rm16)() // Opcode 0x0f 4a -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->PF == 1) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->PF == 1) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovp_r32_rm32)() // Opcode 0x0f 4a -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->PF == 1) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->PF == 1) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovnp_r16_rm16)() // Opcode 0x0f 4b -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->PF == 0) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->PF == 0) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovnp_r32_rm32)() // Opcode 0x0f 4b -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->PF == 0) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->PF == 0) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovl_r16_rm16)() // Opcode 0x0f 4c -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF != cpustate->OF) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->SF != cpustate->OF) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovl_r32_rm32)() // Opcode 0x0f 4c -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF != cpustate->OF) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->SF != cpustate->OF) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovge_r16_rm16)() // Opcode 0x0f 4d -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF == cpustate->OF) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if (cpustate->SF == cpustate->OF) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovge_r32_rm32)() // Opcode 0x0f 4d -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if (cpustate->SF == cpustate->OF) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if (cpustate->SF == cpustate->OF) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovle_r16_rm16)() // Opcode 0x0f 4e -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->ZF == 1) || (cpustate->SF != cpustate->OF)) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if ((cpustate->ZF == 1) || (cpustate->SF != cpustate->OF)) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovle_r32_rm32)() // Opcode 0x0f 4e -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->ZF == 1) || (cpustate->SF != cpustate->OF)) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if ((cpustate->ZF == 1) || (cpustate->SF != cpustate->OF)) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovg_r16_rm16)() // Opcode 0x0f 4f -{ - UINT16 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->ZF == 0) && (cpustate->SF == cpustate->OF)) - { - src = LOAD_RM16(modrm); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 2); - if ((cpustate->ZF == 0) && (cpustate->SF == cpustate->OF)) - { - src = READ16(ea); - STORE_REG16(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(cmovg_r32_rm32)() // Opcode 0x0f 4f -{ - UINT32 src; - UINT8 modrm = FETCH(); - - if( modrm >= 0xc0 ) - { - if ((cpustate->ZF == 0) && (cpustate->SF == cpustate->OF)) - { - src = LOAD_RM32(modrm); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } - else - { - UINT32 ea = GetEA(modrm, 0, 4); - if ((cpustate->ZF == 0) && (cpustate->SF == cpustate->OF)) - { - src = READ32(ea); - STORE_REG32(modrm, src); - } - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(movnti_m16_r16)() // Opcode 0f c3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - // since cache is not implemented - UINT32 ea = GetEA(modrm, 0, 2); - WRITE16(ea,LOAD_RM16(modrm)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(movnti_m32_r32)() // Opcode 0f c3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - // since cache is not implemented - UINT32 ea = GetEA(modrm, 0, 4); - WRITE32(ea,LOAD_RM32(modrm)); - CYCLES(1); // TODO: correct cycle count - } -} - -void I386_OPS_BASE::I386OP(cyrix_special)() // Opcode 0x0f 3a-3d -{ -/* -0f 3a BB0_RESET (set BB0 pointer = base) -0f 3b BB1_RESET (set BB1 pointer = base) -0f 3c CPU_WRITE (write special CPU memory-mapped register, [ebx] = eax) -0f 3d CPU_READ (read special CPU memory-mapped register, eax, = [ebx]) -*/ - - CYCLES(1); -} - - void I386_OPS_BASE::I386OP(cyrix_unknown)() // Opcode 0x0f 74 -{ - logerror("Unemulated 0x0f 0x74 opcode called\n"); - - CYCLES(1); -} - - void I386_OPS_BASE::PENTIUMOP(cmpxchg8b_m64)() // Opcode 0x0f c7 -{ - UINT8 modm = FETCH(); - if( modm >= 0xc0 ) { - report_invalid_modrm( "cmpxchg8b_m64", modm); - } else { - UINT32 ea = GetEA(modm, 0, 8); - UINT64 value = READ64( ea); - UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX); - UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX); - - if( value == edx_eax ) { - WRITE64( ea, ecx_ebx); - cpustate->ZF = 1; - CYCLES(CYCLES_CMPXCHG_REG_MEM_T); - } else { - REG32(EDX) = (UINT32) (value >> 32); - REG32(EAX) = (UINT32) (value >> 0); - cpustate->ZF = 0; - CYCLES(CYCLES_CMPXCHG_REG_MEM_F); - } - } -} - - void I386_OPS_BASE::PENTIUMOP(movntq_m64_r64)() // Opcode 0f e7 -{ - //MMXPROLOG(); // TODO: check if needed - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - CYCLES(1); // unsupported - } else { - // since cache is not implemented - UINT32 ea = GetEA(modrm, 0, 8); - WRITEMMX( ea, MMX((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::PENTIUMOP(maskmovq_r64_r64)() // Opcode 0f f7 -{ - int s,m,n; - UINT8 modm = FETCH(); - UINT32 ea = GetEA(7, 0, 8); // ds:di/edi/rdi register - MMXPROLOG(); - s=(modm >> 3) & 7; - m=modm & 7; - for (n=0;n <= 7;n++) - if (MMX(m).b[n] & 127) - WRITE8(ea+n, MMX(s).b[n]); -} - - void I386_OPS_BASE::SSEOP(maskmovdqu_r128_r128)() // Opcode 66 0f f7 -{ - int s,m,n; - UINT8 modm = FETCH(); - UINT32 ea = GetEA(7, 0, 16); // ds:di/edi/rdi register - s=(modm >> 3) & 7; - m=modm & 7; - for (n=0;n < 16;n++) - if (XMM(m).b[n] & 127) - WRITE8(ea+n, XMM(s).b[n]); -} - - void I386_OPS_BASE::PENTIUMOP(popcnt_r16_rm16)() // Opcode f3 0f b8 -{ - UINT16 src; - UINT8 modrm = FETCH(); - int n,count; - - if( modrm >= 0xc0 ) { - src = LOAD_RM16(modrm); - } else { - UINT32 ea = GetEA(modrm, 0, 2); - src = READ16(ea); - } - count=0; - for (n=0;n < 16;n++) { - count=count+(src & 1); - src=src >> 1; - } - STORE_REG16(modrm, count); - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::PENTIUMOP(popcnt_r32_rm32)() // Opcode f3 0f b8 -{ - UINT32 src; - UINT8 modrm = FETCH(); - int n,count; - - if( modrm >= 0xc0 ) { - src = LOAD_RM32(modrm); - } else { - UINT32 ea = GetEA(modrm, 0, 4); - src = READ32(ea); - } - count=0; - for (n=0;n < 32;n++) { - count=count+(src & 1); - src=src >> 1; - } - STORE_REG32(modrm, count); - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::PENTIUMOP(tzcnt_r16_rm16)() -{ - // for CPUs that don't support TZCNT, fall back to BSF - i386_bsf_r16_rm16(); - // TODO: actually implement TZCNT -} - - void I386_OPS_BASE::PENTIUMOP(tzcnt_r32_rm32)() -{ - // for CPUs that don't support TZCNT, fall back to BSF - i386_bsf_r32_rm32(); - // TODO: actually implement TZCNT -} - - - void I386_OPS_BASE::MMXOP(group_0f71)() // Opcode 0f 71 -{ - UINT8 modm = FETCH(); - UINT8 imm8 = FETCH(); - MMXPROLOG(); - if( modm >= 0xc0 ) { - switch ( (modm & 0x38) >> 3 ) - { - case 2: // psrlw - MMX(modm & 7).w[0]=MMX(modm & 7).w[0] >> imm8; - MMX(modm & 7).w[1]=MMX(modm & 7).w[1] >> imm8; - MMX(modm & 7).w[2]=MMX(modm & 7).w[2] >> imm8; - MMX(modm & 7).w[3]=MMX(modm & 7).w[3] >> imm8; - break; - case 4: // psraw - MMX(modm & 7).s[0]=MMX(modm & 7).s[0] >> imm8; - MMX(modm & 7).s[1]=MMX(modm & 7).s[1] >> imm8; - MMX(modm & 7).s[2]=MMX(modm & 7).s[2] >> imm8; - MMX(modm & 7).s[3]=MMX(modm & 7).s[3] >> imm8; - break; - case 6: // psllw - MMX(modm & 7).w[0]=MMX(modm & 7).w[0] << imm8; - MMX(modm & 7).w[1]=MMX(modm & 7).w[1] << imm8; - MMX(modm & 7).w[2]=MMX(modm & 7).w[2] << imm8; - MMX(modm & 7).w[3]=MMX(modm & 7).w[3] << imm8; - break; - default: - report_invalid_modrm( "mmx_group0f71", modm); - } - } -} - - void I386_OPS_BASE::I386_OPS_BASE::SSEOP(group_660f71)() // Opcode 66 0f 71 -{ - UINT8 modm = FETCH(); - UINT8 imm8 = FETCH(); - if (modm >= 0xc0) { - switch ((modm & 0x38) >> 3) - { - case 2: // psrlw - for (int n = 0; n < 8;n++) - XMM(modm & 7).w[n] = XMM(modm & 7).w[n] >> imm8; - break; - case 4: // psraw - for (int n = 0; n < 8;n++) - XMM(modm & 7).s[n] = XMM(modm & 7).s[n] >> imm8; - break; - case 6: // psllw - for (int n = 0; n < 8;n++) - XMM(modm & 7).w[n] = XMM(modm & 7).w[n] << imm8; - break; - default: - report_invalid_modrm( "mmx_group660f71", modm); - } - } -} - - void I386_OPS_BASE::MMXOP(group_0f72)() // Opcode 0f 72 -{ - UINT8 modm = FETCH(); - UINT8 imm8 = FETCH(); - MMXPROLOG(); - if( modm >= 0xc0 ) { - switch ( (modm & 0x38) >> 3 ) - { - case 2: // psrld - MMX(modm & 7).d[0]=MMX(modm & 7).d[0] >> imm8; - MMX(modm & 7).d[1]=MMX(modm & 7).d[1] >> imm8; - break; - case 4: // psrad - MMX(modm & 7).i[0]=MMX(modm & 7).i[0] >> imm8; - MMX(modm & 7).i[1]=MMX(modm & 7).i[1] >> imm8; - break; - case 6: // pslld - MMX(modm & 7).d[0]=MMX(modm & 7).d[0] << imm8; - MMX(modm & 7).d[1]=MMX(modm & 7).d[1] << imm8; - break; - default: - report_invalid_modrm( "mmx_group0f72", modm); - } - } -} - - void I386_OPS_BASE::SSEOP(group_660f72)() // Opcode 66 0f 72 -{ - UINT8 modm = FETCH(); - UINT8 imm8 = FETCH(); - if (modm >= 0xc0) { - switch ((modm & 0x38) >> 3) - { - case 2: // psrld - for (int n = 0; n < 4;n++) - XMM(modm & 7).d[n] = XMM(modm & 7).d[n] >> imm8; - break; - case 4: // psrad - for (int n = 0; n < 4;n++) - XMM(modm & 7).i[n] = XMM(modm & 7).i[n] >> imm8; - break; - case 6: // pslld - for (int n = 0; n < 4;n++) - XMM(modm & 7).d[n] = XMM(modm & 7).d[n] << imm8; - break; - default: - report_invalid_modrm( "mmx_group660f72", modm); - } - } -} - - void I386_OPS_BASE::MMXOP(group_0f73)() // Opcode 0f 73 -{ - UINT8 modm = FETCH(); - UINT8 imm8 = FETCH(); - MMXPROLOG(); - if( modm >= 0xc0 ) { - switch ( (modm & 0x38) >> 3 ) - { - case 2: // psrlq - MMX(modm & 7).q = imm8 > 63 ? 0 : MMX(modm & 7).q >> imm8; - break; - case 6: // psllq - MMX(modm & 7).q = imm8 > 63 ? 0 : MMX(modm & 7).q << imm8; - break; - default: - report_invalid_modrm( "mmx_group0f73", modm); - } - } -} - - void I386_OPS_BASE::SSEOP(group_660f73)() // Opcode 66 0f 73 -{ - UINT64 t0; - UINT8 modm = FETCH(); - UINT8 imm8 = FETCH(); - if (modm >= 0xc0) { - switch ((modm & 0x38) >> 3) - { - case 2: // psrlq - XMM(modm & 7).q[0] = imm8 > 63 ? 0 : XMM(modm & 7).q[0] >> imm8; - XMM(modm & 7).q[1] = imm8 > 63 ? 0 : XMM(modm & 7).q[1] >> imm8; - break; - case 3: // psrldq - if (imm8 >= 16) - { - XMM(modm & 7).q[0] = 0; - XMM(modm & 7).q[1] = 0; - } - else if (imm8 >= 8) - { - imm8 = (imm8 & 7) << 3; - XMM(modm & 7).q[0] = XMM(modm & 7).q[1] >> imm8; - XMM(modm & 7).q[1] = 0; - } - else if (imm8) - { - t0 = XMM(modm & 7).q[0]; - imm8 = imm8 << 3; - XMM(modm & 7).q[0] = (XMM(modm & 7).q[1] << (64 - imm8)) | (t0 >> imm8); - XMM(modm & 7).q[1] = t0 >> imm8; - } - break; - case 6: // psllq - XMM(modm & 7).q[0] = imm8 > 63 ? 0 : XMM(modm & 7).q[0] << imm8; - XMM(modm & 7).q[1] = imm8 > 63 ? 0 : XMM(modm & 7).q[1] << imm8; - break; - case 7: // pslldq - if (imm8 >= 16) - { - XMM(modm & 7).q[0] = 0; - XMM(modm & 7).q[1] = 0; - } - else if (imm8 >= 8) - { - imm8 = (imm8 & 7) << 3; - XMM(modm & 7).q[1] = XMM(modm & 7).q[0] << imm8; - XMM(modm & 7).q[0] = 0; - } - else if (imm8) - { - imm8 = imm8 << 3; - XMM(modm & 7).q[1] = (XMM(modm & 7).q[0] >> (64 - imm8)) | (XMM(modm & 7).q[1] << imm8); - XMM(modm & 7).q[0] = XMM(modm & 7).q[0] << imm8; - } - break; - default: - report_invalid_modrm( "sse_group660f73", modm); - } - } -} - - void I386_OPS_BASE::MMXOP(psrlw_r64_rm64)() // Opcode 0f d1 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] >> count; - MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] >> count; - MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] >> count; - MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] >> count; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - int count=(int)src.q; - MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] >> count; - MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] >> count; - MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] >> count; - MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psrld_r64_rm64)() // Opcode 0f d2 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] >> count; - MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] >> count; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - int count=(int)src.q; - MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] >> count; - MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psrlq_r64_rm64)() // Opcode 0f d3 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q >> count; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - int count=(int)src.q; - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddq_r64_rm64)() // Opcode 0f d4 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q+MMX(modrm & 7).q; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q+src.q; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pmullw_r64_rm64)() // Opcode 0f d5 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]) & 0xffff; - MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]) & 0xffff; - MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]) & 0xffff; - MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]) & 0xffff; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)src.s[0]) & 0xffff; - MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)src.s[1]) & 0xffff; - MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)src.s[2]) & 0xffff; - MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)src.s[3]) & 0xffff; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psubusb_r64_rm64)() // Opcode 0f d8 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] < MMX(modrm & 7).b[n] ? 0 : MMX((modrm >> 3) & 0x7).b[n]-MMX(modrm & 7).b[n]; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] < src.b[n] ? 0 : MMX((modrm >> 3) & 0x7).b[n]-src.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psubusw_r64_rm64)() // Opcode 0f d9 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] < MMX(modrm & 7).w[n] ? 0 : MMX((modrm >> 3) & 0x7).w[n]-MMX(modrm & 7).w[n]; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] < src.w[n] ? 0 : MMX((modrm >> 3) & 0x7).w[n]-src.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pand_r64_rm64)() // Opcode 0f db -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q & MMX(modrm & 7).q; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q & src.q; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddusb_r64_rm64)() // Opcode 0f dc -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] > (0xff-MMX(modrm & 7).b[n]) ? 0xff : MMX((modrm >> 3) & 0x7).b[n]+MMX(modrm & 7).b[n]; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] > (0xff-src.b[n]) ? 0xff : MMX((modrm >> 3) & 0x7).b[n]+src.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddusw_r64_rm64)() // Opcode 0f dd -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] > (0xffff-MMX(modrm & 7).w[n]) ? 0xffff : MMX((modrm >> 3) & 0x7).w[n]+MMX(modrm & 7).w[n]; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] > (0xffff-src.w[n]) ? 0xffff : MMX((modrm >> 3) & 0x7).w[n]+src.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pandn_r64_rm64)() // Opcode 0f df -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q=(~MMX((modrm >> 3) & 0x7).q) & MMX(modrm & 7).q; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - MMX((modrm >> 3) & 0x7).q=(~MMX((modrm >> 3) & 0x7).q) & src.q; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psraw_r64_rm64)() // Opcode 0f e1 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).s[0]=MMX((modrm >> 3) & 0x7).s[0] >> count; - MMX((modrm >> 3) & 0x7).s[1]=MMX((modrm >> 3) & 0x7).s[1] >> count; - MMX((modrm >> 3) & 0x7).s[2]=MMX((modrm >> 3) & 0x7).s[2] >> count; - MMX((modrm >> 3) & 0x7).s[3]=MMX((modrm >> 3) & 0x7).s[3] >> count; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - int count=(int)src.q; - MMX((modrm >> 3) & 0x7).s[0]=MMX((modrm >> 3) & 0x7).s[0] >> count; - MMX((modrm >> 3) & 0x7).s[1]=MMX((modrm >> 3) & 0x7).s[1] >> count; - MMX((modrm >> 3) & 0x7).s[2]=MMX((modrm >> 3) & 0x7).s[2] >> count; - MMX((modrm >> 3) & 0x7).s[3]=MMX((modrm >> 3) & 0x7).s[3] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psrad_r64_rm64)() // Opcode 0f e2 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).i[0]=MMX((modrm >> 3) & 0x7).i[0] >> count; - MMX((modrm >> 3) & 0x7).i[1]=MMX((modrm >> 3) & 0x7).i[1] >> count; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - int count=(int)src.q; - MMX((modrm >> 3) & 0x7).i[0]=MMX((modrm >> 3) & 0x7).i[0] >> count; - MMX((modrm >> 3) & 0x7).i[1]=MMX((modrm >> 3) & 0x7).i[1] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pmulhw_r64_rm64)() // Opcode 0f e5 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]) >> 16; - MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]) >> 16; - MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]) >> 16; - MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]) >> 16; - } else { - MMX_REG src; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, src); - MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)src.s[0]) >> 16; - MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)src.s[1]) >> 16; - MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)src.s[2]) >> 16; - MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)src.s[3]) >> 16; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psubsb_r64_rm64)() // Opcode 0f e8 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] - (INT16)MMX(modrm & 7).c[n]); - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] - (INT16)s.c[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psubsw_r64_rm64)() // Opcode 0f e9 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] - (INT32)MMX(modrm & 7).s[n]); - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] - (INT32)s.s[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(por_r64_rm64)() // Opcode 0f eb -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q | MMX(modrm & 7).q; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q | s.q; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddsb_r64_rm64)() // Opcode 0f ec -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] + (INT16)MMX(modrm & 7).c[n]); - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] + (INT16)s.c[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddsw_r64_rm64)() // Opcode 0f ed -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] + (INT32)MMX(modrm & 7).s[n]); - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] + (INT32)s.s[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pxor_r64_rm64)() // Opcode 0f ef -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q ^ MMX(modrm & 7).q; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q ^ s.q; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psllw_r64_rm64)() // Opcode 0f f1 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] << count; - MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] << count; - MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] << count; - MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] << count; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - int count=(int)s.q; - MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] << count; - MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] << count; - MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] << count; - MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] << count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pslld_r64_rm64)() // Opcode 0f f2 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] << count; - MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] << count; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - int count=(int)s.q; - MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] << count; - MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] << count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psllq_r64_rm64)() // Opcode 0f f3 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)MMX(modrm & 7).q; - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q << count; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - int count=(int)s.q; - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q << count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pmaddwd_r64_rm64)() // Opcode 0f f5 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).i[0]=(INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]+ - (INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]; - MMX((modrm >> 3) & 0x7).i[1]=(INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]+ - (INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX((modrm >> 3) & 0x7).i[0]=(INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)s.s[0]+ - (INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)s.s[1]; - MMX((modrm >> 3) & 0x7).i[1]=(INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)s.s[2]+ - (INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)s.s[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psubb_r64_rm64)() // Opcode 0f f8 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] - MMX(modrm & 7).b[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] - s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psubw_r64_rm64)() // Opcode 0f f9 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] - MMX(modrm & 7).w[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] - s.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(psubd_r64_rm64)() // Opcode 0f fa -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 2;n++) - MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] - MMX(modrm & 7).d[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 2;n++) - MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] - s.d[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddb_r64_rm64)() // Opcode 0f fc -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] + MMX(modrm & 7).b[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] + s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddw_r64_rm64)() // Opcode 0f fd -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] + MMX(modrm & 7).w[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] + s.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(paddd_r64_rm64)() // Opcode 0f fe -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 2;n++) - MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] + MMX(modrm & 7).d[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 2;n++) - MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] + s.d[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(emms)() // Opcode 0f 77 -{ - cpustate->x87_tw = 0xffff; // tag word = 0xffff - // TODO - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::I386OP(cyrix_svdc)() // Opcode 0f 78 -{ - UINT8 modrm = FETCH(); - - if( modrm < 0xc0 ) { - UINT32 ea = GetEA(modrm, 0, 10); - int index = (modrm >> 3) & 7; - int limit; - switch (index) - { - case 0: - { - index = ES; - break; - } - - case 2: - { - index = SS; - break; - } - - case 3: - { - index = DS; - break; - } - - case 4: - { - index = FS; - break; - } - - case 5: - { - index = GS; - break; - } - - default: - { - i386_trap( 6, 0, 0); - } - } - - limit = cpustate->sreg[index].limit; - - if (cpustate->sreg[index].flags & 0x8000) //G bit - { - limit >>= 12; - } - - WRITE16(ea + 0, limit); - WRITE32(ea + 2, cpustate->sreg[index].base); - WRITE16(ea + 5, cpustate->sreg[index].flags); //replace top 8 bits of base - WRITE8(ea + 7, cpustate->sreg[index].base >> 24); - WRITE16(ea + 8, cpustate->sreg[index].selector); - } else { - i386_trap( 6, 0, 0); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::I386OP(cyrix_rsdc)() // Opcode 0f 79 -{ - UINT8 modrm = FETCH(); - - if( modrm < 0xc0 ) { - UINT32 ea = GetEA(modrm, 0, 10); - int index = (modrm >> 3) & 7; - UINT16 flags; - UINT32 base; - UINT32 limit; - switch (index) - { - case 0: - { - index = ES; - break; - } - - case 2: - { - index = SS; - break; - } - - case 3: - { - index = DS; - break; - } - - case 4: - { - index = FS; - break; - } - - case 5: - { - index = GS; - break; - } - - default: - { - i386_trap( 6, 0, 0); - } - } - - base = (READ32(ea + 2) & 0x00ffffff) | (READ8(ea + 7) << 24); - flags = READ16(ea + 5); - limit = READ16(ea + 0) | ((flags & 3) << 16); - - if (flags & 0x8000) //G bit - { - limit = (limit << 12) | 0xfff; - } - - cpustate->sreg[index].selector = READ16(ea + 8); - cpustate->sreg[index].flags = flags; - cpustate->sreg[index].base = base; - cpustate->sreg[index].limit = limit; - } else { - i386_trap( 6, 0, 0); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::I386OP(cyrix_svldt)() // Opcode 0f 7a -{ - if ( PROTECTED_MODE && !V8086_MODE ) - { - UINT8 modrm = FETCH(); - - if( !(modrm & 0xf8) ) { - UINT32 ea = GetEA(modrm, 0, 10); - UINT32 limit = cpustate->ldtr.limit; - - if (cpustate->ldtr.flags & 0x8000) //G bit - { - limit >>= 12; - } - - WRITE16(ea + 0, limit); - WRITE32(ea + 2, cpustate->ldtr.base); - WRITE16(ea + 5, cpustate->ldtr.flags); //replace top 8 bits of base - WRITE8(ea + 7, cpustate->ldtr.base >> 24); - WRITE16(ea + 8, cpustate->ldtr.segment); - } else { - i386_trap( 6, 0, 0); - } - } else { - i386_trap( 6, 0, 0); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::I386OP(cyrix_rsldt)() // Opcode 0f 7b -{ - if ( PROTECTED_MODE && !V8086_MODE ) - { - if(cpustate->CPL) - FAULT(FAULT_GP,0) - - UINT8 modrm = FETCH(); - - if( !(modrm & 0xf8) ) { - UINT32 ea = GetEA(modrm, 0, 10); - UINT16 flags = READ16(ea + 5); - UINT32 base = (READ32(ea + 2) | 0x00ffffff) | (READ8(ea + 7) << 24); - UINT32 limit = READ16(ea + 0) | ((flags & 3) << 16); - I386_SREG seg; - - if (flags & 0x8000) //G bit - { - limit = (limit << 12) | 0xfff; - } - - memset(&seg, 0, sizeof(seg)); - seg.selector = READ16(ea + 8); - i386_load_protected_mode_segment(&seg,NULL); - cpustate->ldtr.limit = limit; - cpustate->ldtr.base = base; - cpustate->ldtr.flags = flags; - } else { - i386_trap( 6, 0, 0); - } - } else { - i386_trap( 6, 0, 0); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::I386OP(cyrix_svts)() // Opcode 0f 7c -{ - if ( PROTECTED_MODE ) - { - UINT8 modrm = FETCH(); - - if( !(modrm & 0xf8) ) { - UINT32 ea = GetEA(modrm, 0, 10); - UINT32 limit = cpustate->task.limit; - - if (cpustate->task.flags & 0x8000) //G bit - { - limit >>= 12; - } - - WRITE16(ea + 0, limit); - WRITE32(ea + 2, cpustate->task.base); - WRITE16(ea + 5, cpustate->task.flags); //replace top 8 bits of base - WRITE8(ea + 7, cpustate->task.base >> 24); - WRITE16(ea + 8, cpustate->task.segment); - } else { - i386_trap( 6, 0, 0); - } - } else { - i386_trap( 6, 0, 0); - } -} - - void I386_OPS_BASE::I386OP(cyrix_rsts)() // Opcode 0f 7d -{ - if ( PROTECTED_MODE ) - { - if(cpustate->CPL) - FAULT(FAULT_GP,0) - - UINT8 modrm = FETCH(); - - if( !(modrm & 0xf8) ) { - UINT32 ea = GetEA(modrm, 0, 10); - UINT16 flags = READ16(ea + 5); - UINT32 base = (READ32(ea + 2) | 0x00ffffff) | (READ8(ea + 7) << 24); - UINT32 limit = READ16(ea + 0) | ((flags & 3) << 16); - - if (flags & 0x8000) //G bit - { - limit = (limit << 12) | 0xfff; - } - cpustate->task.segment = READ16(ea + 8); - cpustate->task.limit = limit; - cpustate->task.base = base; - cpustate->task.flags = flags; - } else { - i386_trap( 6, 0, 0); - } - } else { - i386_trap( 6, 0, 0); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(movd_r64_rm32)() // Opcode 0f 6e -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).d[0]=LOAD_RM32(modrm); - } else { - UINT32 ea = GetEA(modrm, 0, 4); - MMX((modrm >> 3) & 0x7).d[0]=READ32(ea); - } - MMX((modrm >> 3) & 0x7).d[1]=0; - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(movq_r64_rm64)() // Opcode 0f 6f -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).l=MMX(modrm & 0x7).l; - } else { - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, MMX((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(movd_rm32_r64)() // Opcode 0f 7e -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - STORE_RM32(modrm, MMX((modrm >> 3) & 0x7).d[0]); - } else { - UINT32 ea = GetEA(modrm, 0, 4); - WRITE32(ea, MMX((modrm >> 3) & 0x7).d[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(movq_rm64_r64)() // Opcode 0f 7f -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX(modrm & 0x7)=MMX((modrm >> 3) & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 8); - WRITEMMX( ea, MMX((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pcmpeqb_r64_rm64)() // Opcode 0f 74 -{ - int c; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (c=0;c <= 7;c++) - MMX(d).b[c]=(MMX(d).b[c] == MMX(s).b[c]) ? 0xff : 0; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (c=0;c <= 7;c++) - MMX(d).b[c]=(MMX(d).b[c] == s.b[c]) ? 0xff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pcmpeqw_r64_rm64)() // Opcode 0f 75 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - MMX(d).w[0]=(MMX(d).w[0] == MMX(s).w[0]) ? 0xffff : 0; - MMX(d).w[1]=(MMX(d).w[1] == MMX(s).w[1]) ? 0xffff : 0; - MMX(d).w[2]=(MMX(d).w[2] == MMX(s).w[2]) ? 0xffff : 0; - MMX(d).w[3]=(MMX(d).w[3] == MMX(s).w[3]) ? 0xffff : 0; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX(d).w[0]=(MMX(d).w[0] == s.w[0]) ? 0xffff : 0; - MMX(d).w[1]=(MMX(d).w[1] == s.w[1]) ? 0xffff : 0; - MMX(d).w[2]=(MMX(d).w[2] == s.w[2]) ? 0xffff : 0; - MMX(d).w[3]=(MMX(d).w[3] == s.w[3]) ? 0xffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pcmpeqd_r64_rm64)() // Opcode 0f 76 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - MMX(d).d[0]=(MMX(d).d[0] == MMX(s).d[0]) ? 0xffffffff : 0; - MMX(d).d[1]=(MMX(d).d[1] == MMX(s).d[1]) ? 0xffffffff : 0; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX(d).d[0]=(MMX(d).d[0] == s.d[0]) ? 0xffffffff : 0; - MMX(d).d[1]=(MMX(d).d[1] == s.d[1]) ? 0xffffffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pshufw_r64_rm64_i8)() // Opcode 0f 70 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX_REG t; - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q=MMX(s).q; - MMX(d).w[0]=t.w[imm8 & 3]; - MMX(d).w[1]=t.w[(imm8 >> 2) & 3]; - MMX(d).w[2]=t.w[(imm8 >> 4) & 3]; - MMX(d).w[3]=t.w[(imm8 >> 6) & 3]; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - UINT8 imm8 = FETCH(); - READMMX( ea, s); - MMX(d).w[0]=s.w[imm8 & 3]; - MMX(d).w[1]=s.w[(imm8 >> 2) & 3]; - MMX(d).w[2]=s.w[(imm8 >> 4) & 3]; - MMX(d).w[3]=s.w[(imm8 >> 6) & 3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(punpcklbw_r128_rm128)() // Opcode 66 0f 60 -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM_REG xd,xs; - int s, d; - s = modrm & 0x7; - d = (modrm >> 3) & 0x7; - xd.l[0] = XMM(d).l[0]; - xs.l[0] = XMM(s).l[0]; - XMM(d).b[0] = xd.b[0]; - XMM(d).b[1] = xs.b[0]; - XMM(d).b[2] = xd.b[1]; - XMM(d).b[3] = xs.b[1]; - XMM(d).b[4] = xd.b[2]; - XMM(d).b[5] = xs.b[2]; - XMM(d).b[6] = xd.b[3]; - XMM(d).b[7] = xs.b[3]; - XMM(d).b[8] = xd.b[4]; - XMM(d).b[9] = xs.b[4]; - XMM(d).b[10] = xd.b[5]; - XMM(d).b[11] = xs.b[5]; - XMM(d).b[12] = xd.b[6]; - XMM(d).b[13] = xs.b[6]; - XMM(d).b[14] = xd.b[7]; - XMM(d).b[15] = xs.b[7]; - } - else { - XMM_REG xd, xs; - int d = (modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - xd.l[0] = XMM(d).l[0]; - xs.q[0] = READ64( ea); - for (int n = 0; n < 8; n++) { - XMM(d).b[n << 1] = xd.b[n]; - XMM(d).b[(n << 1) | 1] = xs.b[n]; - } - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(punpcklwd_r128_rm128)() -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM_REG xd, xs; - int s, d; - s = modrm & 0x7; - d = (modrm >> 3) & 0x7; - xd.l[0] = XMM(d).l[0]; - xs.l[0] = XMM(s).l[0]; - for (int n = 0; n < 4; n++) { - XMM(d).w[n << 1] = xd.w[n]; - XMM(d).w[(n << 1) | 1] = xs.w[n]; - } - } - else { - XMM_REG xd, xs; - int d = (modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - xd.l[0] = XMM(d).l[0]; - xs.q[0] = READ64( ea); - for (int n = 0; n < 4; n++) { - XMM(d).w[n << 1] = xd.w[n]; - XMM(d).w[(n << 1) | 1] = xs.w[n]; - } - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(punpckldq_r128_rm128)() -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM_REG xd, xs; - int s, d; - s = modrm & 0x7; - d = (modrm >> 3) & 0x7; - xd.l[0] = XMM(d).l[0]; - xs.l[0] = XMM(s).l[0]; - for (int n = 0; n < 2; n++) { - XMM(d).d[n << 1] = xd.d[n]; - XMM(d).d[(n << 1) | 1] = xs.d[n]; - } - } - else { - XMM_REG xd, xs; - int d = (modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - xd.l[0] = XMM(d).l[0]; - xs.q[0] = READ64( ea); - for (int n = 0; n < 2; n++) { - XMM(d).d[n << 1] = xd.d[n]; - XMM(d).d[(n << 1) | 1] = xs.d[n]; - } - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(punpcklqdq_r128_rm128)() -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM_REG xd, xs; - int s, d; - s = modrm & 0x7; - d = (modrm >> 3) & 0x7; - xd.l[0] = XMM(d).l[0]; - xs.l[0] = XMM(s).l[0]; - XMM(d).q[0] = xd.q[0]; - XMM(d).q[1] = xs.q[0]; - } - else { - XMM_REG xd, xs; - int d = (modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - xd.l[0] = XMM(d).l[0]; - xs.q[0] = READ64( ea); - XMM(d).q[0] = xd.q[0]; - XMM(d).q[1] = xs.q[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(punpcklbw_r64_r64m32)() // Opcode 0f 60 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 t; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t=MMX(d).d[0]; - MMX(d).b[0]=t & 0xff; - MMX(d).b[1]=MMX(s).b[0]; - MMX(d).b[2]=(t >> 8) & 0xff; - MMX(d).b[3]=MMX(s).b[1]; - MMX(d).b[4]=(t >> 16) & 0xff; - MMX(d).b[5]=MMX(s).b[2]; - MMX(d).b[6]=(t >> 24) & 0xff; - MMX(d).b[7]=MMX(s).b[3]; - } else { - UINT32 s,t; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 4); - s = READ32(ea); - t=MMX(d).d[0]; - MMX(d).b[0]=t & 0xff; - MMX(d).b[1]=s & 0xff; - MMX(d).b[2]=(t >> 8) & 0xff; - MMX(d).b[3]=(s >> 8) & 0xff; - MMX(d).b[4]=(t >> 16) & 0xff; - MMX(d).b[5]=(s >> 16) & 0xff; - MMX(d).b[6]=(t >> 24) & 0xff; - MMX(d).b[7]=(s >> 24) & 0xff; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(punpcklwd_r64_r64m32)() // Opcode 0f 61 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT16 t; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t=MMX(d).w[1]; - MMX(d).w[0]=MMX(d).w[0]; - MMX(d).w[1]=MMX(s).w[0]; - MMX(d).w[2]=t; - MMX(d).w[3]=MMX(s).w[1]; - } else { - UINT32 s; - UINT16 t; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 4); - s = READ32(ea); - t=MMX(d).w[1]; - MMX(d).w[0]=MMX(d).w[0]; - MMX(d).w[1]=s & 0xffff; - MMX(d).w[2]=t; - MMX(d).w[3]=(s >> 16) & 0xffff; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(punpckldq_r64_r64m32)() // Opcode 0f 62 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - MMX(d).d[0]=MMX(d).d[0]; - MMX(d).d[1]=MMX(s).d[0]; - } else { - UINT32 s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 4); - s = READ32(ea); - MMX(d).d[0]=MMX(d).d[0]; - MMX(d).d[1]=s; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(packsswb_r64_rm64)() // Opcode 0f 63 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - MMX(d).c[0]=SaturatedSignedWordToSignedByte(MMX(d).s[0]); - MMX(d).c[1]=SaturatedSignedWordToSignedByte(MMX(d).s[1]); - MMX(d).c[2]=SaturatedSignedWordToSignedByte(MMX(d).s[2]); - MMX(d).c[3]=SaturatedSignedWordToSignedByte(MMX(d).s[3]); - MMX(d).c[4]=SaturatedSignedWordToSignedByte(MMX(s).s[0]); - MMX(d).c[5]=SaturatedSignedWordToSignedByte(MMX(s).s[1]); - MMX(d).c[6]=SaturatedSignedWordToSignedByte(MMX(s).s[2]); - MMX(d).c[7]=SaturatedSignedWordToSignedByte(MMX(s).s[3]); - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX(d).c[0]=SaturatedSignedWordToSignedByte(MMX(d).s[0]); - MMX(d).c[1]=SaturatedSignedWordToSignedByte(MMX(d).s[1]); - MMX(d).c[2]=SaturatedSignedWordToSignedByte(MMX(d).s[2]); - MMX(d).c[3]=SaturatedSignedWordToSignedByte(MMX(d).s[3]); - MMX(d).c[4]=SaturatedSignedWordToSignedByte(s.s[0]); - MMX(d).c[5]=SaturatedSignedWordToSignedByte(s.s[1]); - MMX(d).c[6]=SaturatedSignedWordToSignedByte(s.s[2]); - MMX(d).c[7]=SaturatedSignedWordToSignedByte(s.s[3]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pcmpgtb_r64_rm64)() // Opcode 0f 64 -{ - int c; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (c=0;c <= 7;c++) - MMX(d).b[c]=(MMX(d).c[c] > MMX(s).c[c]) ? 0xff : 0; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (c=0;c <= 7;c++) - MMX(d).b[c]=(MMX(d).c[c] > s.c[c]) ? 0xff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pcmpgtw_r64_rm64)() // Opcode 0f 65 -{ - int c; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (c=0;c <= 3;c++) - MMX(d).w[c]=(MMX(d).s[c] > MMX(s).s[c]) ? 0xffff : 0; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (c=0;c <= 3;c++) - MMX(d).w[c]=(MMX(d).s[c] > s.s[c]) ? 0xffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(pcmpgtd_r64_rm64)() // Opcode 0f 66 -{ - int c; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (c=0;c <= 1;c++) - MMX(d).d[c]=(MMX(d).i[c] > MMX(s).i[c]) ? 0xffffffff : 0; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (c=0;c <= 1;c++) - MMX(d).d[c]=(MMX(d).i[c] > s.i[c]) ? 0xffffffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(packuswb_r64_rm64)() // Opcode 0f 67 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX_REG ds, sd; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - ds.q = MMX(d).q; - sd.q = MMX(s).q; - MMX(d).b[0]=SaturatedSignedWordToUnsignedByte(ds.s[0]); - MMX(d).b[1]=SaturatedSignedWordToUnsignedByte(ds.s[1]); - MMX(d).b[2]=SaturatedSignedWordToUnsignedByte(ds.s[2]); - MMX(d).b[3]=SaturatedSignedWordToUnsignedByte(ds.s[3]); - MMX(d).b[4]=SaturatedSignedWordToUnsignedByte(sd.s[0]); - MMX(d).b[5]=SaturatedSignedWordToUnsignedByte(sd.s[1]); - MMX(d).b[6]=SaturatedSignedWordToUnsignedByte(sd.s[2]); - MMX(d).b[7]=SaturatedSignedWordToUnsignedByte(sd.s[3]); - } else { - MMX_REG s,t; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - t.q = MMX(d).q; - MMX(d).b[0]=SaturatedSignedWordToUnsignedByte(t.s[0]); - MMX(d).b[1]=SaturatedSignedWordToUnsignedByte(t.s[1]); - MMX(d).b[2]=SaturatedSignedWordToUnsignedByte(t.s[2]); - MMX(d).b[3]=SaturatedSignedWordToUnsignedByte(t.s[3]); - MMX(d).b[4]=SaturatedSignedWordToUnsignedByte(s.s[0]); - MMX(d).b[5]=SaturatedSignedWordToUnsignedByte(s.s[1]); - MMX(d).b[6]=SaturatedSignedWordToUnsignedByte(s.s[2]); - MMX(d).b[7]=SaturatedSignedWordToUnsignedByte(s.s[3]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(punpckhbw_r64_rm64)() // Opcode 0f 68 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - MMX(d).b[0]=MMX(d).b[4]; - MMX(d).b[1]=MMX(s).b[4]; - MMX(d).b[2]=MMX(d).b[5]; - MMX(d).b[3]=MMX(s).b[5]; - MMX(d).b[4]=MMX(d).b[6]; - MMX(d).b[5]=MMX(s).b[6]; - MMX(d).b[6]=MMX(d).b[7]; - MMX(d).b[7]=MMX(s).b[7]; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX(d).b[0]=MMX(d).b[4]; - MMX(d).b[1]=s.b[4]; - MMX(d).b[2]=MMX(d).b[5]; - MMX(d).b[3]=s.b[5]; - MMX(d).b[4]=MMX(d).b[6]; - MMX(d).b[5]=s.b[6]; - MMX(d).b[6]=MMX(d).b[7]; - MMX(d).b[7]=s.b[7]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(punpckhwd_r64_rm64)() // Opcode 0f 69 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - MMX(d).w[0]=MMX(d).w[2]; - MMX(d).w[1]=MMX(s).w[2]; - MMX(d).w[2]=MMX(d).w[3]; - MMX(d).w[3]=MMX(s).w[3]; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX(d).w[0]=MMX(d).w[2]; - MMX(d).w[1]=s.w[2]; - MMX(d).w[2]=MMX(d).w[3]; - MMX(d).w[3]=s.w[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(punpckhdq_r64_rm64)() // Opcode 0f 6a -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - MMX(d).d[0]=MMX(d).d[1]; - MMX(d).d[1]=MMX(s).d[1]; - } else { - MMX_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX(d).d[0]=MMX(d).d[1]; - MMX(d).d[1]=s.d[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::MMXOP(packssdw_r64_rm64)() // Opcode 0f 6b -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - INT32 t1, t2, t3, t4; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t1 = MMX(d).i[0]; - t2 = MMX(d).i[1]; - t3 = MMX(s).i[0]; - t4 = MMX(s).i[1]; - MMX(d).s[0] = SaturatedSignedDwordToSignedWord(t1); - MMX(d).s[1] = SaturatedSignedDwordToSignedWord(t2); - MMX(d).s[2] = SaturatedSignedDwordToSignedWord(t3); - MMX(d).s[3] = SaturatedSignedDwordToSignedWord(t4); - } - else { - MMX_REG s; - INT32 t1, t2; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - t1 = MMX(d).i[0]; - t2 = MMX(d).i[1]; - MMX(d).s[0] = SaturatedSignedDwordToSignedWord(t1); - MMX(d).s[1] = SaturatedSignedDwordToSignedWord(t2); - MMX(d).s[2] = SaturatedSignedDwordToSignedWord(s.i[0]); - MMX(d).s[3] = SaturatedSignedDwordToSignedWord(s.i[1]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(group_0fae)() // Opcode 0f ae -{ - UINT8 modm = FETCH(); - if( modm == 0xf8 ) { - logerror("Unemulated SFENCE opcode called\n"); - CYCLES(1); // sfence instruction - } else if( modm == 0xf0 ) { - CYCLES(1); // mfence instruction - } else if( modm == 0xe8 ) { - CYCLES(1); // lfence instruction - } else if( modm < 0xc0 ) { - UINT32 ea; - switch ( (modm & 0x38) >> 3 ) - { - case 2: // ldmxcsr m32 - ea = GetEA(modm, 0, 4); - cpustate->mxcsr = READ32(ea); - break; - case 3: // stmxcsr m32 - ea = GetEA(modm, 0, 4); - WRITE32(ea, cpustate->mxcsr); - break; - case 7: // clflush m8 - GetNonTranslatedEA(modm, NULL); - break; - default: - report_invalid_modrm( "sse_group_0fae", modm); - } - } else { - report_invalid_modrm( "sse_group_0fae", modm); - } -} - - void I386_OPS_BASE::SSEOP(cvttps2dq_r128_rm128)() // Opcode f3 0f 5b -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).i[0]=(INT32)XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).i[1]=(INT32)XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).i[2]=(INT32)XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).i[3]=(INT32)XMM(modrm & 0x7).f[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).i[0]=(INT32)src.f[0]; - XMM((modrm >> 3) & 0x7).i[1]=(INT32)src.f[1]; - XMM((modrm >> 3) & 0x7).i[2]=(INT32)src.f[2]; - XMM((modrm >> 3) & 0x7).i[3]=(INT32)src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtss2sd_r128_r128m32)() // Opcode f3 0f 5a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM(modrm & 0x7).f[0]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 4); - s.d[0] = READ32(ea); - XMM((modrm >> 3) & 0x7).f64[0] = s.f[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvttss2si_r32_r128m32)() // Opcode f3 0f 2c -{ - INT32 src; - UINT8 modrm = FETCH(); // get mordm byte - if( modrm >= 0xc0 ) { // if bits 7-6 are 11 the source is a xmm register (low doubleword) - src = (INT32)XMM(modrm & 0x7).f[0^NATIVE_ENDIAN_VALUE_LE_BE(0,1)]; - } else { // otherwise is a memory address - XMM_REG t; - UINT32 ea = GetEA(modrm, 0, 4); - t.d[0] = READ32(ea); - src = (INT32)t.f[0]; - } - STORE_REG32(modrm, (UINT32)src); - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtss2si_r32_r128m32)() // Opcode f3 0f 2d -{ - INT32 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = (INT32)XMM(modrm & 0x7).f[0]; - } else { - XMM_REG t; - UINT32 ea = GetEA(modrm, 0, 4); - t.d[0] = READ32(ea); - src = (INT32)t.f[0]; - } - STORE_REG32(modrm, (UINT32)src); - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtsi2ss_r128_rm32)() // Opcode f3 0f 2a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = (INT32)LOAD_RM32(modrm); - } else { - UINT32 ea = GetEA(modrm, 0, 4); - XMM((modrm >> 3) & 0x7).f[0] = (INT32)READ32(ea); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtpi2ps_r128_rm64)() // Opcode 0f 2a -{ - UINT8 modrm = FETCH(); - MMXPROLOG(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = (float)MMX(modrm & 0x7).i[0]; - XMM((modrm >> 3) & 0x7).f[1] = (float)MMX(modrm & 0x7).i[1]; - } else { - MMX_REG r; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, r); - XMM((modrm >> 3) & 0x7).f[0] = (float)r.i[0]; - XMM((modrm >> 3) & 0x7).f[1] = (float)r.i[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvttps2pi_r64_r128m64)() // Opcode 0f 2c -{ - UINT8 modrm = FETCH(); - MMXPROLOG(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f[0]; - MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f[1]; - } else { - XMM_REG r; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, r); - XMM((modrm >> 3) & 0x7).i[0] = r.f[0]; - XMM((modrm >> 3) & 0x7).i[1] = r.f[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtps2pi_r64_r128m64)() // Opcode 0f 2d -{ - UINT8 modrm = FETCH(); - MMXPROLOG(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f[0]; - MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f[1]; - } else { - XMM_REG r; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, r); - XMM((modrm >> 3) & 0x7).i[0] = r.f[0]; - XMM((modrm >> 3) & 0x7).i[1] = r.f[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtps2pd_r128_r128m64)() // Opcode 0f 5a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = (double)XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).f64[1] = (double)XMM(modrm & 0x7).f[1]; - } else { - MMX_REG r; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, r); - XMM((modrm >> 3) & 0x7).f64[0] = (double)r.f[0]; - XMM((modrm >> 3) & 0x7).f64[1] = (double)r.f[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtdq2ps_r128_rm128)() // Opcode 0f 5b -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = (float)XMM(modrm & 0x7).i[0]; - XMM((modrm >> 3) & 0x7).f[1] = (float)XMM(modrm & 0x7).i[1]; - XMM((modrm >> 3) & 0x7).f[2] = (float)XMM(modrm & 0x7).i[2]; - XMM((modrm >> 3) & 0x7).f[3] = (float)XMM(modrm & 0x7).i[3]; - } else { - XMM_REG r; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, r); - XMM((modrm >> 3) & 0x7).f[0] = (float)r.i[0]; - XMM((modrm >> 3) & 0x7).f[1] = (float)r.i[1]; - XMM((modrm >> 3) & 0x7).f[2] = (float)r.i[2]; - XMM((modrm >> 3) & 0x7).f[3] = (float)r.i[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtdq2pd_r128_r128m64)() // Opcode f3 0f e6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = (double)XMM(modrm & 0x7).i[0]; - XMM((modrm >> 3) & 0x7).f64[1] = (double)XMM(modrm & 0x7).i[1]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - XMM((modrm >> 3) & 0x7).f64[0] = (double)s.i[0]; - XMM((modrm >> 3) & 0x7).f64[1] = (double)s.i[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movss_r128_rm128)() // Opcode f3 0f 10 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[0]; - } else { - UINT32 ea = GetEA(modrm, 0, 4); - XMM((modrm >> 3) & 0x7).d[0] = READ32(ea); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movss_rm128_r128)() // Opcode f3 0f 11 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0]; - } else { - UINT32 ea = GetEA(modrm, 0, 4); - WRITE32(ea, XMM((modrm >> 3) & 0x7).d[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movsldup_r128_rm128)() // Opcode f3 0f 12 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[0]; - XMM((modrm >> 3) & 0x7).d[1] = XMM(modrm & 0x7).d[0]; - XMM((modrm >> 3) & 0x7).d[2] = XMM(modrm & 0x7).d[2]; - XMM((modrm >> 3) & 0x7).d[3] = XMM(modrm & 0x7).d[2]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).d[0] = src.d[0]; - XMM((modrm >> 3) & 0x7).d[1] = src.d[0]; - XMM((modrm >> 3) & 0x7).d[2] = src.d[2]; - XMM((modrm >> 3) & 0x7).d[3] = src.d[2]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movshdup_r128_rm128)() // Opcode f3 0f 16 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[1]; - XMM((modrm >> 3) & 0x7).d[1] = XMM(modrm & 0x7).d[1]; - XMM((modrm >> 3) & 0x7).d[2] = XMM(modrm & 0x7).d[3]; - XMM((modrm >> 3) & 0x7).d[3] = XMM(modrm & 0x7).d[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).d[0] = src.d[1]; - XMM((modrm >> 3) & 0x7).d[1] = src.d[1]; - XMM((modrm >> 3) & 0x7).d[2] = src.d[3]; - XMM((modrm >> 3) & 0x7).d[3] = src.d[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movaps_r128_rm128)() // Opcode 0f 28 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movaps_rm128_r128)() // Opcode 0f 29 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movups_r128_rm128)() // Opcode 0f 10 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movupd_r128_rm128)() // Opcode 66 0f 10 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movups_rm128_r128)() // Opcode 0f 11 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movupd_rm128_r128)() // Opcode 66 0f 11 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movlps_r128_m64)() // Opcode 0f 12 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // MOVHLPS opcode - XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[1]; - CYCLES(1); // TODO: correct cycle count - } else { - // MOVLPS opcode - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_LO64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movlpd_r128_m64)() // Opcode 66 0f 12 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - CYCLES(1); // TODO: correct cycle count - } else { - // MOVLPS opcode - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_LO64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movlps_m64_r128)() // Opcode 0f 13 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - UINT32 ea = GetEA(modrm, 0, 8); - WRITEXMM_LO64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movlpd_m64_r128)() // Opcode 66 0f 13 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - UINT32 ea = GetEA(modrm, 0, 8); - WRITEXMM_LO64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movhps_r128_m64)() // Opcode 0f 16 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // MOVLHPS opcode - XMM((modrm >> 3) & 0x7).q[1] = XMM(modrm & 0x7).q[0]; - CYCLES(1); // TODO: correct cycle count - } else { - // MOVHPS opcode - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_HI64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movhpd_r128_m64)() // Opcode 66 0f 16 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - // MOVHPS opcode - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_HI64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movhps_m64_r128)() // Opcode 0f 17 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - UINT32 ea = GetEA(modrm, 0, 8); - WRITEXMM_HI64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movhpd_m64_r128)() // Opcode 66 0f 17 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - UINT32 ea = GetEA(modrm, 0, 8); - WRITEXMM_HI64( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movntps_m128_r128)() // Opcode 0f 2b -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - // since cache is not implemented - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movmskps_r16_r128)() // Opcode 0f 50 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int b; - b=(XMM(modrm & 0x7).d[0] >> 31) & 1; - b=b | ((XMM(modrm & 0x7).d[1] >> 30) & 2); - b=b | ((XMM(modrm & 0x7).d[2] >> 29) & 4); - b=b | ((XMM(modrm & 0x7).d[3] >> 28) & 8); - STORE_REG16(modrm, b); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movmskps_r32_r128)() // Opcode 0f 50 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int b; - b=(XMM(modrm & 0x7).d[0] >> 31) & 1; - b=b | ((XMM(modrm & 0x7).d[1] >> 30) & 2); - b=b | ((XMM(modrm & 0x7).d[2] >> 29) & 4); - b=b | ((XMM(modrm & 0x7).d[3] >> 28) & 8); - STORE_REG32(modrm, b); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movmskpd_r32_r128)() // Opcode 66 0f 50 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int b; - b=(XMM(modrm & 0x7).q[0] >> 63) & 1; - b=b | ((XMM(modrm & 0x7).q[1] >> 62) & 2); - STORE_REG32(modrm, b); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movq2dq_r128_r64)() // Opcode f3 0f d6 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = MMX(modrm & 7).q; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movdqu_r128_rm128)() // Opcode f3 0f 6f -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM(modrm & 0x7).q[1]; - } else { - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movdqu_rm128_r128)() // Opcode f3 0f 7f -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0]; - XMM(modrm & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1]; - } else { - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movd_m128_rm32)() // Opcode 66 0f 6e -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM((modrm >> 3) & 0x7).d[0] = LOAD_RM32(modrm); - } - else { - UINT32 ea = GetEA(modrm, 0, 4); - XMM((modrm >> 3) & 0x7).d[0] = READ32(ea); - } - XMM((modrm >> 3) & 0x7).d[1] = 0; - XMM((modrm >> 3) & 0x7).q[1] = 0; - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movdqa_m128_rm128)() // Opcode 66 0f 6f -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM(modrm & 0x7).q[1]; - } - else { - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movq_r128_r128m64)() // Opcode f3 0f 7e -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } else { - UINT32 ea = GetEA(modrm, 0, 8); - XMM((modrm >> 3) & 0x7).q[0] = READ64( ea); - XMM((modrm >> 3) & 0x7).q[1] = 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movd_rm32_r128)() // Opcode 66 0f 7e -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - STORE_RM32(modrm, XMM((modrm >> 3) & 0x7).d[0]); - } - else { - UINT32 ea = GetEA(modrm, 0, 4); - WRITE32(ea, XMM((modrm >> 3) & 0x7).d[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movdqa_rm128_r128)() // Opcode 66 0f 7f -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM(modrm & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0]; - XMM(modrm & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1]; - } - else { - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmovmskb_r16_r64)() // Opcode 0f d7 -{ - //MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int b; - b=(MMX(modrm & 0x7).b[0] >> 7) & 1; - b=b | ((MMX(modrm & 0x7).b[1] >> 6) & 2); - b=b | ((MMX(modrm & 0x7).b[2] >> 5) & 4); - b=b | ((MMX(modrm & 0x7).b[3] >> 4) & 8); - b=b | ((MMX(modrm & 0x7).b[4] >> 3) & 16); - b=b | ((MMX(modrm & 0x7).b[5] >> 2) & 32); - b=b | ((MMX(modrm & 0x7).b[6] >> 1) & 64); - b=b | ((MMX(modrm & 0x7).b[7] >> 0) & 128); - STORE_REG16(modrm, b); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmovmskb_r32_r64)() // Opcode 0f d7 -{ - //MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int b; - b=(MMX(modrm & 0x7).b[0] >> 7) & 1; - b=b | ((MMX(modrm & 0x7).b[1] >> 6) & 2); - b=b | ((MMX(modrm & 0x7).b[2] >> 5) & 4); - b=b | ((MMX(modrm & 0x7).b[3] >> 4) & 8); - b=b | ((MMX(modrm & 0x7).b[4] >> 3) & 16); - b=b | ((MMX(modrm & 0x7).b[5] >> 2) & 32); - b=b | ((MMX(modrm & 0x7).b[6] >> 1) & 64); - b=b | ((MMX(modrm & 0x7).b[7] >> 0) & 128); - STORE_REG32(modrm, b); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmovmskb_r32_r128)() // Opcode 66 0f d7 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT32 b; - b=(XMM(modrm & 0x7).b[0] >> 7) & 1; - b=b | ((XMM(modrm & 0x7).b[1] >> 6) & 2); - b=b | ((XMM(modrm & 0x7).b[2] >> 5) & 4); - b=b | ((XMM(modrm & 0x7).b[3] >> 4) & 8); - b=b | ((XMM(modrm & 0x7).b[4] >> 3) & 16); - b=b | ((XMM(modrm & 0x7).b[5] >> 2) & 32); - b=b | ((XMM(modrm & 0x7).b[6] >> 1) & 64); - b=b | ((XMM(modrm & 0x7).b[7] >> 0) & 128); - b=b | ((XMM(modrm & 0x7).b[8] << 1) & 256); - b=b | ((XMM(modrm & 0x7).b[9] << 2) & 512); - b=b | ((XMM(modrm & 0x7).b[10] << 3) & 1024); - b=b | ((XMM(modrm & 0x7).b[11] << 4) & 2048); - b=b | ((XMM(modrm & 0x7).b[12] << 5) & 4096); - b=b | ((XMM(modrm & 0x7).b[13] << 6) & 8192); - b=b | ((XMM(modrm & 0x7).b[14] << 7) & 16384); - b=b | ((XMM(modrm & 0x7).b[15] << 8) & 32768); - STORE_REG32(modrm, b); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(xorps)() // Opcode 0f 57 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0] ^ XMM(modrm & 0x7).d[0]; - XMM((modrm >> 3) & 0x7).d[1] = XMM((modrm >> 3) & 0x7).d[1] ^ XMM(modrm & 0x7).d[1]; - XMM((modrm >> 3) & 0x7).d[2] = XMM((modrm >> 3) & 0x7).d[2] ^ XMM(modrm & 0x7).d[2]; - XMM((modrm >> 3) & 0x7).d[3] = XMM((modrm >> 3) & 0x7).d[3] ^ XMM(modrm & 0x7).d[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0] ^ src.d[0]; - XMM((modrm >> 3) & 0x7).d[1] = XMM((modrm >> 3) & 0x7).d[1] ^ src.d[1]; - XMM((modrm >> 3) & 0x7).d[2] = XMM((modrm >> 3) & 0x7).d[2] ^ src.d[2]; - XMM((modrm >> 3) & 0x7).d[3] = XMM((modrm >> 3) & 0x7).d[3] ^ src.d[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(xorpd_r128_rm128)() // Opcode 66 0f 57 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] ^ XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] ^ XMM(modrm & 0x7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] ^ src.q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] ^ src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(addps)() // Opcode 0f 58 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + XMM(modrm & 0x7).f[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + src.f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + src.f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + src.f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(sqrtps_r128_rm128)() // Opcode 0f 51 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = sqrt(XMM(modrm & 0x7).f[0]); - XMM((modrm >> 3) & 0x7).f[1] = sqrt(XMM(modrm & 0x7).f[1]); - XMM((modrm >> 3) & 0x7).f[2] = sqrt(XMM(modrm & 0x7).f[2]); - XMM((modrm >> 3) & 0x7).f[3] = sqrt(XMM(modrm & 0x7).f[3]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = sqrt(src.f[0]); - XMM((modrm >> 3) & 0x7).f[1] = sqrt(src.f[1]); - XMM((modrm >> 3) & 0x7).f[2] = sqrt(src.f[2]); - XMM((modrm >> 3) & 0x7).f[3] = sqrt(src.f[3]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(rsqrtps_r128_rm128)() // Opcode 0f 52 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(XMM(modrm & 0x7).f[0]); - XMM((modrm >> 3) & 0x7).f[1] = 1.0 / sqrt(XMM(modrm & 0x7).f[1]); - XMM((modrm >> 3) & 0x7).f[2] = 1.0 / sqrt(XMM(modrm & 0x7).f[2]); - XMM((modrm >> 3) & 0x7).f[3] = 1.0 / sqrt(XMM(modrm & 0x7).f[3]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(src.f[0]); - XMM((modrm >> 3) & 0x7).f[1] = 1.0 / sqrt(src.f[1]); - XMM((modrm >> 3) & 0x7).f[2] = 1.0 / sqrt(src.f[2]); - XMM((modrm >> 3) & 0x7).f[3] = 1.0 / sqrt(src.f[3]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(rcpps_r128_rm128)() // Opcode 0f 53 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = 1.0f / XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).f[1] = 1.0f / XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).f[2] = 1.0f / XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).f[3] = 1.0f / XMM(modrm & 0x7).f[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = 1.0f / src.f[0]; - XMM((modrm >> 3) & 0x7).f[1] = 1.0f / src.f[1]; - XMM((modrm >> 3) & 0x7).f[2] = 1.0f / src.f[2]; - XMM((modrm >> 3) & 0x7).f[3] = 1.0f / src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(andps_r128_rm128)() // Opcode 0f 54 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & XMM(modrm & 0x7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & src.q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(andpd_r128_rm128)() // Opcode 66 0f 54 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & XMM(modrm & 0x7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & src.q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(andnps_r128_rm128)() // Opcode 0f 55 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & XMM(modrm & 0x7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & src.q[0]; - XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(andnpd_r128_rm128)() // Opcode 66 0f 55 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & XMM(modrm & 0x7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & src.q[0]; - XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(orps_r128_rm128)() // Opcode 0f 56 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | XMM(modrm & 0x7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | src.q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(orpd_r128_rm128)() // Opcode 66 0f 56 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | XMM(modrm & 0x7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | src.q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(mulps)() // Opcode 0f 59 ???? -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * XMM(modrm & 0x7).f[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * src.f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * src.f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * src.f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(subps)() // Opcode 0f 5c -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] - XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] - XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] - XMM(modrm & 0x7).f[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - src.f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] - src.f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] - src.f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] - src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - -INLINE float sse_min_single(float src1, float src2) -{ - /*if ((src1 == 0) && (src2 == 0)) - return src2; - if (src1 = SNaN) - return src2; - if (src2 = SNaN) - return src2;*/ - if (src1 < src2) - return src1; - return src2; -} - -INLINE double sse_min_double(double src1, double src2) -{ - /*if ((src1 == 0) && (src2 == 0)) - return src2; - if (src1 = SNaN) - return src2; - if (src2 = SNaN) - return src2;*/ - if (src1 < src2) - return src1; - return src2; -} - - void I386_OPS_BASE::SSEOP(minps)() // Opcode 0f 5d -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = sse_min_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); - XMM((modrm >> 3) & 0x7).f[1] = sse_min_single(XMM((modrm >> 3) & 0x7).f[1], XMM(modrm & 0x7).f[1]); - XMM((modrm >> 3) & 0x7).f[2] = sse_min_single(XMM((modrm >> 3) & 0x7).f[2], XMM(modrm & 0x7).f[2]); - XMM((modrm >> 3) & 0x7).f[3] = sse_min_single(XMM((modrm >> 3) & 0x7).f[3], XMM(modrm & 0x7).f[3]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = sse_min_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); - XMM((modrm >> 3) & 0x7).f[1] = sse_min_single(XMM((modrm >> 3) & 0x7).f[1], src.f[1]); - XMM((modrm >> 3) & 0x7).f[2] = sse_min_single(XMM((modrm >> 3) & 0x7).f[2], src.f[2]); - XMM((modrm >> 3) & 0x7).f[3] = sse_min_single(XMM((modrm >> 3) & 0x7).f[3], src.f[3]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(divps)() // Opcode 0f 5e -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] / XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] / XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] / XMM(modrm & 0x7).f[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / src.f[0]; - XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] / src.f[1]; - XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] / src.f[2]; - XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] / src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - -INLINE float sse_max_single(float src1, float src2) -{ - /*if ((src1 == 0) && (src2 == 0)) - return src2; - if (src1 = SNaN) - return src2; - if (src2 = SNaN) - return src2;*/ - if (src1 > src2) - return src1; - return src2; -} - -INLINE double sse_max_double(double src1, double src2) -{ - /*if ((src1 == 0) && (src2 == 0)) - return src2; - if (src1 = SNaN) - return src2; - if (src2 = SNaN) - return src2;*/ - if (src1 > src2) - return src1; - return src2; -} - - void I386_OPS_BASE::SSEOP(maxps)() // Opcode 0f 5f -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); - XMM((modrm >> 3) & 0x7).f[1] = sse_max_single(XMM((modrm >> 3) & 0x7).f[1], XMM(modrm & 0x7).f[1]); - XMM((modrm >> 3) & 0x7).f[2] = sse_max_single(XMM((modrm >> 3) & 0x7).f[2], XMM(modrm & 0x7).f[2]); - XMM((modrm >> 3) & 0x7).f[3] = sse_max_single(XMM((modrm >> 3) & 0x7).f[3], XMM(modrm & 0x7).f[3]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); - XMM((modrm >> 3) & 0x7).f[1] = sse_max_single(XMM((modrm >> 3) & 0x7).f[1], src.f[1]); - XMM((modrm >> 3) & 0x7).f[2] = sse_max_single(XMM((modrm >> 3) & 0x7).f[2], src.f[2]); - XMM((modrm >> 3) & 0x7).f[3] = sse_max_single(XMM((modrm >> 3) & 0x7).f[3], src.f[3]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(maxss_r128_r128m32)() // Opcode f3 0f 5f -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 4); - src.d[0]=READ32(ea); - XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(addss)() // Opcode f3 0f 58 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + XMM(modrm & 0x7).f[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + src.f[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(subss)() // Opcode f3 0f 5c -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - XMM(modrm & 0x7).f[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - src.f[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(mulss)() // Opcode f3 0f 5e -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * XMM(modrm & 0x7).f[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * src.f[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(divss)() // Opcode 0f 59 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / XMM(modrm & 0x7).f[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / src.f[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(rcpss_r128_r128m32)() // Opcode f3 0f 53 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = 1.0f / XMM(modrm & 0x7).f[0]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 4); - s.d[0]=READ32(ea); - XMM((modrm >> 3) & 0x7).f[0] = 1.0f / s.f[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(sqrtss_r128_r128m32)() // Opcode f3 0f 51 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = sqrt(XMM(modrm & 0x7).f[0]); - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 4); - s.d[0]=READ32(ea); - XMM((modrm >> 3) & 0x7).f[0] = sqrt(s.f[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(rsqrtss_r128_r128m32)() // Opcode f3 0f 52 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(XMM(modrm & 0x7).f[0]); - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 4); - s.d[0]=READ32(ea); - XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(s.f[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(minss_r128_r128m32)() // Opcode f3 0f 5d -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] < XMM(modrm & 0x7).f[0] ? XMM((modrm >> 3) & 0x7).f[0] : XMM(modrm & 0x7).f[0]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 4); - s.d[0] = READ32(ea); - XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] < s.f[0] ? XMM((modrm >> 3) & 0x7).f[0] : s.f[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(comiss_r128_r128m32)() // Opcode 0f 2f -{ - float32 a,b; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - a = XMM((modrm >> 3) & 0x7).d[0]; - b = XMM(modrm & 0x7).d[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - a = XMM((modrm >> 3) & 0x7).d[0]; - b = src.d[0]; - } - cpustate->OF=0; - cpustate->SF=0; - cpustate->AF=0; - if (float32_is_nan(a) || float32_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - if (float32_eq(a, b)) - cpustate->ZF = 1; - if (float32_lt(a, b)) - cpustate->CF = 1; - } - // should generate exception when at least one of the operands is either QNaN or SNaN - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(comisd_r128_r128m64)() // Opcode 66 0f 2f -{ - float64 a,b; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - a = XMM((modrm >> 3) & 0x7).q[0]; - b = XMM(modrm & 0x7).q[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - a = XMM((modrm >> 3) & 0x7).q[0]; - b = src.q[0]; - } - cpustate->OF=0; - cpustate->SF=0; - cpustate->AF=0; - if (float64_is_nan(a) || float64_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - if (float64_eq(a, b)) - cpustate->ZF = 1; - if (float64_lt(a, b)) - cpustate->CF = 1; - } - // should generate exception when at least one of the operands is either QNaN or SNaN - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(ucomiss_r128_r128m32)() // Opcode 0f 2e -{ - float32 a,b; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - a = XMM((modrm >> 3) & 0x7).d[0]; - b = XMM(modrm & 0x7).d[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - a = XMM((modrm >> 3) & 0x7).d[0]; - b = src.d[0]; - } - cpustate->OF=0; - cpustate->SF=0; - cpustate->AF=0; - if (float32_is_nan(a) || float32_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - if (float32_eq(a, b)) - cpustate->ZF = 1; - if (float32_lt(a, b)) - cpustate->CF = 1; - } - // should generate exception when at least one of the operands is SNaN - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(ucomisd_r128_r128m64)() // Opcode 66 0f 2e -{ - float64 a,b; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - a = XMM((modrm >> 3) & 0x7).q[0]; - b = XMM(modrm & 0x7).q[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - a = XMM((modrm >> 3) & 0x7).q[0]; - b = src.q[0]; - } - cpustate->OF=0; - cpustate->SF=0; - cpustate->AF=0; - if (float64_is_nan(a) || float64_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - if (float64_eq(a, b)) - cpustate->ZF = 1; - if (float64_lt(a, b)) - cpustate->CF = 1; - } - // should generate exception when at least one of the operands is SNaN - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(shufps)() // Opcode 0f c6 -{ - UINT8 modrm = FETCH(); - UINT8 sel = FETCH(); - int m1,m2,m3,m4; - int s,d; - m1=sel & 3; - m2=(sel >> 2) & 3; - m3=(sel >> 4) & 3; - m4=(sel >> 6) & 3; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - if( modrm >= 0xc0 ) { - UINT32 t1,t2,t3,t4; - t1=XMM(d).d[m1]; - t2=XMM(d).d[m2]; - t3=XMM(s).d[m3]; - t4=XMM(s).d[m4]; - XMM(d).d[0]=t1; - XMM(d).d[1]=t2; - XMM(d).d[2]=t3; - XMM(d).d[3]=t4; - } else { - UINT32 t1,t2; - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - t1=XMM(d).d[m1]; - t2=XMM(d).d[m2]; - XMM(d).d[0]=t1; - XMM(d).d[1]=t2; - XMM(d).d[2]=src.d[m3]; - XMM(d).d[3]=src.d[m4]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(shufpd_r128_rm128_i8)() // Opcode 66 0f c6 -{ - UINT8 modrm = FETCH(); - UINT8 sel = FETCH(); - int m1,m2; - int s,d; - m1=sel & 1; - m2=(sel >> 1) & 1; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - if( modrm >= 0xc0 ) { - UINT64 t1,t2; - t1=XMM(d).q[m1]; - t2=XMM(s).q[m2]; - XMM(d).q[0]=t1; - XMM(d).q[1]=t2; - } else { - UINT64 t1; - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - t1=XMM(d).q[m1]; - XMM(d).q[0]=t1; - XMM(d).q[1]=src.q[m2]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(unpcklps_r128_rm128)() // Opcode 0f 14 -{ - UINT8 modrm = FETCH(); - int s,d; - UINT32 t1, t2, t3, t4; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - if( modrm >= 0xc0 ) { - t1 = XMM(s).d[1]; - t2 = XMM(d).d[1]; - t3 = XMM(s).d[0]; - t4 = XMM(d).d[0]; - XMM(d).d[3]=t1; - XMM(d).d[2]=t2; - XMM(d).d[1]=t3; - XMM(d).d[0]=t4; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - t2 = XMM(d).d[1]; - XMM(d).d[3]=src.d[1]; - XMM(d).d[2]=t2; - XMM(d).d[1]=src.d[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(unpcklpd_r128_rm128)() // Opcode 66 0f 14 -{ - UINT8 modrm = FETCH(); - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - if( modrm >= 0xc0 ) { - XMM(d).q[1]=XMM(s).q[0]; - XMM(d).q[0]=XMM(d).q[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM(d).q[1]=src.q[0]; - XMM(d).q[0]=XMM(d).q[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(unpckhps_r128_rm128)() // Opcode 0f 15 -{ - UINT8 modrm = FETCH(); - int s,d; - UINT32 t1, t2, t3, t4; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - if( modrm >= 0xc0 ) { - t1 = XMM(d).d[2]; - t2 = XMM(s).d[2]; - t3 = XMM(d).d[3]; - t4 = XMM(s).d[3]; - XMM(d).d[0]=t1; - XMM(d).d[1]=t2; - XMM(d).d[2]=t3; - XMM(d).d[3]=t4; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - t1 = XMM(d).d[2]; - t2 = XMM(d).d[3]; - XMM(d).d[0]=t1; - XMM(d).d[1]=src.d[2]; - XMM(d).d[2]=t2; - XMM(d).d[3]=src.d[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(unpckhpd_r128_rm128)() // Opcode 66 0f 15 -{ - UINT8 modrm = FETCH(); - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - if( modrm >= 0xc0 ) { - XMM(d).q[0]=XMM(d).q[1]; - XMM(d).q[1]=XMM(s).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM(d).q[0]=XMM(d).q[1]; - XMM(d).q[1]=src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - -INLINE bool sse_issingleordered(float op1, float op2) -{ - // TODO: true when at least one of the two source operands being compared is a NaN - return (op1 != op1) || (op1 != op2); -} - -INLINE bool sse_issingleunordered(float op1, float op2) -{ - // TODO: true when neither source operand is a NaN - return !((op1 != op1) || (op1 != op2)); -} - -INLINE bool sse_isdoubleordered(double op1, double op2) -{ - // TODO: true when at least one of the two source operands being compared is a NaN - return (op1 != op1) || (op1 != op2); -} - -INLINE bool sse_isdoubleunordered(double op1, double op2) -{ - // TODO: true when neither source operand is a NaN - return !((op1 != op1) || (op1 != op2)); -} - - void I386_OPS_BASE::SSEOP(predicate_compare_single)(UINT8 imm8, XMM_REG d, XMM_REG s) -{ - switch (imm8 & 7) - { - case 0: - d.d[0]=d.f[0] == s.f[0] ? 0xffffffff : 0; - d.d[1]=d.f[1] == s.f[1] ? 0xffffffff : 0; - d.d[2]=d.f[2] == s.f[2] ? 0xffffffff : 0; - d.d[3]=d.f[3] == s.f[3] ? 0xffffffff : 0; - break; - case 1: - d.d[0]=d.f[0] < s.f[0] ? 0xffffffff : 0; - d.d[1]=d.f[1] < s.f[1] ? 0xffffffff : 0; - d.d[2]=d.f[2] < s.f[2] ? 0xffffffff : 0; - d.d[3]=d.f[3] < s.f[3] ? 0xffffffff : 0; - break; - case 2: - d.d[0]=d.f[0] <= s.f[0] ? 0xffffffff : 0; - d.d[1]=d.f[1] <= s.f[1] ? 0xffffffff : 0; - d.d[2]=d.f[2] <= s.f[2] ? 0xffffffff : 0; - d.d[3]=d.f[3] <= s.f[3] ? 0xffffffff : 0; - break; - case 3: - d.d[0]=sse_issingleunordered(d.f[0], s.f[0]) ? 0xffffffff : 0; - d.d[1]=sse_issingleunordered(d.f[1], s.f[1]) ? 0xffffffff : 0; - d.d[2]=sse_issingleunordered(d.f[2], s.f[2]) ? 0xffffffff : 0; - d.d[3]=sse_issingleunordered(d.f[3], s.f[3]) ? 0xffffffff : 0; - break; - case 4: - d.d[0]=d.f[0] != s.f[0] ? 0xffffffff : 0; - d.d[1]=d.f[1] != s.f[1] ? 0xffffffff : 0; - d.d[2]=d.f[2] != s.f[2] ? 0xffffffff : 0; - d.d[3]=d.f[3] != s.f[3] ? 0xffffffff : 0; - break; - case 5: - d.d[0]=d.f[0] < s.f[0] ? 0 : 0xffffffff; - d.d[1]=d.f[1] < s.f[1] ? 0 : 0xffffffff; - d.d[2]=d.f[2] < s.f[2] ? 0 : 0xffffffff; - d.d[3]=d.f[3] < s.f[3] ? 0 : 0xffffffff; - break; - case 6: - d.d[0]=d.f[0] <= s.f[0] ? 0 : 0xffffffff; - d.d[1]=d.f[1] <= s.f[1] ? 0 : 0xffffffff; - d.d[2]=d.f[2] <= s.f[2] ? 0 : 0xffffffff; - d.d[3]=d.f[3] <= s.f[3] ? 0 : 0xffffffff; - break; - case 7: - d.d[0]=sse_issingleordered(d.f[0], s.f[0]) ? 0xffffffff : 0; - d.d[1]=sse_issingleordered(d.f[1], s.f[1]) ? 0xffffffff : 0; - d.d[2]=sse_issingleordered(d.f[2], s.f[2]) ? 0xffffffff : 0; - d.d[3]=sse_issingleordered(d.f[3], s.f[3]) ? 0xffffffff : 0; - break; - } -} - - void I386_OPS_BASE::SSEOP(predicate_compare_double)(UINT8 imm8, XMM_REG d, XMM_REG s) -{ - switch (imm8 & 7) - { - case 0: - d.q[0]=d.f64[0] == s.f64[0] ? U64(0xffffffffffffffff) : 0; - d.q[1]=d.f64[1] == s.f64[1] ? U64(0xffffffffffffffff) : 0; - break; - case 1: - d.q[0]=d.f64[0] < s.f64[0] ? U64(0xffffffffffffffff) : 0; - d.q[1]=d.f64[1] < s.f64[1] ? U64(0xffffffffffffffff) : 0; - break; - case 2: - d.q[0]=d.f64[0] <= s.f64[0] ? U64(0xffffffffffffffff) : 0; - d.q[1]=d.f64[1] <= s.f64[1] ? U64(0xffffffffffffffff) : 0; - break; - case 3: - d.q[0]=sse_isdoubleunordered(d.f64[0], s.f64[0]) ? U64(0xffffffffffffffff) : 0; - d.q[1]=sse_isdoubleunordered(d.f64[1], s.f64[1]) ? U64(0xffffffffffffffff) : 0; - break; - case 4: - d.q[0]=d.f64[0] != s.f64[0] ? U64(0xffffffffffffffff) : 0; - d.q[1]=d.f64[1] != s.f64[1] ? U64(0xffffffffffffffff) : 0; - break; - case 5: - d.q[0]=d.f64[0] < s.f64[0] ? 0 : U64(0xffffffffffffffff); - d.q[1]=d.f64[1] < s.f64[1] ? 0 : U64(0xffffffffffffffff); - break; - case 6: - d.q[0]=d.f64[0] <= s.f64[0] ? 0 : U64(0xffffffffffffffff); - d.q[1]=d.f64[1] <= s.f64[1] ? 0 : U64(0xffffffffffffffff); - break; - case 7: - d.q[0]=sse_isdoubleordered(d.f64[0], s.f64[0]) ? U64(0xffffffffffffffff) : 0; - d.q[1]=sse_isdoubleordered(d.f64[1], s.f64[1]) ? U64(0xffffffffffffffff) : 0; - break; - } -} - - void I386_OPS_BASE::SSEOP(predicate_compare_single_scalar)(UINT8 imm8, XMM_REG d, XMM_REG s) -{ - switch (imm8 & 7) - { - case 0: - d.d[0]=d.f[0] == s.f[0] ? 0xffffffff : 0; - break; - case 1: - d.d[0]=d.f[0] < s.f[0] ? 0xffffffff : 0; - break; - case 2: - d.d[0]=d.f[0] <= s.f[0] ? 0xffffffff : 0; - break; - case 3: - d.d[0]=sse_issingleunordered(d.f[0], s.f[0]) ? 0xffffffff : 0; - break; - case 4: - d.d[0]=d.f[0] != s.f[0] ? 0xffffffff : 0; - break; - case 5: - d.d[0]=d.f[0] < s.f[0] ? 0 : 0xffffffff; - break; - case 6: - d.d[0]=d.f[0] <= s.f[0] ? 0 : 0xffffffff; - break; - case 7: - d.d[0]=sse_issingleordered(d.f[0], s.f[0]) ? 0xffffffff : 0; - break; - } -} - - void I386_OPS_BASE::SSEOP(predicate_compare_double_scalar)(UINT8 imm8, XMM_REG d, XMM_REG s) -{ - switch (imm8 & 7) - { - case 0: - d.q[0]=d.f64[0] == s.f64[0] ? 0xffffffffffffffff : 0; - break; - case 1: - d.q[0]=d.f64[0] < s.f64[0] ? 0xffffffffffffffff : 0; - break; - case 2: - d.q[0]=d.f64[0] <= s.f64[0] ? 0xffffffffffffffff : 0; - break; - case 3: - d.q[0]=sse_isdoubleunordered(d.f64[0], s.f64[0]) ? 0xffffffffffffffff : 0; - break; - case 4: - d.q[0]=d.f64[0] != s.f64[0] ? 0xffffffffffffffff : 0; - break; - case 5: - d.q[0]=d.f64[0] < s.f64[0] ? 0 : 0xffffffffffffffff; - break; - case 6: - d.q[0]=d.f64[0] <= s.f64[0] ? 0 : 0xffffffffffffffff; - break; - case 7: - d.q[0]=sse_isdoubleordered(d.f64[0], s.f64[0]) ? 0xffffffffffffffff : 0; - break; - } -} - - void I386_OPS_BASE::SSEOP(cmpps_r128_rm128_i8)() // Opcode 0f c2 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - sse_predicate_compare_single(imm8, XMM(d), XMM(s)); - } else { - int d; - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - UINT8 imm8 = FETCH(); - READXMM( ea, s); - d=(modrm >> 3) & 0x7; - sse_predicate_compare_single(imm8, XMM(d), s); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cmppd_r128_rm128_i8)() // Opcode 66 0f c2 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - sse_predicate_compare_double(imm8, XMM(d), XMM(s)); - } else { - int d; - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - UINT8 imm8 = FETCH(); - READXMM( ea, s); - d=(modrm >> 3) & 0x7; - sse_predicate_compare_double(imm8, XMM(d), s); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cmpss_r128_r128m32_i8)() // Opcode f3 0f c2 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - sse_predicate_compare_single_scalar(imm8, XMM(d), XMM(s)); - } else { - int d; - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 4); - UINT8 imm8 = FETCH(); - s.d[0]=READ32(ea); - d=(modrm >> 3) & 0x7; - sse_predicate_compare_single_scalar(imm8, XMM(d), s); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pinsrw_r64_r16m16_i8)() // Opcode 0f c4, 16bit register -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 imm8 = FETCH(); - UINT16 v = LOAD_RM16(modrm); - if (cpustate->xmm_operand_size) - XMM((modrm >> 3) & 0x7).w[imm8 & 7] = v; - else - MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; - } else { - UINT32 ea = GetEA(modrm, 0, 2); - UINT8 imm8 = FETCH(); - UINT16 v = READ16(ea); - if (cpustate->xmm_operand_size) - XMM((modrm >> 3) & 0x7).w[imm8 & 7] = v; - else - MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pinsrw_r64_r32m16_i8)() // Opcode 0f c4, 32bit register -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 imm8 = FETCH(); - UINT16 v = (UINT16)LOAD_RM32(modrm); - MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; - } else { - UINT32 ea = GetEA(modrm, 0, 2); - UINT8 imm8 = FETCH(); - UINT16 v = READ16(ea); - MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pinsrw_r128_r32m16_i8)() // Opcode 66 0f c4 -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - UINT8 imm8 = FETCH(); - UINT16 v = (UINT16)LOAD_RM32(modrm); - XMM((modrm >> 3) & 0x7).w[imm8 & 7] = v; - } - else { - UINT32 ea = GetEA(modrm, 0, 2); - UINT8 imm8 = FETCH(); - UINT16 v = READ16(ea); - XMM((modrm >> 3) & 0x7).w[imm8 & 7] = v; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pextrw_r16_r64_i8)() // Opcode 0f c5 -{ - //MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 imm8 = FETCH(); - if (cpustate->xmm_operand_size) - STORE_REG16(modrm, XMM(modrm & 0x7).w[imm8 & 7]); - else - STORE_REG16(modrm, MMX(modrm & 0x7).w[imm8 & 3]); - } else { - //UINT8 imm8 = FETCH(); - report_invalid_modrm( "pextrw_r16_r64_i8", modrm); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pextrw_r32_r64_i8)() // Opcode 0f c5 -{ - //MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - UINT8 imm8 = FETCH(); - STORE_REG32(modrm, MMX(modrm & 0x7).w[imm8 & 3]); - } else { - //UINT8 imm8 = FETCH(); - report_invalid_modrm( "pextrw_r32_r64_i8", modrm); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pextrw_reg_r128_i8)() // Opcode 66 0f c5 -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - UINT8 imm8 = FETCH(); - STORE_REG32(modrm, XMM(modrm & 0x7).w[imm8 & 7]); - } - else { - //UINT8 imm8 = FETCH(); - report_invalid_modrm( "sse_pextrw_reg_r128_i8", modrm); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pminub_r64_rm64)() // Opcode 0f da -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] < MMX(modrm & 0x7).b[n] ? MMX((modrm >> 3) & 0x7).b[n] : MMX(modrm & 0x7).b[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] < s.b[n] ? MMX((modrm >> 3) & 0x7).b[n] : s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pminub_r128_rm128)() // Opcode 66 0f da -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n] = XMM((modrm >> 3) & 0x7).b[n] < XMM(modrm & 0x7).b[n] ? XMM((modrm >> 3) & 0x7).b[n] : XMM(modrm & 0x7).b[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n] = XMM((modrm >> 3) & 0x7).b[n] < s.b[n] ? XMM((modrm >> 3) & 0x7).b[n] : s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmaxub_r64_rm64)() // Opcode 0f de -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] > MMX(modrm & 0x7).b[n] ? MMX((modrm >> 3) & 0x7).b[n] : MMX(modrm & 0x7).b[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] > s.b[n] ? MMX((modrm >> 3) & 0x7).b[n] : s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pavgb_r64_rm64)() // Opcode 0f e0 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n] = ((UINT16)MMX((modrm >> 3) & 0x7).b[n] + (UINT16)MMX(modrm & 0x7).b[n] + 1) >> 1; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 8;n++) - MMX((modrm >> 3) & 0x7).b[n] = ((UINT16)MMX((modrm >> 3) & 0x7).b[n] + (UINT16)s.b[n] + 1) >> 1; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pavgw_r64_rm64)() // Opcode 0f e3 -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n] = ((UINT32)MMX((modrm >> 3) & 0x7).w[n] + (UINT32)MMX(modrm & 0x7).w[n] + 1) >> 1; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).w[n] = ((UINT32)MMX((modrm >> 3) & 0x7).w[n] + (UINT32)s.w[n] + 1) >> 1; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmulhuw_r64_rm64)() // Opcode 0f e4 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).w[0]=((UINT32)MMX((modrm >> 3) & 0x7).w[0]*(UINT32)MMX(modrm & 7).w[0]) >> 16; - MMX((modrm >> 3) & 0x7).w[1]=((UINT32)MMX((modrm >> 3) & 0x7).w[1]*(UINT32)MMX(modrm & 7).w[1]) >> 16; - MMX((modrm >> 3) & 0x7).w[2]=((UINT32)MMX((modrm >> 3) & 0x7).w[2]*(UINT32)MMX(modrm & 7).w[2]) >> 16; - MMX((modrm >> 3) & 0x7).w[3]=((UINT32)MMX((modrm >> 3) & 0x7).w[3]*(UINT32)MMX(modrm & 7).w[3]) >> 16; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX((modrm >> 3) & 0x7).w[0]=((UINT32)MMX((modrm >> 3) & 0x7).w[0]*(UINT32)s.w[0]) >> 16; - MMX((modrm >> 3) & 0x7).w[1]=((UINT32)MMX((modrm >> 3) & 0x7).w[1]*(UINT32)s.w[1]) >> 16; - MMX((modrm >> 3) & 0x7).w[2]=((UINT32)MMX((modrm >> 3) & 0x7).w[2]*(UINT32)s.w[2]) >> 16; - MMX((modrm >> 3) & 0x7).w[3]=((UINT32)MMX((modrm >> 3) & 0x7).w[3]*(UINT32)s.w[3]) >> 16; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pminsw_r64_rm64)() // Opcode 0f ea -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] < MMX(modrm & 0x7).s[n] ? MMX((modrm >> 3) & 0x7).s[n] : MMX(modrm & 0x7).s[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] < s.s[n] ? MMX((modrm >> 3) & 0x7).s[n] : s.s[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmaxsw_r64_rm64)() // Opcode 0f ee -{ - int n; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] > MMX(modrm & 0x7).s[n] ? MMX((modrm >> 3) & 0x7).s[n] : MMX(modrm & 0x7).s[n]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - for (n=0;n < 4;n++) - MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] > s.s[n] ? MMX((modrm >> 3) & 0x7).s[n] : s.s[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmuludq_r64_rm64)() // Opcode 0f f4 -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q = (UINT64)MMX((modrm >> 3) & 0x7).d[0] * (UINT64)MMX(modrm & 0x7).d[0]; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX((modrm >> 3) & 0x7).q = (UINT64)MMX((modrm >> 3) & 0x7).d[0] * (UINT64)s.d[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmuludq_r128_rm128)() // Opcode 66 0f f4 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = (UINT64)XMM((modrm >> 3) & 0x7).d[0] * (UINT64)XMM(modrm & 0x7).d[0]; - XMM((modrm >> 3) & 0x7).q[1] = (UINT64)XMM((modrm >> 3) & 0x7).d[2] * (UINT64)XMM(modrm & 0x7).d[2]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - XMM((modrm >> 3) & 0x7).q[0] = (UINT64)XMM((modrm >> 3) & 0x7).d[0] * (UINT64)s.d[0]; - XMM((modrm >> 3) & 0x7).q[1] = (UINT64)XMM((modrm >> 3) & 0x7).d[2] * (UINT64)s.d[2]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psadbw_r64_rm64)() // Opcode 0f f6 -{ - int n; - INT32 temp; - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - temp=0; - for (n=0;n < 8;n++) - temp += abs((INT32)MMX((modrm >> 3) & 0x7).b[n] - (INT32)MMX(modrm & 0x7).b[n]); - MMX((modrm >> 3) & 0x7).l=(UINT64)temp & 0xffff; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - temp=0; - for (n=0;n < 8;n++) - temp += abs((INT32)MMX((modrm >> 3) & 0x7).b[n] - (INT32)s.b[n]); - MMX((modrm >> 3) & 0x7).l=(UINT64)temp & 0xffff; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubq_r64_rm64)() // Opcode 0f fb -{ - MMXPROLOG(); - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q - MMX(modrm & 7).q; - } else { - MMX_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, s); - MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q - s.q; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubq_r128_rm128)() // Opcode 66 0f fb -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] - XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] - XMM(modrm & 7).q[1]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] - s.q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] - s.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pshufd_r128_rm128_i8)() // Opcode 66 0f 70 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[0]=XMM(s).q[0]; - t.q[1]=XMM(s).q[1]; - XMM(d).d[0]=t.d[imm8 & 3]; - XMM(d).d[1]=t.d[(imm8 >> 2) & 3]; - XMM(d).d[2]=t.d[(imm8 >> 4) & 3]; - XMM(d).d[3]=t.d[(imm8 >> 6) & 3]; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - UINT8 imm8 = FETCH(); - READXMM( ea, s); - XMM(d).d[0]=s.d[(imm8 & 3)]; - XMM(d).d[1]=s.d[((imm8 >> 2) & 3)]; - XMM(d).d[2]=s.d[((imm8 >> 4) & 3)]; - XMM(d).d[3]=s.d[((imm8 >> 6) & 3)]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pshuflw_r128_rm128_i8)() // Opcode f2 0f 70 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[0]=XMM(s).q[0]; - XMM(d).q[1]=XMM(s).q[1]; - XMM(d).w[0]=t.w[imm8 & 3]; - XMM(d).w[1]=t.w[(imm8 >> 2) & 3]; - XMM(d).w[2]=t.w[(imm8 >> 4) & 3]; - XMM(d).w[3]=t.w[(imm8 >> 6) & 3]; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - UINT8 imm8 = FETCH(); - READXMM( ea, s); - XMM(d).q[1]=s.q[1]; - XMM(d).w[0]=s.w[imm8 & 3]; - XMM(d).w[1]=s.w[(imm8 >> 2) & 3]; - XMM(d).w[2]=s.w[(imm8 >> 4) & 3]; - XMM(d).w[3]=s.w[(imm8 >> 6) & 3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pshufhw_r128_rm128_i8)() // Opcode f3 0f 70 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[0]=XMM(s).q[1]; - XMM(d).q[0]=XMM(s).q[0]; - XMM(d).w[4]=t.w[imm8 & 3]; - XMM(d).w[5]=t.w[(imm8 >> 2) & 3]; - XMM(d).w[6]=t.w[(imm8 >> 4) & 3]; - XMM(d).w[7]=t.w[(imm8 >> 6) & 3]; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - UINT8 imm8 = FETCH(); - READXMM( ea, s); - XMM(d).q[0]=s.q[0]; - XMM(d).w[4]=s.w[4 + (imm8 & 3)]; - XMM(d).w[5]=s.w[4 + ((imm8 >> 2) & 3)]; - XMM(d).w[6]=s.w[4 + ((imm8 >> 4) & 3)]; - XMM(d).w[7]=s.w[4 + ((imm8 >> 6) & 3)]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(packsswb_r128_rm128)() // Opcode 66 0f 63 -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM_REG t; - int s, d; - s = modrm & 0x7; - d = (modrm >> 3) & 0x7; - t.q[0] = XMM(s).q[0]; - t.q[1] = XMM(s).q[1]; - for (int n = 0; n < 8; n++) - XMM(d).c[n] = SaturatedSignedWordToSignedByte(XMM(d).s[n]); - for (int n = 0; n < 8; n++) - XMM(d).c[n+8] = SaturatedSignedWordToSignedByte(t.s[n]); - } - else { - XMM_REG s; - int d = (modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n = 0; n < 8; n++) - XMM(d).c[n] = SaturatedSignedWordToSignedByte(XMM(d).s[n]); - for (int n = 0; n < 8; n++) - XMM(d).c[n + 8] = SaturatedSignedWordToSignedByte(s.s[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(packssdw_r128_rm128)() // Opcode 66 0f 6b -{ - UINT8 modrm = FETCH(); - if (modrm >= 0xc0) { - XMM_REG t; - int s, d; - s = modrm & 0x7; - d = (modrm >> 3) & 0x7; - t.q[0] = XMM(s).q[0]; - t.q[1] = XMM(s).q[1]; - XMM(d).s[0] = SaturatedSignedDwordToSignedWord(XMM(d).i[0]); - XMM(d).s[1] = SaturatedSignedDwordToSignedWord(XMM(d).i[1]); - XMM(d).s[2] = SaturatedSignedDwordToSignedWord(XMM(d).i[2]); - XMM(d).s[3] = SaturatedSignedDwordToSignedWord(XMM(d).i[3]); - XMM(d).s[4] = SaturatedSignedDwordToSignedWord(t.i[0]); - XMM(d).s[5] = SaturatedSignedDwordToSignedWord(t.i[1]); - XMM(d).s[6] = SaturatedSignedDwordToSignedWord(t.i[2]); - XMM(d).s[7] = SaturatedSignedDwordToSignedWord(t.i[3]); - } - else { - XMM_REG s; - int d = (modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - XMM(d).s[0] = SaturatedSignedDwordToSignedWord(XMM(d).i[0]); - XMM(d).s[1] = SaturatedSignedDwordToSignedWord(XMM(d).i[1]); - XMM(d).s[2] = SaturatedSignedDwordToSignedWord(XMM(d).i[2]); - XMM(d).s[3] = SaturatedSignedDwordToSignedWord(XMM(d).i[3]); - XMM(d).s[4] = SaturatedSignedDwordToSignedWord(s.i[0]); - XMM(d).s[5] = SaturatedSignedDwordToSignedWord(s.i[1]); - XMM(d).s[6] = SaturatedSignedDwordToSignedWord(s.i[2]); - XMM(d).s[7] = SaturatedSignedDwordToSignedWord(s.i[3]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pcmpgtb_r128_rm128)() // Opcode 66 0f 64 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (int c=0;c <= 15;c++) - XMM(d).b[c]=(XMM(d).c[c] > XMM(s).c[c]) ? 0xff : 0; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int c=0;c <= 15;c++) - XMM(d).b[c]=(XMM(d).c[c] > s.c[c]) ? 0xff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pcmpgtw_r128_rm128)() // Opcode 66 0f 65 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (int c=0;c <= 7;c++) - XMM(d).w[c]=(XMM(d).s[c] > XMM(s).s[c]) ? 0xffff : 0; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int c=0;c <= 7;c++) - XMM(d).w[c]=(XMM(d).s[c] > s.s[c]) ? 0xffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pcmpgtd_r128_rm128)() // Opcode 66 0f 66 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (int c=0;c <= 3;c++) - XMM(d).d[c]=(XMM(d).i[c] > XMM(s).i[c]) ? 0xffffffff : 0; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int c=0;c <= 3;c++) - XMM(d).d[c]=(XMM(d).i[c] > s.i[c]) ? 0xffffffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(packuswb_r128_rm128)() // Opcode 66 0f 67 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[0] = XMM(s).q[0]; - t.q[1] = XMM(s).q[1]; - for (int n = 0; n < 8;n++) - XMM(d).b[n]=SaturatedSignedWordToUnsignedByte(XMM(d).s[n]); - for (int n = 0; n < 8;n++) - XMM(d).b[n+8]=SaturatedSignedWordToUnsignedByte(t.s[n]); - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n = 0; n < 8;n++) - XMM(d).b[n]=SaturatedSignedWordToUnsignedByte(XMM(d).s[n]); - for (int n = 0; n < 8;n++) - XMM(d).b[n+8]=SaturatedSignedWordToUnsignedByte(s.s[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(punpckhbw_r128_rm128)() // Opcode 66 0f 68 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[1] = XMM(s).q[1]; - for (int n = 0; n < 16; n += 2) { - XMM(d).b[n]=XMM(d).b[8+(n >> 1)]; - XMM(d).b[n+1]=t.b[8+(n >> 1)]; - } - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n = 0; n < 16; n += 2) { - XMM(d).b[n]=XMM(d).b[8+(n >> 1)]; - XMM(d).b[n+1]=s.b[8+(n >> 1)]; - } - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(punpckhwd_r128_rm128)() // Opcode 66 0f 69 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[1] = XMM(s).q[1]; - for (int n = 0; n < 8; n += 2) { - XMM(d).w[n]=XMM(d).w[4+(n >> 1)]; - XMM(d).w[n+1]=t.w[4+(n >> 1)]; - } - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n = 0; n < 8; n += 2) { - XMM(d).w[n]=XMM(d).w[4+(n >> 1)]; - XMM(d).w[n+1]=s.w[4+(n >> 1)]; - } - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(unpckhdq_r128_rm128)() // Opcode 66 0f 6a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[1] = XMM(s).q[1]; - XMM(d).d[0]=XMM(d).d[2]; - XMM(d).d[1]=t.d[2]; - XMM(d).d[2]=XMM(d).d[3]; - XMM(d).d[3]=t.d[3]; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - XMM(d).d[0]=XMM(d).d[2]; - XMM(d).d[1]=s.d[2]; - XMM(d).d[2]=XMM(d).d[3]; - XMM(d).d[3]=s.d[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(punpckhqdq_r128_rm128)() // Opcode 66 0f 6d -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM_REG t; - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - t.q[1] = XMM(s).q[1]; - XMM(d).q[0]=XMM(d).q[1]; - XMM(d).q[1]=t.q[1]; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - XMM(d).q[0]=XMM(d).q[1]; - XMM(d).q[1]=s.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pcmpeqb_r128_rm128)() // Opcode 66 0f 74 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (int c=0;c <= 15;c++) - XMM(d).b[c]=(XMM(d).c[c] == XMM(s).c[c]) ? 0xff : 0; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int c=0;c <= 15;c++) - XMM(d).b[c]=(XMM(d).c[c] == s.c[c]) ? 0xff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pcmpeqw_r128_rm128)() // Opcode 66 0f 75 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (int c=0;c <= 7;c++) - XMM(d).w[c]=(XMM(d).s[c] == XMM(s).s[c]) ? 0xffff : 0; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int c=0;c <= 7;c++) - XMM(d).w[c]=(XMM(d).s[c] == s.s[c]) ? 0xffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pcmpeqd_r128_rm128)() // Opcode 66 0f 76 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (int c=0;c <= 3;c++) - XMM(d).d[c]=(XMM(d).i[c] == XMM(s).i[c]) ? 0xffffffff : 0; - } else { - XMM_REG s; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int c=0;c <= 3;c++) - XMM(d).d[c]=(XMM(d).i[c] == s.i[c]) ? 0xffffffff : 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddq_r128_rm128)() // Opcode 66 0f d4 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - XMM(d).q[0]=XMM(d).q[0]+XMM(s).q[0]; - XMM(d).q[1]=XMM(d).q[1]+XMM(s).q[1]; - } else { - XMM_REG src; - int d=(modrm >> 3) & 0x7; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM(d).q[0]=XMM(d).q[0]+src.q[0]; - XMM(d).q[1]=XMM(d).q[1]+src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmullw_r128_rm128)() // Opcode 66 0f d5 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - for (int n = 0; n < 8;n++) - XMM(d).w[n]=(UINT32)((INT32)XMM(d).s[n]*(INT32)XMM(s).s[n]) & 0xffff; - } else { - XMM_REG src; - int d; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - d=(modrm >> 3) & 0x7; - for (int n = 0; n < 8;n++) - XMM(d).w[n]=(UINT32)((INT32)XMM(d).s[n]*(INT32)src.s[n]) & 0xffff; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddb_r128_rm128)() // Opcode 66 0f fc -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] + XMM(modrm & 7).b[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] + s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddw_r128_rm128)() // Opcode 66 0f fd -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] + XMM(modrm & 7).w[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] + s.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddd_r128_rm128)() // Opcode 66 0f fe -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 4;n++) - XMM((modrm >> 3) & 0x7).d[n]=XMM((modrm >> 3) & 0x7).d[n] + XMM(modrm & 7).d[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 4;n++) - XMM((modrm >> 3) & 0x7).d[n]=XMM((modrm >> 3) & 0x7).d[n] + s.d[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubusb_r128_rm128)() // Opcode 66 0f d8 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] < XMM(modrm & 7).b[n] ? 0 : XMM((modrm >> 3) & 0x7).b[n]-XMM(modrm & 7).b[n]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] < src.b[n] ? 0 : XMM((modrm >> 3) & 0x7).b[n]-src.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubusw_r128_rm128)() // Opcode 66 0f d9 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] < XMM(modrm & 7).w[n] ? 0 : XMM((modrm >> 3) & 0x7).w[n]-XMM(modrm & 7).w[n]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] < src.w[n] ? 0 : XMM((modrm >> 3) & 0x7).w[n]-src.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pand_r128_rm128)() // Opcode 66 0f db -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] & XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] & XMM(modrm & 7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] & src.q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] & src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pandn_r128_rm128)() // Opcode 66 0f df -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0]=(~XMM((modrm >> 3) & 0x7).q[0]) & XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).q[1]=(~XMM((modrm >> 3) & 0x7).q[1]) & XMM(modrm & 7).q[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).q[0]=(~XMM((modrm >> 3) & 0x7).q[0]) & src.q[0]; - XMM((modrm >> 3) & 0x7).q[1]=(~XMM((modrm >> 3) & 0x7).q[1]) & src.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddusb_r128_rm128)() // Opcode 66 0f dc -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] > (0xff-XMM(modrm & 7).b[n]) ? 0xff : XMM((modrm >> 3) & 0x7).b[n]+XMM(modrm & 7).b[n]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] > (0xff-src.b[n]) ? 0xff : XMM((modrm >> 3) & 0x7).b[n]+src.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddusw_r128_rm128)() // Opcode 66 0f dd -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] > (0xffff-XMM(modrm & 7).w[n]) ? 0xffff : XMM((modrm >> 3) & 0x7).w[n]+XMM(modrm & 7).w[n]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] > (0xffff-src.w[n]) ? 0xffff : XMM((modrm >> 3) & 0x7).w[n]+src.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmaxub_r128_rm128)() // Opcode 66 0f de -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n] = XMM((modrm >> 3) & 0x7).b[n] > XMM(modrm & 0x7).b[n] ? XMM((modrm >> 3) & 0x7).b[n] : XMM(modrm & 0x7).b[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n] = XMM((modrm >> 3) & 0x7).b[n] > s.b[n] ? XMM((modrm >> 3) & 0x7).b[n] : s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmulhuw_r128_rm128)() // Opcode 66 0f e4 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=((UINT32)XMM((modrm >> 3) & 0x7).w[n]*(UINT32)XMM(modrm & 7).w[n]) >> 16; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=((UINT32)XMM((modrm >> 3) & 0x7).w[n]*(UINT32)s.w[n]) >> 16; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmulhw_r128_rm128)() // Opcode 66 0f e5 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=(UINT32)((INT32)XMM((modrm >> 3) & 0x7).s[n]*(INT32)XMM(modrm & 7).s[n]) >> 16; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=(UINT32)((INT32)XMM((modrm >> 3) & 0x7).s[n]*(INT32)src.s[n]) >> 16; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubsb_r128_rm128)() // Opcode 66 0f e8 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)XMM((modrm >> 3) & 0x7).c[n] - (INT16)XMM(modrm & 7).c[n]); - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)XMM((modrm >> 3) & 0x7).c[n] - (INT16)s.c[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubsw_r128_rm128)() // Opcode 66 0f e9 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)XMM((modrm >> 3) & 0x7).s[n] - (INT32)XMM(modrm & 7).s[n]); - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)XMM((modrm >> 3) & 0x7).s[n] - (INT32)s.s[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pminsw_r128_rm128)() // Opcode 66 0f ea -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n] = XMM((modrm >> 3) & 0x7).s[n] < XMM(modrm & 0x7).s[n] ? XMM((modrm >> 3) & 0x7).s[n] : XMM(modrm & 0x7).s[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n] = XMM((modrm >> 3) & 0x7).s[n] < s.s[n] ? XMM((modrm >> 3) & 0x7).s[n] : s.s[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmaxsw_r128_rm128)() // Opcode 66 0f ee -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n] = XMM((modrm >> 3) & 0x7).s[n] > XMM(modrm & 0x7).s[n] ? XMM((modrm >> 3) & 0x7).s[n] : XMM(modrm & 0x7).s[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n] = XMM((modrm >> 3) & 0x7).s[n] > s.s[n] ? XMM((modrm >> 3) & 0x7).s[n] : s.s[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddsb_r128_rm128)() // Opcode 66 0f ec -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)XMM((modrm >> 3) & 0x7).c[n] + (INT16)XMM(modrm & 7).c[n]); - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)XMM((modrm >> 3) & 0x7).c[n] + (INT16)s.c[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(paddsw_r128_rm128)() // Opcode 66 0f ed -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)XMM((modrm >> 3) & 0x7).s[n] + (INT32)XMM(modrm & 7).s[n]); - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)XMM((modrm >> 3) & 0x7).s[n] + (INT32)s.s[n]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(por_r128_rm128)() // Opcode 66 0f eb -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] | XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] | XMM(modrm & 7).q[1]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] | s.q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] | s.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pxor_r128_rm128)() // Opcode 66 0f ef -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] ^ XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] ^ XMM(modrm & 7).q[1]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] ^ s.q[0]; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] ^ s.q[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pmaddwd_r128_rm128)() // Opcode 66 0f f5 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 4;n++) - XMM((modrm >> 3) & 0x7).i[n]=(INT32)XMM((modrm >> 3) & 0x7).s[n]*(INT32)XMM(modrm & 7).s[n]+ - (INT32)XMM((modrm >> 3) & 0x7).s[n]*(INT32)XMM(modrm & 7).s[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 4;n++) - XMM((modrm >> 3) & 0x7).i[n]=(INT32)XMM((modrm >> 3) & 0x7).s[n]*(INT32)s.s[n]+ - (INT32)XMM((modrm >> 3) & 0x7).s[n]*(INT32)s.s[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubb_r128_rm128)() // Opcode 66 0f f8 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] - XMM(modrm & 7).b[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n]=XMM((modrm >> 3) & 0x7).b[n] - s.b[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubw_r128_rm128)() // Opcode 66 0f f9 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] - XMM(modrm & 7).w[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] - s.w[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psubd_r128_rm128)() // Opcode 66 0f fa -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 4;n++) - XMM((modrm >> 3) & 0x7).d[n]=XMM((modrm >> 3) & 0x7).d[n] - XMM(modrm & 7).d[n]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 4;n++) - XMM((modrm >> 3) & 0x7).d[n]=XMM((modrm >> 3) & 0x7).d[n] - s.d[n]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psadbw_r128_rm128)() // Opcode 66 0f f6 -{ - INT32 temp; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - temp=0; - for (int n=0;n < 8;n++) - temp += abs((INT32)XMM((modrm >> 3) & 0x7).b[n] - (INT32)XMM(modrm & 0x7).b[n]); - XMM((modrm >> 3) & 0x7).l[0]=(UINT64)temp & 0xffff; - temp=0; - for (int n=8;n < 16;n++) - temp += abs((INT32)XMM((modrm >> 3) & 0x7).b[n] - (INT32)XMM(modrm & 0x7).b[n]); - XMM((modrm >> 3) & 0x7).l[1]=(UINT64)temp & 0xffff; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - temp=0; - for (int n=0;n < 8;n++) - temp += abs((INT32)XMM((modrm >> 3) & 0x7).b[n] - (INT32)s.b[n]); - XMM((modrm >> 3) & 0x7).l[0]=(UINT64)temp & 0xffff; - temp=0; - for (int n=8;n < 16;n++) - temp += abs((INT32)XMM((modrm >> 3) & 0x7).b[n] - (INT32)s.b[n]); - XMM((modrm >> 3) & 0x7).l[1]=(UINT64)temp & 0xffff; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pavgb_r128_rm128)() // Opcode 66 0f e0 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n] = ((UINT16)XMM((modrm >> 3) & 0x7).b[n] + (UINT16)XMM(modrm & 0x7).b[n] + 1) >> 1; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 16;n++) - XMM((modrm >> 3) & 0x7).b[n] = ((UINT16)XMM((modrm >> 3) & 0x7).b[n] + (UINT16)s.b[n] + 1) >> 1; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pavgw_r128_rm128)() // Opcode 66 0f e3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n] = ((UINT32)XMM((modrm >> 3) & 0x7).w[n] + (UINT32)XMM(modrm & 0x7).w[n] + 1) >> 1; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - for (int n=0;n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n] = ((UINT32)XMM((modrm >> 3) & 0x7).w[n] + (UINT32)s.w[n] + 1) >> 1; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psrlw_r128_rm128)() // Opcode 66 0f d1 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - for (int n=0; n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] >> count; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - int count=(int)src.q[0]; - for (int n=0; n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psrld_r128_rm128)() // Opcode 66 0f d2 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).d[0]=XMM((modrm >> 3) & 0x7).d[0] >> count; - XMM((modrm >> 3) & 0x7).d[1]=XMM((modrm >> 3) & 0x7).d[1] >> count; - XMM((modrm >> 3) & 0x7).d[2]=XMM((modrm >> 3) & 0x7).d[2] >> count; - XMM((modrm >> 3) & 0x7).d[3]=XMM((modrm >> 3) & 0x7).d[3] >> count; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - int count=(int)src.q[0]; - XMM((modrm >> 3) & 0x7).d[0]=XMM((modrm >> 3) & 0x7).d[0] >> count; - XMM((modrm >> 3) & 0x7).d[1]=XMM((modrm >> 3) & 0x7).d[1] >> count; - XMM((modrm >> 3) & 0x7).d[2]=XMM((modrm >> 3) & 0x7).d[2] >> count; - XMM((modrm >> 3) & 0x7).d[3]=XMM((modrm >> 3) & 0x7).d[3] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psrlq_r128_rm128)() // Opcode 66 0f d3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] >> count; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] >> count; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - int count=(int)src.q[0]; - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] >> count; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psllw_r128_rm128)() // Opcode 66 0f f1 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - for (int n=0; n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] << count; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - int count=(int)s.q[0]; - for (int n=0; n < 8;n++) - XMM((modrm >> 3) & 0x7).w[n]=XMM((modrm >> 3) & 0x7).w[n] << count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(pslld_r128_rm128)() // Opcode 66 0f f2 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).d[0]=XMM((modrm >> 3) & 0x7).d[0] << count; - XMM((modrm >> 3) & 0x7).d[1]=XMM((modrm >> 3) & 0x7).d[1] << count; - XMM((modrm >> 3) & 0x7).d[2]=XMM((modrm >> 3) & 0x7).d[2] << count; - XMM((modrm >> 3) & 0x7).d[3]=XMM((modrm >> 3) & 0x7).d[3] << count; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - int count=(int)s.q[0]; - XMM((modrm >> 3) & 0x7).d[0]=XMM((modrm >> 3) & 0x7).d[0] << count; - XMM((modrm >> 3) & 0x7).d[1]=XMM((modrm >> 3) & 0x7).d[1] << count; - XMM((modrm >> 3) & 0x7).d[2]=XMM((modrm >> 3) & 0x7).d[2] << count; - XMM((modrm >> 3) & 0x7).d[3]=XMM((modrm >> 3) & 0x7).d[3] << count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psllq_r128_rm128)() // Opcode 66 0f f3 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] << count; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] << count; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, s); - int count=(int)s.q[0]; - XMM((modrm >> 3) & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0] << count; - XMM((modrm >> 3) & 0x7).q[1]=XMM((modrm >> 3) & 0x7).q[1] << count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psraw_r128_rm128)() // Opcode 66 0f e1 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - for (int n=0; n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n]=XMM((modrm >> 3) & 0x7).s[n] >> count; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - int count=(int)src.q[0]; - for (int n=0; n < 8;n++) - XMM((modrm >> 3) & 0x7).s[n]=XMM((modrm >> 3) & 0x7).s[n] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(psrad_r128_rm128)() // Opcode 66 0f e2 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int count=(int)XMM(modrm & 7).q[0]; - XMM((modrm >> 3) & 0x7).i[0]=XMM((modrm >> 3) & 0x7).i[0] >> count; - XMM((modrm >> 3) & 0x7).i[1]=XMM((modrm >> 3) & 0x7).i[1] >> count; - XMM((modrm >> 3) & 0x7).i[2]=XMM((modrm >> 3) & 0x7).i[2] >> count; - XMM((modrm >> 3) & 0x7).i[3]=XMM((modrm >> 3) & 0x7).i[3] >> count; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - int count=(int)src.q[0]; - XMM((modrm >> 3) & 0x7).i[0]=XMM((modrm >> 3) & 0x7).i[0] >> count; - XMM((modrm >> 3) & 0x7).i[1]=XMM((modrm >> 3) & 0x7).i[1] >> count; - XMM((modrm >> 3) & 0x7).i[2]=XMM((modrm >> 3) & 0x7).i[2] >> count; - XMM((modrm >> 3) & 0x7).i[3]=XMM((modrm >> 3) & 0x7).i[3] >> count; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movntdq_m128_r128)() // Opcode 66 0f e7 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - CYCLES(1); // unsupported - } else { - // since cache is not implemented - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(cvttpd2dq_r128_rm128)() // Opcode 66 0f e6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).i[0]=(INT32)XMM((modrm >> 3) & 0x7).f64[0]; - XMM((modrm >> 3) & 0x7).i[1]=(INT32)XMM((modrm >> 3) & 0x7).f64[1]; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).i[0]=(INT32)src.f64[0]; - XMM((modrm >> 3) & 0x7).i[1]=(INT32)src.f64[1]; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movq_r128m64_r128)() // Opcode 66 0f d6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7).q[0]=XMM((modrm >> 3) & 0x7).q[0]; - XMM(modrm & 0x7).q[1] = 0; - } else { - UINT32 ea = GetEA(modrm, 0, 16); - WRITE64( ea, XMM((modrm >> 3) & 0x7).q[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(addsubpd_r128_rm128)() // Opcode 66 0f d0 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s, d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - XMM(d).f64[0]=XMM(d).f64[0]-XMM(s).f64[0]; - XMM(d).f64[1]=XMM(d).f64[1]+XMM(s).f64[1]; - } else { - XMM_REG src; - int d; - UINT32 ea = GetEA(modrm, 0, 16); - d=(modrm >> 3) & 0x7; - READXMM( ea, src); - XMM(d).f64[0]=XMM(d).f64[0]-src.f64[0]; - XMM(d).f64[1]=XMM(d).f64[1]+src.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(haddpd_r128_rm128)() // Opcode 66 0f 7c -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s, d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - XMM(d).f64[0]=XMM(d).f64[0]+XMM(d).f64[1]; - XMM(d).f64[1]=XMM(s).f64[0]+XMM(s).f64[1]; - } else { - XMM_REG src; - int d; - UINT32 ea = GetEA(modrm, 0, 16); - d=(modrm >> 3) & 0x7; - READXMM( ea, src); - XMM(d).f64[0]=XMM(d).f64[0]+XMM(d).f64[1]; - XMM(d).f64[1]=src.f64[0]+src.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(hsubpd_r128_rm128)() // Opcode 66 0f 7d -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s, d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - XMM(d).f64[0]=XMM(d).f64[0]-XMM(d).f64[1]; - XMM(d).f64[1]=XMM(s).f64[0]-XMM(s).f64[1]; - } else { - XMM_REG src; - int d; - UINT32 ea = GetEA(modrm, 0, 16); - d=(modrm >> 3) & 0x7; - READXMM( ea, src); - XMM(d).f64[0]=XMM(d).f64[0]-XMM(d).f64[1]; - XMM(d).f64[1]=src.f64[0]-src.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(sqrtpd_r128_rm128)() // Opcode 66 0f 51 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s, d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - XMM(d).f64[0]=sqrt(XMM(s).f64[0]); - XMM(d).f64[1]=sqrt(XMM(s).f64[1]); - } else { - XMM_REG src; - int d; - UINT32 ea = GetEA(modrm, 0, 16); - d=(modrm >> 3) & 0x7; - READXMM( ea, src); - XMM(d).f64[0]=sqrt(src.f64[0]); - XMM(d).f64[1]=sqrt(src.f64[1]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtpi2pd_r128_rm64)() // Opcode 66 0f 2a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - MMXPROLOG(); - XMM((modrm >> 3) & 0x7).f64[0] = (double)MMX(modrm & 0x7).i[0]; - XMM((modrm >> 3) & 0x7).f64[1] = (double)MMX(modrm & 0x7).i[1]; - } else { - MMX_REG r; - UINT32 ea = GetEA(modrm, 0, 8); - READMMX( ea, r); - XMM((modrm >> 3) & 0x7).f64[0] = (double)r.i[0]; - XMM((modrm >> 3) & 0x7).f64[1] = (double)r.i[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvttpd2pi_r64_rm128)() // Opcode 66 0f 2c -{ - UINT8 modrm = FETCH(); - MMXPROLOG(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f64[0]; - MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f64[1]; - } else { - XMM_REG r; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, r); - MMX((modrm >> 3) & 0x7).i[0] = r.f64[0]; - MMX((modrm >> 3) & 0x7).i[1] = r.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtpd2pi_r64_rm128)() // Opcode 66 0f 2d -{ - UINT8 modrm = FETCH(); - MMXPROLOG(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f64[0]; - MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f64[1]; - } else { - XMM_REG r; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, r); - MMX((modrm >> 3) & 0x7).i[0] = r.f64[0]; - MMX((modrm >> 3) & 0x7).i[1] = r.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtpd2ps_r128_rm128)() // Opcode 66 0f 5a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = (float)XMM(modrm & 0x7).f64[0]; - XMM((modrm >> 3) & 0x7).f[1] = (float)XMM(modrm & 0x7).f64[1]; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } else { - XMM_REG r; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, r); - XMM((modrm >> 3) & 0x7).f[0] = (float)r.f64[0]; - XMM((modrm >> 3) & 0x7).f[1] = (float)r.f64[1]; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtps2dq_r128_rm128)() // Opcode 66 0f 5b -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).i[2] = XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).i[3] = XMM(modrm & 0x7).f[3]; - } else { - XMM_REG r; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, r); - XMM((modrm >> 3) & 0x7).i[0] = r.f[0]; - XMM((modrm >> 3) & 0x7).i[1] = r.f[1]; - XMM((modrm >> 3) & 0x7).i[2] = r.f[2]; - XMM((modrm >> 3) & 0x7).i[3] = r.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(addpd_r128_rm128)() // Opcode 66 0f 58 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] + XMM(modrm & 0x7).f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] + XMM(modrm & 0x7).f64[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] + src.f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] + src.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(mulpd_r128_rm128)() // Opcode 66 0f 59 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] * XMM(modrm & 0x7).f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] * XMM(modrm & 0x7).f64[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] * src.f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] * src.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(subpd_r128_rm128)() // Opcode 66 0f 5c -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] - XMM(modrm & 0x7).f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] - XMM(modrm & 0x7).f64[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] - src.f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] - src.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(minpd_r128_rm128)() // Opcode 66 0f 5d -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = sse_min_double(XMM((modrm >> 3) & 0x7).f64[0], XMM(modrm & 0x7).f64[0]); - XMM((modrm >> 3) & 0x7).f64[1] = sse_min_double(XMM((modrm >> 3) & 0x7).f64[1], XMM(modrm & 0x7).f64[1]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = sse_min_double(XMM((modrm >> 3) & 0x7).f64[0], src.f64[0]); - XMM((modrm >> 3) & 0x7).f64[1] = sse_min_double(XMM((modrm >> 3) & 0x7).f64[1], src.f64[1]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(divpd_r128_rm128)() // Opcode 66 0f 5e -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] / XMM(modrm & 0x7).f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] / XMM(modrm & 0x7).f64[1]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] / src.f64[0]; - XMM((modrm >> 3) & 0x7).f64[1] = XMM((modrm >> 3) & 0x7).f64[1] / src.f64[1]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(maxpd_r128_rm128)() // Opcode 66 0f 5f -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = sse_max_double(XMM((modrm >> 3) & 0x7).f64[0], XMM(modrm & 0x7).f64[0]); - XMM((modrm >> 3) & 0x7).f64[1] = sse_max_double(XMM((modrm >> 3) & 0x7).f64[1], XMM(modrm & 0x7).f64[1]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = sse_max_double(XMM((modrm >> 3) & 0x7).f64[0], src.f64[0]); - XMM((modrm >> 3) & 0x7).f64[1] = sse_max_double(XMM((modrm >> 3) & 0x7).f64[1], src.f64[1]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movntpd_m128_r128)() // Opcode 66 0f 2b -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - // since cache is not implemented - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(movapd_r128_rm128)() // Opcode 66 0f 28 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movapd_rm128_r128)() // Opcode 66 0f 29 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); - } else { - UINT32 ea = GetEA(modrm, 0, 16); - WRITEXMM( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movsd_r128_r128m64)() // Opcode f2 0f 10 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; - } else { - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_LO64( ea, XMM((modrm >> 3) & 0x7)); - XMM((modrm >> 3) & 0x7).q[1] = 0; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movsd_r128m64_r128)() // Opcode f2 0f 11 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM(modrm & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0]; - } else { - UINT32 ea = GetEA(modrm, 0, 8); - WRITEXMM_LO64( ea, XMM((modrm >> 3) & 0x7)); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movddup_r128_r128m64)() // Opcode f2 0f 12 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[0]; - } else { - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_LO64( ea, XMM((modrm >> 3) & 0x7)); - XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtsi2sd_r128_rm32)() // Opcode f2 0f 2a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = (INT32)LOAD_RM32(modrm); - } else { - UINT32 ea = GetEA(modrm, 0, 4); - XMM((modrm >> 3) & 0x7).f64[0] = (INT32)READ32(ea); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvttsd2si_r32_r128m64)() // Opcode f2 0f 2c -{ - INT32 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = (INT32)XMM(modrm & 0x7).f64[0]; - } else { // otherwise is a memory address - XMM_REG t; - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_LO64( ea, t); - src = (INT32)t.f64[0]; - } - STORE_REG32(modrm, (UINT32)src); - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtsd2si_r32_r128m64)() // Opcode f2 0f 2d -{ - INT32 src; - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - src = (INT32)XMM(modrm & 0x7).f64[0]; - } else { // otherwise is a memory address - XMM_REG t; - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_LO64( ea, t); - src = (INT32)t.f64[0]; - } - STORE_REG32(modrm, (UINT32)src); - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(sqrtsd_r128_r128m64)() // Opcode f2 0f 51 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s, d; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - XMM(d).f64[0]=sqrt(XMM(s).f64[0]); - } else { - XMM_REG src; - int d; - UINT32 ea = GetEA(modrm, 0, 16); - d=(modrm >> 3) & 0x7; - READXMM( ea, src); - XMM(d).f64[0]=sqrt(src.f64[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(addsd_r128_r128m64)() // Opcode f2 0f 58 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] + XMM(modrm & 0x7).f64[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] + src.f64[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(mulsd_r128_r128m64)() // Opcode f2 0f 59 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] * XMM(modrm & 0x7).f64[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] * src.f64[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cvtsd2ss_r128_r128m64)() // Opcode f2 0f 5a -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0] = XMM(modrm & 0x7).f64[0]; - } else { - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - READXMM_LO64( ea, s); - XMM((modrm >> 3) & 0x7).f[0] = s.f64[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(subsd_r128_r128m64)() // Opcode f2 0f 5c -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] - XMM(modrm & 0x7).f64[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] - src.f64[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(minsd_r128_r128m64)() // Opcode f2 0f 5d -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = sse_min_double(XMM((modrm >> 3) & 0x7).f64[0], XMM(modrm & 0x7).f64[0]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = sse_min_double(XMM((modrm >> 3) & 0x7).f64[0], src.f64[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(divsd_r128_r128m64)() // Opcode f2 0f 5e -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] / XMM(modrm & 0x7).f64[0]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = XMM((modrm >> 3) & 0x7).f64[0] / src.f64[0]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(maxsd_r128_r128m64)() // Opcode f2 0f 5f -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f64[0] = sse_max_double(XMM((modrm >> 3) & 0x7).f64[0], XMM(modrm & 0x7).f64[0]); - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f64[0] = sse_max_double(XMM((modrm >> 3) & 0x7).f64[0], src.f64[0]); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(haddps_r128_rm128)() // Opcode f2 0f 7c -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s, d; - float f1, f2, f3, f4; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - f1=XMM(d).f[0]+XMM(d).f[1]; - f2=XMM(d).f[2]+XMM(d).f[3]; - f3=XMM(s).f[0]+XMM(s).f[1]; - f4=XMM(s).f[2]+XMM(s).f[3]; - XMM(d).f[0]=f1; - XMM(d).f[1]=f2; - XMM(d).f[2]=f3; - XMM(d).f[3]=f4; - } else { - XMM_REG src; - int d; - float f1, f2; - UINT32 ea = GetEA(modrm, 0, 16); - d=(modrm >> 3) & 0x7; - READXMM( ea, src); - f1=XMM(d).f[0]+XMM(d).f[1]; - f2=XMM(d).f[2]+XMM(d).f[3]; - XMM(d).f[0]=f1; - XMM(d).f[1]=f2; - XMM(d).f[2]=src.f[0]+src.f[1]; - XMM(d).f[3]=src.f[2]+src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(hsubps_r128_rm128)() // Opcode f2 0f 7d -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s, d; - float f1, f2, f3, f4; - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - f1=XMM(d).f[0]-XMM(d).f[1]; - f2=XMM(d).f[2]-XMM(d).f[3]; - f3=XMM(s).f[0]-XMM(s).f[1]; - f4=XMM(s).f[2]-XMM(s).f[3]; - XMM(d).f[0]=f1; - XMM(d).f[1]=f2; - XMM(d).f[2]=f3; - XMM(d).f[3]=f4; - } else { - XMM_REG src; - int d; - float f1, f2; - UINT32 ea = GetEA(modrm, 0, 16); - d=(modrm >> 3) & 0x7; - READXMM( ea, src); - f1=XMM(d).f[0]-XMM(d).f[1]; - f2=XMM(d).f[2]-XMM(d).f[3]; - XMM(d).f[0]=f1; - XMM(d).f[1]=f2; - XMM(d).f[2]=src.f[0]-src.f[1]; - XMM(d).f[3]=src.f[2]-src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(cmpsd_r128_r128m64_i8)() // Opcode f2 0f c2 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - int s,d; - UINT8 imm8 = FETCH(); - s=modrm & 0x7; - d=(modrm >> 3) & 0x7; - sse_predicate_compare_double_scalar(imm8, XMM(d), XMM(s)); - } else { - int d; - XMM_REG s; - UINT32 ea = GetEA(modrm, 0, 8); - UINT8 imm8 = FETCH(); - READXMM_LO64( ea, s); - d=(modrm >> 3) & 0x7; - sse_predicate_compare_double_scalar(imm8, XMM(d), s); - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(addsubps_r128_rm128)() // Opcode f2 0f d0 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).f[0]=XMM((modrm >> 3) & 0x7).f[0] - XMM(modrm & 0x7).f[0]; - XMM((modrm >> 3) & 0x7).f[1]=XMM((modrm >> 3) & 0x7).f[1] + XMM(modrm & 0x7).f[1]; - XMM((modrm >> 3) & 0x7).f[2]=XMM((modrm >> 3) & 0x7).f[2] - XMM(modrm & 0x7).f[2]; - XMM((modrm >> 3) & 0x7).f[3]=XMM((modrm >> 3) & 0x7).f[3] + XMM(modrm & 0x7).f[3]; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).f[0]=XMM((modrm >> 3) & 0x7).f[0] - src.f[0]; - XMM((modrm >> 3) & 0x7).f[1]=XMM((modrm >> 3) & 0x7).f[1] + src.f[1]; - XMM((modrm >> 3) & 0x7).f[2]=XMM((modrm >> 3) & 0x7).f[2] - src.f[2]; - XMM((modrm >> 3) & 0x7).f[3]=XMM((modrm >> 3) & 0x7).f[3] + src.f[3]; - } - CYCLES(1); // TODO: correct cycle count -} - - void I386_OPS_BASE::SSEOP(movdq2q_r64_r128)() // Opcode f2 0f d6 -{ - UINT8 modrm = FETCH(); - MMXPROLOG(); - if( modrm >= 0xc0 ) { - MMX((modrm >> 3) & 0x7).q = XMM(modrm & 0x7).q[0]; - CYCLES(1); // TODO: correct cycle count - } else { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } -} - - void I386_OPS_BASE::SSEOP(cvtpd2dq_r128_rm128)() // Opcode f2 0f e6 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - XMM((modrm >> 3) & 0x7).i[0]=(INT32)XMM((modrm >> 3) & 0x7).f64[0]; - XMM((modrm >> 3) & 0x7).i[1]=(INT32)XMM((modrm >> 3) & 0x7).f64[1]; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } else { - XMM_REG src; - UINT32 ea = GetEA(modrm, 0, 16); - READXMM( ea, src); - XMM((modrm >> 3) & 0x7).i[0]=(INT32)src.f64[0]; - XMM((modrm >> 3) & 0x7).i[1]=(INT32)src.f64[1]; - XMM((modrm >> 3) & 0x7).q[1] = 0; - } - CYCLES(1); // TODO: correct cycle count -} - -void I386_OPS_BASE::SSEOP(lddqu_r128_m128)() // Opcode f2 0f f0 -{ - UINT8 modrm = FETCH(); - if( modrm >= 0xc0 ) { - // unsupported by cpu - CYCLES(1); // TODO: correct cycle count - } else { - UINT32 ea = GetEA(modrm, 0, 16); - READXMM(ea, XMM((modrm >> 3) & 0x7)); - } -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/readme_takeda.txt b/source/src/vm/libcpu_newdev/libcpu_i386/readme_takeda.txt deleted file mode 100644 index 25b3acb5b..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/readme_takeda.txt +++ /dev/null @@ -1,5 +0,0 @@ -Based on MAME 0.152. -Fixes in MAME 0.154 to 0.204 are applied. - -cycle_table_rm/pm are changed from dynamic array to static array. -convert char to _TCHAR in disassembler. diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/vtlb.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/vtlb.cpp deleted file mode 100644 index 463013066..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/vtlb.cpp +++ /dev/null @@ -1,297 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - vtlb.c - - Generic virtual TLB implementation. - -***************************************************************************/ - -#include "i386_opdef.h" - -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define PRINTF_TLB (0) - - -/*************************************************************************** - INITIALIZATION/TEARDOWN -***************************************************************************/ - -/*------------------------------------------------- - vtlb_alloc - allocate a new VTLB for the - given CPU --------------------------------------------------*/ - -vtlb_state *I386_OPS_BASE::vtlb_alloc(void *cpu, address_spacenum space, int fixed_entries, int dynamic_entries) -{ - vtlb_state *vtlb; - - /* allocate memory for the core structure */ - vtlb = (vtlb_state *)calloc(1, sizeof(vtlb_state)); - - /* fill in CPU information */ - vtlb->cpudevice = cpu; - vtlb->space = space; - vtlb->dynamic = dynamic_entries; - vtlb->fixed = fixed_entries; -// const address_space_config *spaceconfig = device_get_space_config(*cpu, space); -// assert(spaceconfig != NULL); -// vtlb->pageshift = spaceconfig->m_page_shift; -// vtlb->addrwidth = spaceconfig->m_logaddr_width; - /* for i386 */ - vtlb->pageshift = 12; - vtlb->addrwidth = 32; - - /* validate CPU information */ - assert((1 << vtlb->pageshift) > VTLB_FLAGS_MASK); - assert(vtlb->addrwidth > vtlb->pageshift); - - /* allocate the entry array */ - vtlb->live = (offs_t *)calloc(fixed_entries + dynamic_entries, sizeof(offs_t)); -// cpu->save_pointer(NAME(vtlb->live), fixed_entries + dynamic_entries, space); - - /* allocate the lookup table */ - vtlb->table = (vtlb_entry *)calloc((size_t) 1 << (vtlb->addrwidth - vtlb->pageshift), sizeof(vtlb_entry)); -// cpu->save_pointer(NAME(vtlb->table), 1 << (vtlb->addrwidth - vtlb->pageshift), space); - - /* allocate the fixed page count array */ - if (fixed_entries > 0) - { - vtlb->fixedpages = (int *)calloc(fixed_entries, sizeof(int)); -// cpu->save_pointer(NAME(vtlb->fixedpages), fixed_entries, space); - } - return vtlb; -} - - -/*------------------------------------------------- - vtlb_free - free an allocated VTLB --------------------------------------------------*/ - -void I386_OPS_BASE::vtlb_free(vtlb_state *vtlb) -{ - /* free the fixed pages if allocated */ - if (vtlb->fixedpages != NULL) - free(vtlb->fixedpages); - - /* free the table and array if they exist */ - if (vtlb->live != NULL) - free(vtlb->live); - if (vtlb->table != NULL) - free(vtlb->table); - - /* and then the VTLB object itself */ - free(vtlb); -} - - - -/*************************************************************************** - FILLING -***************************************************************************/ - -/*------------------------------------------------- - vtlb_fill - rcalled by the CPU core in - response to an unmapped access --------------------------------------------------*/ - -int I386_OPS_BASE::vtlb_fill(vtlb_state *vtlb, offs_t address, int intention) -{ - offs_t tableindex = address >> vtlb->pageshift; - vtlb_entry entry = vtlb->table[tableindex]; - offs_t taddress; - -// if (PRINTF_TLB) -// printf("vtlb_fill: %08X(%X) ... ", address, intention); - - /* should not be called here if the entry is in the table already */ -// assert((entry & (1 << intention)) == 0); - - /* if we have no dynamic entries, we always fail */ - if (vtlb->dynamic == 0) - { -// if (PRINTF_TLB) -// printf("failed: no dynamic entries\n"); - return FALSE; - } - - /* ask the CPU core to translate for us */ - taddress = address; -// if (!vtlb->cpudevice->translate(vtlb->space, intention, taddress)) - if (!CPU_TRANSLATE_NAME(i386)(vtlb->cpudevice, vtlb->space, intention, &taddress)) - { -// if (PRINTF_TLB) -// printf("failed: no translation\n"); - return FALSE; - } - - /* if this is the first successful translation for this address, allocate a new entry */ - if ((entry & VTLB_FLAGS_MASK) == 0) - { - int liveindex = vtlb->dynindex++ % vtlb->dynamic; - - /* if an entry already exists at this index, free it */ - if (vtlb->live[liveindex] != 0) - vtlb->table[vtlb->live[liveindex] - 1] = 0; - - /* claim this new entry */ - vtlb->live[liveindex] = tableindex + 1; - - /* form a new blank entry */ - entry = (taddress >> vtlb->pageshift) << vtlb->pageshift; - entry |= VTLB_FLAG_VALID; - -// if (PRINTF_TLB) -// printf("success (%08X), new entry\n", taddress); - } - - /* otherwise, ensure that different intentions do not produce different addresses */ - else - { - assert((entry >> vtlb->pageshift) == (taddress >> vtlb->pageshift)); - assert(entry & VTLB_FLAG_VALID); - -// if (PRINTF_TLB) -// printf("success (%08X), existing entry\n", taddress); - } - - /* add the intention to the list of valid intentions and store */ - entry |= 1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)); - vtlb->table[tableindex] = entry; - return TRUE; -} - - -/*------------------------------------------------- - vtlb_load - load a fixed VTLB entry --------------------------------------------------*/ - -void I386_OPS_BASE::vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value) -{ - offs_t tableindex = address >> vtlb->pageshift; - int liveindex = vtlb->dynamic + entrynum; - int pagenum; - - /* must be in range */ - assert(entrynum >= 0 && entrynum < vtlb->fixed); - -// if (PRINTF_TLB) -// printf("vtlb_load %d for %d pages at %08X == %08X\n", entrynum, numpages, address, value); - - /* if an entry already exists at this index, free it */ - if (vtlb->live[liveindex] != 0) - { - int pagecount = vtlb->fixedpages[entrynum]; - int oldtableindex = vtlb->live[liveindex] - 1; - for (pagenum = 0; pagenum < pagecount; pagenum++) - vtlb->table[oldtableindex + pagenum] = 0; - } - - /* claim this new entry */ - vtlb->live[liveindex] = tableindex + 1; - - /* store the raw value, making sure the "fixed" flag is set */ - value |= VTLB_FLAG_FIXED; - vtlb->fixedpages[entrynum] = numpages; - for (pagenum = 0; pagenum < numpages; pagenum++) - vtlb->table[tableindex + pagenum] = value + (pagenum << vtlb->pageshift); -} - -/*------------------------------------------------- - vtlb_dynload - load a dynamic VTLB entry --------------------------------------------------*/ - -void I386_OPS_BASE::vtlb_dynload(vtlb_state *vtlb, UINT32 index, offs_t address, vtlb_entry value) -{ - vtlb_entry entry = vtlb->table[index]; - - if (vtlb->dynamic == 0) - { -// if (PRINTF_TLB) -// printf("failed: no dynamic entries\n"); - return; - } - - int liveindex = vtlb->dynindex++ % vtlb->dynamic; - /* is entry already live? */ - if (!(entry & VTLB_FLAG_VALID)) - { - /* if an entry already exists at this index, free it */ - if (vtlb->live[liveindex] != 0) - vtlb->table[vtlb->live[liveindex] - 1] = 0; - - /* claim this new entry */ - vtlb->live[liveindex] = index + 1; - } - /* form a new blank entry */ - entry = (address >> vtlb->pageshift) << vtlb->pageshift; - entry |= VTLB_FLAG_VALID | value; - -// if (PRINTF_TLB) -// printf("success (%08X), new entry\n", address); - - vtlb->table[index] = entry; -} - -/*************************************************************************** - FLUSHING -***************************************************************************/ - -/*------------------------------------------------- - vtlb_flush_dynamic - flush all knowledge - from the dynamic part of the VTLB --------------------------------------------------*/ - -void I386_OPS_BASE::vtlb_flush_dynamic(vtlb_state *vtlb) -{ - int liveindex; - -// if (PRINTF_TLB) -// printf("vtlb_flush_dynamic\n"); - - /* loop over live entries and release them from the table */ - for (liveindex = 0; liveindex < vtlb->dynamic; liveindex++) - if (vtlb->live[liveindex] != 0) - { - offs_t tableindex = vtlb->live[liveindex] - 1; - vtlb->table[tableindex] = 0; - vtlb->live[liveindex] = 0; - } -} - - -/*------------------------------------------------- - vtlb_flush_address - flush knowledge of a - particular address from the VTLB --------------------------------------------------*/ - -void I386_OPS_BASE::vtlb_flush_address(vtlb_state *vtlb, offs_t address) -{ - offs_t tableindex = address >> vtlb->pageshift; - -// if (PRINTF_TLB) -// printf("vtlb_flush_address %08X\n", address); - - /* free the entry in the table; for speed, we leave the entry in the live array */ - vtlb->table[tableindex] = 0; -} - - - -/*************************************************************************** - ACCESSORS -***************************************************************************/ - -/*------------------------------------------------- - vtlb_table - return a pointer to the base of - the linear VTLB lookup table --------------------------------------------------*/ - -const vtlb_entry *I386_OPS_BASE::vtlb_table(vtlb_state *vtlb) -{ - return vtlb->table; -} diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/vtlb.h b/source/src/vm/libcpu_newdev/libcpu_i386/vtlb.h deleted file mode 100644 index 2c9271494..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/vtlb.h +++ /dev/null @@ -1,43 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - vtlb.h - - Generic virtual TLB implementation. - -***************************************************************************/ - -#pragma once - -#ifndef __LIB_I386_VTLB_H__ -#define __LIB_I386_VTLB_H__ - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -#define VTLB_FLAGS_MASK 0xff - -#define VTLB_READ_ALLOWED 0x01 /* (1 << TRANSLATE_READ) */ -#define VTLB_WRITE_ALLOWED 0x02 /* (1 << TRANSLATE_WRITE) */ -#define VTLB_FETCH_ALLOWED 0x04 /* (1 << TRANSLATE_FETCH) */ -#define VTLB_FLAG_VALID 0x08 -#define VTLB_USER_READ_ALLOWED 0x10 /* (1 << TRANSLATE_READ_USER) */ -#define VTLB_USER_WRITE_ALLOWED 0x20 /* (1 << TRANSLATE_WRITE_USER) */ -#define VTLB_USER_FETCH_ALLOWED 0x40 /* (1 << TRANSLATE_FETCH_USER) */ -#define VTLB_FLAG_FIXED 0x80 - - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -/* represents an entry in the VTLB */ -typedef UINT32 vtlb_entry; - -/* opaque structure describing VTLB state */ -//struct vtlb_state; - -#endif /* __VTLB_H__ */ diff --git a/source/src/vm/libcpu_newdev/libcpu_i386/x87ops.cpp b/source/src/vm/libcpu_newdev/libcpu_i386/x87ops.cpp deleted file mode 100644 index 46e38c35e..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_i386/x87ops.cpp +++ /dev/null @@ -1,4996 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Philp Bennett -/*************************************************************************** - - x87 FPU emulation - - TODO: - - 80-bit precision for F2XM1, FYL2X, FPATAN - - Figure out why SoftFloat trig extensions produce bad values - - Cycle counts for all processors (currently using 486 counts) - - Precision-dependent cycle counts for divide instructions - - Last instruction, operand pointers etc. - - Fix FLDENV, FSTENV, FSAVE, FRSTOR and FPREM - - Status word C2 updates to reflect round up/down - - Handling of invalid and denormal numbers - - Remove redundant operand checks - - Exceptions - -***************************************************************************/ - -#include - -#include "./i386_opdef.h" -//extern "C" { -#include "../libcpu_softfloat/mamesf.h" -#include "../libcpu_softfloat/milieu.h" -#include "../libcpu_softfloat/softfloat.h" -#include "../libcpu_softfloat/fyl2x.c" -#include "../libcpu_softfloat/fsincos.c" -#include "../libcpu_softfloat/softfloat.c" - -//}; - -#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;} -#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;} - -/************************************* - * - * Constants - * - *************************************/ - -//const floatx80 I386_OPS_BASE::ffx80_zero = { 0x0000, U64(0x0000000000000000) }; -//const floatx80 I386_OPS_BASE::ffx80_one = { 0x3fff, U64(0x8000000000000000) }; - -//const floatx80 I386_OPS_BASE::ffx80_ninf = { 0xffff, U64(0x8000000000000000) }; -//const floatx80 I386_OPS_BASE::ffx80_inan = { 0xffff, U64(0xc000000000000000) }; - -/************************************* - * - * SoftFloat helpers - * - *************************************/ - -extern "C" { -// extern flag floatx80_is_nan( floatx80 a ); -} - -void I386_OPS_BASE::x87_write_stack( int i, floatx80 value, int update_tag) -{ - ST(i) = value; - - if (update_tag) - { - int tag; - - if (floatx80_is_zero(value)) - { - tag = X87_TW_ZERO; - } - else if (floatx80_is_inf(value) || floatx80_is_nan(value)) - { - tag = X87_TW_SPECIAL; - } - else - { - tag = X87_TW_VALID; - } - - x87_set_tag( ST_TO_PHYS(i), tag); - } -} - -int I386_OPS_BASE::x87_inc_stack() -{ - int ret = 1; - - // Check for stack underflow - if (X87_IS_ST_EMPTY(0)) - { - ret = 0; - x87_set_stack_underflow(); - - // Don't update the stack if the exception is unmasked - if (~cpustate->x87_cw & X87_CW_IM) - return ret; - } - - x87_set_tag( ST_TO_PHYS(0), X87_TW_EMPTY); - x87_set_stack_top( ST_TO_PHYS(1)); - return ret; -} - -int I386_OPS_BASE::x87_dec_stack() -{ - int ret = 1; - - // Check for stack overflow - if (!X87_IS_ST_EMPTY(7)) - { - ret = 0; - x87_set_stack_overflow(); - - // Don't update the stack if the exception is unmasked - if (~cpustate->x87_cw & X87_CW_IM) - return ret; - } - - x87_set_stack_top( ST_TO_PHYS(7)); - return ret; -} - - -/************************************* - * - * Exception handling - * - *************************************/ - -int I386_OPS_BASE::x87_check_exceptions() -{ - /* Update the exceptions from SoftFloat */ - if (float_exception_flags & float_flag_invalid) - { - cpustate->x87_sw |= X87_SW_IE; - float_exception_flags &= ~float_flag_invalid; - } - if (float_exception_flags & float_flag_overflow) - { - cpustate->x87_sw |= X87_SW_OE; - float_exception_flags &= ~float_flag_overflow; - } - if (float_exception_flags & float_flag_underflow) - { - cpustate->x87_sw |= X87_SW_UE; - float_exception_flags &= ~float_flag_underflow; - } - if (float_exception_flags & float_flag_inexact) - { - cpustate->x87_sw |= X87_SW_PE; - float_exception_flags &= ~float_flag_inexact; - } - - if ((cpustate->x87_sw & ~cpustate->x87_cw) & 0x3f) - { - // cpustate->device->execute().set_input_line(INPUT_LINE_FERR, RAISE_LINE); - logerror("Unmasked x87 exception (CW:%.4x, SW:%.4x)\n", cpustate->x87_cw, cpustate->x87_sw); - // interrupt handler - if (!(cpustate->x87_cw & X87_CW_IEM)) { cpustate->x87_sw |= X87_SW_ES; /*ferr_handler(cpustate, 1);*/ } - - if (cpustate->cr[0] & 0x20) // FIXME: 486 and up only - { - cpustate->ext = 1; - i386_trap( FAULT_MF, 0, 0); - } - return 0; - } - - return 1; -} - -void I386_OPS_BASE::x87_reset() -{ - x87_write_cw( 0x0037f); - - cpustate->x87_sw = 0; - cpustate->x87_tw = 0xffff; - - // TODO: FEA=0, FDS=0, FIP=0 FOP=0 FCS=0 - cpustate->x87_data_ptr = 0; - cpustate->x87_inst_ptr = 0; - cpustate->x87_opcode = 0; - -// ferr_handler(cpustate, 0); -} - - -/************************************* - * - * Core arithmetic - * - *************************************/ - -floatx80 I386_OPS_BASE::x87_add( floatx80 a, floatx80 b) -{ - floatx80 result = { 0 }; - - switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) - { - case X87_CW_PC_SINGLE: - { - float32 a32 = floatx80_to_float32(a); - float32 b32 = floatx80_to_float32(b); - result = float32_to_floatx80(float32_add(a32, b32)); - break; - } - case X87_CW_PC_DOUBLE: - { - float64 a64 = floatx80_to_float64(a); - float64 b64 = floatx80_to_float64(b); - result = float64_to_floatx80(float64_add(a64, b64)); - break; - } - case X87_CW_PC_EXTEND: - { - result = floatx80_add(a, b); - break; - } - } - - return result; -} - -floatx80 I386_OPS_BASE::x87_sub( floatx80 a, floatx80 b) -{ - floatx80 result = { 0 }; - - switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) - { - case X87_CW_PC_SINGLE: - { - float32 a32 = floatx80_to_float32(a); - float32 b32 = floatx80_to_float32(b); - result = float32_to_floatx80(float32_sub(a32, b32)); - break; - } - case X87_CW_PC_DOUBLE: - { - float64 a64 = floatx80_to_float64(a); - float64 b64 = floatx80_to_float64(b); - result = float64_to_floatx80(float64_sub(a64, b64)); - break; - } - case X87_CW_PC_EXTEND: - { - result = floatx80_sub(a, b); - break; - } - } - - return result; -} - -floatx80 I386_OPS_BASE::x87_mul( floatx80 a, floatx80 b) -{ - floatx80 val = { 0 }; - - switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) - { - case X87_CW_PC_SINGLE: - { - float32 a32 = floatx80_to_float32(a); - float32 b32 = floatx80_to_float32(b); - val = float32_to_floatx80(float32_mul(a32, b32)); - break; - } - case X87_CW_PC_DOUBLE: - { - float64 a64 = floatx80_to_float64(a); - float64 b64 = floatx80_to_float64(b); - val = float64_to_floatx80(float64_mul(a64, b64)); - break; - } - case X87_CW_PC_EXTEND: - { - val = floatx80_mul(a, b); - break; - } - } - - return val; -} - - -floatx80 I386_OPS_BASE::x87_div( floatx80 a, floatx80 b) -{ - floatx80 val = { 0 }; - - switch ((cpustate->x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) - { - case X87_CW_PC_SINGLE: - { - float32 a32 = floatx80_to_float32(a); - float32 b32 = floatx80_to_float32(b); - val = float32_to_floatx80(float32_div(a32, b32)); - break; - } - case X87_CW_PC_DOUBLE: - { - float64 a64 = floatx80_to_float64(a); - float64 b64 = floatx80_to_float64(b); - val = float64_to_floatx80(float64_div(a64, b64)); - break; - } - case X87_CW_PC_EXTEND: - { - val = floatx80_div(a, b); - break; - } - } - return val; -} - - -/************************************* - * - * Instructions - * - *************************************/ - -/************************************* - * - * Add - * - *************************************/ - -void I386_OPS_BASE::x87_fadd_m32real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT32 m32real = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = float32_to_floatx80(m32real); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_add( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fadd_m64real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT64 m64real = READ64( ea); - - floatx80 a = ST(0); - floatx80 b = float64_to_floatx80(m64real); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_add( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fadd_st_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_add( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fadd_sti_st( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_add( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( i, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_faddp( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_add( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - x87_inc_stack(); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fiadd_m32int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT32 m32int= READ32( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m32int); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_add( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 19); -} - -void I386_OPS_BASE::x87_fiadd_m16int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT16 m16int= READ16(ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m16int); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_add( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 20); -} - - -/************************************* - * - * Subtract - * - *************************************/ - -void I386_OPS_BASE::x87_fsub_m32real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT32 m32real = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = float32_to_floatx80(m32real); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsub_m64real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT64 m64real = READ64( ea); - - floatx80 a = ST(0); - floatx80 b = float64_to_floatx80(m64real); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsub_st_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsub_sti_st( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(i); - floatx80 b = ST(0); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( i, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsubp( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(i); - floatx80 b = ST(0); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - x87_inc_stack(); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fisub_m32int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT32 m32int = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m32int); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 19); -} - -void I386_OPS_BASE::x87_fisub_m16int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT16 m16int = READ16( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m16int); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 20); -} - - -/************************************* - * - * Reverse Subtract - * - *************************************/ - -void I386_OPS_BASE::x87_fsubr_m32real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT32 m32real = READ32( ea); - - floatx80 a = float32_to_floatx80(m32real); - floatx80 b = ST(0); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsubr_m64real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT64 m64real = READ64( ea); - - floatx80 a = float64_to_floatx80(m64real); - floatx80 b = ST(0); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsubr_st_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(i); - floatx80 b = ST(0); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsubr_sti_st( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( i, result, TRUE); - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fsubrp( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - x87_inc_stack(); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fisubr_m32int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT32 m32int = READ32( ea); - - floatx80 a = int32_to_floatx80(m32int); - floatx80 b = ST(0); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 19); -} - -void I386_OPS_BASE::x87_fisubr_m16int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT16 m16int = READ16( ea); - - floatx80 a = int32_to_floatx80(m16int); - floatx80 b = ST(0); - - if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_sub( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 20); -} - - -/************************************* - * - * Divide - * - *************************************/ - -void I386_OPS_BASE::x87_fdiv_m32real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT32 m32real = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = float32_to_floatx80(m32real); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fdiv_m64real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT64 m64real = READ64( ea); - - floatx80 a = ST(0); - floatx80 b = float64_to_floatx80(m64real); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fdiv_st_sti( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( 0, result, TRUE); - } - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::I386_OPS_BASE::x87_fdiv_sti_st( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(i); - floatx80 b = ST(0); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - } - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fdivp( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(i); - floatx80 b = ST(0); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - x87_inc_stack(); - } - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fidiv_m32int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT32 m32int = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m32int); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fidiv_m16int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT16 m16int = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m16int); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - - -/************************************* - * - * Reverse Divide - * - *************************************/ - -void I386_OPS_BASE::x87_fdivr_m32real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT32 m32real = READ32( ea); - - floatx80 a = float32_to_floatx80(m32real); - floatx80 b = ST(0); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fdivr_m64real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT64 m64real = READ64( ea); - - floatx80 a = float64_to_floatx80(m64real); - floatx80 b = ST(0); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fdivr_st_sti( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(i); - floatx80 b = ST(0); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( 0, result, TRUE); - } - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fdivr_sti_st( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - } - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fdivrp( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - x87_inc_stack(); - } - - // 73, 62, 35 - CYCLES( 73); -} - - -void I386_OPS_BASE::x87_fidivr_m32int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT32 m32int = READ32( ea); - - floatx80 a = int32_to_floatx80(m32int); - floatx80 b = ST(0); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - -void I386_OPS_BASE::x87_fidivr_m16int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT16 m16int = READ32( ea); - - floatx80 a = int32_to_floatx80(m16int); - floatx80 b = ST(0); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_div( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - // 73, 62, 35 - CYCLES( 73); -} - - -/************************************* - * - * Multiply - * - *************************************/ - -void I386_OPS_BASE::x87_fmul_m32real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT32 m32real = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = float32_to_floatx80(m32real); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_mul( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 11); -} - -void I386_OPS_BASE::x87_fmul_m64real( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT64 m64real = READ64( ea); - - floatx80 a = ST(0); - floatx80 b = float64_to_floatx80(m64real); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_mul( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 14); -} - -void I386_OPS_BASE::x87_fmul_st_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_mul( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 16); -} - -void I386_OPS_BASE::x87_fmul_sti_st( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_mul( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( i, result, TRUE); - - CYCLES( 16); -} - -void I386_OPS_BASE::x87_fmulp( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_mul( a, b); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, result, TRUE); - x87_inc_stack(); - } - - CYCLES( 16); -} - -void I386_OPS_BASE::x87_fimul_m32int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT32 m32int = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m32int); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_mul( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 22); -} - -void I386_OPS_BASE::x87_fimul_m16int( UINT8 modrm) -{ - floatx80 result; - - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - INT16 m16int = READ16( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m16int); - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = x87_mul( a, b); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 22); -} - - -/************************************* -* -* Conditional Move -* -*************************************/ - -void I386_OPS_BASE::x87_fcmovb_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (cpustate->CF == 1) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcmove_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (cpustate->ZF == 1) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcmovbe_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if ((cpustate->CF | cpustate->ZF) == 1) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcmovu_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (cpustate->PF == 1) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcmovnb_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (cpustate->CF == 0) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcmovne_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (cpustate->ZF == 0) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcmovnbe_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if ((cpustate->CF == 0) && (cpustate->ZF == 0)) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcmovnu_sti( UINT8 modrm) -{ - floatx80 result; - int i = modrm & 7; - - if (cpustate->PF == 0) - { - if (X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - result = ST(i); - - if (x87_check_exceptions()) - { - ST(0) = result; - } - } - - CYCLES( 4); -} - -/************************************* - * - * Miscellaneous arithmetic - * - *************************************/ - -/* D9 F8 */ -void I386_OPS_BASE::x87_fprem( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a0 = ST(0); // dividend - floatx80 b1 = ST(1); // divider - - floatx80 a0_abs = packFloatx80(0, (a0.high & 0x7FFF), a0.low); - floatx80 b1_abs = packFloatx80(0, (b1.high & 0x7FFF), b1.low); - cpustate->x87_sw &= ~X87_SW_C2; - - //int d=extractFloatx80Exp(a0)-extractFloatx80Exp(b1); - int d = (a0.high & 0x7FFF) - (b1.high & 0x7FFF); - if (d < 64) { - floatx80 t=floatx80_div(a0_abs, b1_abs); - int64 q = floatx80_to_int64_round_to_zero(t); - floatx80 qf = int64_to_floatx80(q); - floatx80 tt = floatx80_mul(b1_abs, qf); - result = floatx80_sub(a0_abs, tt); - result.high |= a0.high & 0x8000; - // C2 already 0 - cpustate->x87_sw &= ~(X87_SW_C0|X87_SW_C3|X87_SW_C1); - if (q & 1) - cpustate->x87_sw |= X87_SW_C1; - if (q & 2) - cpustate->x87_sw |= X87_SW_C3; - if (q & 4) - cpustate->x87_sw |= X87_SW_C0; - } - else { - cpustate->x87_sw |= X87_SW_C2; - int n = 63; - int e = 1 << (d - n); - floatx80 ef = int32_to_floatx80(e); - floatx80 t=floatx80_div(a0, b1); - floatx80 td = floatx80_div(t, ef); - int64 qq = floatx80_to_int64_round_to_zero(td); - floatx80 qqf = int64_to_floatx80(qq); - floatx80 tt = floatx80_mul(b1, qqf); - floatx80 ttt = floatx80_mul(tt, ef); - result = floatx80_sub(a0, ttt); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 84); -} - -void I386_OPS_BASE::x87_fprem1( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 a = ST(0); - floatx80 b = ST(1); - - cpustate->x87_sw &= ~X87_SW_C2; - - // TODO: Implement Cx bits - result = floatx80_rem(a, b); - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 94); -} - -void I386_OPS_BASE::x87_fsqrt( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 value = ST(0); - - if ((!floatx80_is_zero(value) && (value.high & 0x8000)) || - floatx80_is_denormal(value)) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - result = floatx80_sqrt(value); - } - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 8); -} - -/************************************* - * - * Trigonometric - * - *************************************/ - -void I386_OPS_BASE::x87_f2xm1( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - // TODO: Inaccurate - double x = fx80_to_double(ST(0)); - double res = pow(2.0, x) - 1; - result = double_to_fx80(res); - } - - if (x87_check_exceptions()) - { - x87_write_stack( 0, result, TRUE); - } - - CYCLES( 242); -} - -void I386_OPS_BASE::x87_fyl2x( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 x = ST(0); - floatx80 y = ST(1); - - if (x.high & 0x8000) - { - cpustate->x87_sw |= X87_SW_IE; - result = fx80_inan; - } - else - { - // TODO: Inaccurate - double d64 = fx80_to_double(x); - double l2x = log(d64)/log(2.0); - result = floatx80_mul(double_to_fx80(l2x), y); - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( 1, result, TRUE); - x87_inc_stack(); - } - - CYCLES( 250); -} - -void I386_OPS_BASE::x87_fyl2xp1( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - floatx80 x = ST(0); - floatx80 y = ST(1); - - // TODO: Inaccurate - double d64 = fx80_to_double(x); - double l2x1 = log(d64 + 1.0)/log(2.0); - result = floatx80_mul(double_to_fx80(l2x1), y); - } - - if (x87_check_exceptions()) - { - x87_write_stack( 1, result, TRUE); - x87_inc_stack(); - } - - CYCLES( 313); -} - -/* D9 F2 if 8087 0 < angle < pi/4 */ -void I386_OPS_BASE::x87_fptan( UINT8 modrm) -{ - floatx80 result1, result2; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result1 = fx80_inan; - result2 = fx80_inan; - } - else if (!X87_IS_ST_EMPTY(7)) - { - x87_set_stack_overflow(); - result1 = fx80_inan; - result2 = fx80_inan; - } - else - { - result1 = ST(0); - result2 = fx80_one; - -#if 1 // TODO: Function produces bad values - if (floatx80_ftan(result1) != -1) - cpustate->x87_sw &= ~X87_SW_C2; - else - cpustate->x87_sw |= X87_SW_C2; -#else - double x = fx80_to_double(result1); - x = tan(x); - result1 = double_to_fx80(x); - - cpustate->x87_sw &= ~X87_SW_C2; -#endif - } - - if (x87_check_exceptions()) - { - x87_write_stack( 0, result1, TRUE); - x87_dec_stack(); - x87_write_stack( 0, result2, TRUE); - } - - CYCLES( 244); -} - -/* D9 F3 */ -void I386_OPS_BASE::x87_fpatan( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - // TODO: Inaccurate - double val = atan2(fx80_to_double(ST(1)) , fx80_to_double(ST(0))); - result = double_to_fx80(val); - } - - if (x87_check_exceptions()) - { - x87_write_stack( 1, result, TRUE); - x87_inc_stack(); - } - - CYCLES( 289); -} - -/* D9 FE 387 only */ -void I386_OPS_BASE::x87_fsin( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - result = ST(0); - -#if 1 // TODO: Function produces bad values Result checked - if (floatx80_fsin(result) != -1) - cpustate->x87_sw &= ~X87_SW_C2; - else - cpustate->x87_sw |= X87_SW_C2; -#else - double x = fx80_to_double(result); - x = sin(x); - result = double_to_fx80(x); - - cpustate->x87_sw &= ~X87_SW_C2; -#endif - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 241); -} - -void I386_OPS_BASE::x87_fcos( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - result = ST(0); - -#if 1 // TODO: Function produces bad values to check! - if (floatx80_fcos(result) != -1) - cpustate->x87_sw &= ~X87_SW_C2; - else - cpustate->x87_sw |= X87_SW_C2; -#else - double x = fx80_to_double(result); - x = cos(x); - result = double_to_fx80(x); - - cpustate->x87_sw &= ~X87_SW_C2; -#endif - } - - if (x87_check_exceptions()) - x87_write_stack( 0, result, TRUE); - - CYCLES( 241); -} - -extern "C" { - //extern int sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a); -} - -/* D9 FB 387 only */ -void I386_OPS_BASE::x87_fsincos( UINT8 modrm) -{ - floatx80 s_result, c_result; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - s_result = c_result = fx80_inan; - } - else if (!X87_IS_ST_EMPTY(7)) - { - x87_set_stack_overflow(); - s_result = c_result = fx80_inan; - } - else - { - - s_result = c_result = ST(0); - -#if 0 // TODO: Function produces bad values - if (sf_fsincos(s_result, &s_result, &c_result) != -1) - cpustate->x87_sw &= ~X87_SW_C2; - else - cpustate->x87_sw |= X87_SW_C2; -#else - double s = fx80_to_double(s_result); - double c = fx80_to_double(c_result); - s = sin(s); - c = cos(c); - - s_result = double_to_fx80(s); - c_result = double_to_fx80(c); - - cpustate->x87_sw &= ~X87_SW_C2; -#endif - } - - if (x87_check_exceptions()) - { - x87_write_stack( 0, s_result, TRUE); - x87_dec_stack(); - x87_write_stack( 0, c_result, TRUE); - } - - CYCLES( 291); -} - - -/************************************* - * - * Load data - * - *************************************/ - -void I386_OPS_BASE::x87_fld_m32real( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 0, 4); - if (x87_dec_stack()) - { - UINT32 m32real = READ32( ea); - - value = float32_to_floatx80(m32real); - - cpustate->x87_sw &= ~X87_SW_C1; - - if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value)) - { - cpustate->x87_sw |= X87_SW_IE; - value = fx80_inan; - } - } - else - { - value = fx80_inan; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fld_m64real( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 0, 8); - if (x87_dec_stack()) - { - UINT64 m64real = READ64( ea); - - value = float64_to_floatx80(m64real); - - cpustate->x87_sw &= ~X87_SW_C1; - - if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value)) - { - cpustate->x87_sw |= X87_SW_IE; - value = fx80_inan; - } - } - else - { - value = fx80_inan; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fld_m80real( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 0, 10); - if (x87_dec_stack()) - { - cpustate->x87_sw &= ~X87_SW_C1; - value = READ80( ea); - } - else - { - value = fx80_inan; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 6); -} - -void I386_OPS_BASE::x87_fld_sti( UINT8 modrm) -{ - floatx80 value; - - if (x87_dec_stack()) - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST((modrm + 1) & 7); - } - else - { - value = fx80_inan; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fild_m16int( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 0, 2); - if (!x87_dec_stack()) - { - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - INT16 m16int = READ16( ea); - value = int32_to_floatx80(m16int); - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 13); -} - -void I386_OPS_BASE::x87_fild_m32int( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 0, 4); - if (!x87_dec_stack()) - { - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - INT32 m32int = READ32( ea); - value = int32_to_floatx80(m32int); - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 9); -} - -void I386_OPS_BASE::x87_fild_m64int( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 0, 8); - if (!x87_dec_stack()) - { - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - INT64 m64int = READ64( ea); - value = int64_to_floatx80(m64int); - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 10); -} - -void I386_OPS_BASE::x87_fbld( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 0, 10); - if (!x87_dec_stack()) - { - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - UINT64 m64val = 0; - UINT16 sign; - - value = READ80( ea); - - sign = value.high & 0x8000; - m64val += ((value.high >> 4) & 0xf) * 10; - m64val += ((value.high >> 0) & 0xf); - - for (int i = 60; i >= 0; i -= 4) - { - m64val *= 10; - m64val += (value.low >> i) & 0xf; - } - - value = int64_to_floatx80(m64val); - value.high |= sign; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 75); -} - - -/************************************* - * - * Store data - * - *************************************/ - -void I386_OPS_BASE::x87_fst_m32real( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 1, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - } - - if (x87_check_exceptions()) - { - UINT32 m32real = floatx80_to_float32(value); - WRITE32( ea, m32real); - } - - CYCLES( 7); -} - -void I386_OPS_BASE::x87_fst_m64real( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 1, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - } - - if (x87_check_exceptions()) - { - UINT64 m64real = floatx80_to_float64(value); - WRITE64( ea, m64real); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fst_sti( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 value; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - } - - if (x87_check_exceptions()) - x87_write_stack( i, value, TRUE); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fstp_m32real( UINT8 modrm) -{ - floatx80 value; - - UINT32 ea = GetEA( modrm, 1, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - } - - if (x87_check_exceptions()) - { - UINT32 m32real = floatx80_to_float32(value); - WRITE32( ea, m32real); - x87_inc_stack(); - } - - CYCLES( 7); -} - -void I386_OPS_BASE::x87_fstp_m64real( UINT8 modrm) -{ - floatx80 value; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - } - - - UINT32 ea = GetEA( modrm, 1, 8); - if (x87_check_exceptions()) - { - UINT64 m64real = floatx80_to_float64(value); - WRITE64( ea, m64real); - x87_inc_stack(); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fstp_m80real( UINT8 modrm) -{ - floatx80 value; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - } - - UINT32 ea = GetEA( modrm, 1, 10); - if (x87_check_exceptions()) - { - WRITE80( ea, value); - x87_inc_stack(); - } - - CYCLES( 6); -} - -void I386_OPS_BASE::x87_fstp_sti( UINT8 modrm) -{ - int i = modrm & 7; - floatx80 value; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - } - - if (x87_check_exceptions()) - { - x87_write_stack( i, value, TRUE); - x87_inc_stack(); - } - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fist_m16int( UINT8 modrm) -{ - INT16 m16int; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - m16int = -32768; - } - else - { - floatx80 fx80 = floatx80_round_to_int(ST(0)); - - floatx80 lowerLim = int32_to_floatx80(-32768); - floatx80 upperLim = int32_to_floatx80(32767); - - cpustate->x87_sw &= ~X87_SW_C1; - - if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) - m16int = floatx80_to_int32(fx80); - else - m16int = -32768; - } - - UINT32 ea = GetEA( modrm, 1, 2); - if (x87_check_exceptions()) - { - WRITE16( ea, m16int); - } - - CYCLES( 29); -} - -void I386_OPS_BASE::x87_fist_m32int( UINT8 modrm) -{ - INT32 m32int; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - m32int = 0x80000000; - } - else - { - floatx80 fx80 = floatx80_round_to_int(ST(0)); - - floatx80 lowerLim = int32_to_floatx80(0x80000000); - floatx80 upperLim = int32_to_floatx80(0x7fffffff); - - cpustate->x87_sw &= ~X87_SW_C1; - - if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) - m32int = floatx80_to_int32(fx80); - else - m32int = 0x80000000; - } - - UINT32 ea = GetEA( modrm, 1, 4); - if (x87_check_exceptions()) - { - WRITE32( ea, m32int); - } - - CYCLES( 28); -} - -void I386_OPS_BASE::x87_fistp_m16int( UINT8 modrm) -{ - INT16 m16int; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - m16int = (UINT16)0x8000; - } - else - { - floatx80 fx80 = floatx80_round_to_int(ST(0)); - - floatx80 lowerLim = int32_to_floatx80(-32768); - floatx80 upperLim = int32_to_floatx80(32767); - - cpustate->x87_sw &= ~X87_SW_C1; - - if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) - m16int = floatx80_to_int32(fx80); - else - m16int = (UINT16)0x8000; - } - - UINT32 ea = GetEA( modrm, 1, 2); - if (x87_check_exceptions()) - { - WRITE16( ea, m16int); - x87_inc_stack(); - } - - CYCLES( 29); -} - -void I386_OPS_BASE::x87_fistp_m32int( UINT8 modrm) -{ - INT32 m32int; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - m32int = 0x80000000; - } - else - { - floatx80 fx80 = floatx80_round_to_int(ST(0)); - - floatx80 lowerLim = int32_to_floatx80(0x80000000); - floatx80 upperLim = int32_to_floatx80(0x7fffffff); - - cpustate->x87_sw &= ~X87_SW_C1; - - if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) - m32int = floatx80_to_int32(fx80); - else - m32int = 0x80000000; - } - - UINT32 ea = GetEA( modrm, 1, 4); - if (x87_check_exceptions()) - { - WRITE32( ea, m32int); - x87_inc_stack(); - } - - CYCLES( 29); -} - -void I386_OPS_BASE::x87_fistp_m64int( UINT8 modrm) -{ - INT64 m64int; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - m64int = U64(0x8000000000000000); - } - else - { - floatx80 fx80 = floatx80_round_to_int(ST(0)); - - floatx80 lowerLim = int64_to_floatx80(U64(0x8000000000000000)); - floatx80 upperLim = int64_to_floatx80(U64(0x7fffffffffffffff)); - - cpustate->x87_sw &= ~X87_SW_C1; - - if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) - m64int = floatx80_to_int64(fx80); - else - m64int = U64(0x8000000000000000); - } - - UINT32 ea = GetEA( modrm, 1, 8); - if (x87_check_exceptions()) - { - WRITE64( ea, m64int); - x87_inc_stack(); - } - - CYCLES( 29); -} - -void I386_OPS_BASE::x87_fbstp( UINT8 modrm) -{ - floatx80 result; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - result = fx80_inan; - } - else - { - UINT64 u64 = floatx80_to_int64(floatx80_abs(ST(0))); - result.low = 0; - - for (int i = 0; i < 64; i += 4) - { - result.low += (u64 % 10) << i; - u64 /= 10; - } - - result.high = (u64 % 10); - result.high += ((u64 / 10) % 10) << 4; - result.high |= ST(0).high & 0x8000; - } - - UINT32 ea = GetEA( modrm, 1, 10); - if (x87_check_exceptions()) - { - WRITE80( ea, result); - x87_inc_stack(); - } - - CYCLES( 175); -} - - -/************************************* - * - * Constant load - * - *************************************/ - -void I386_OPS_BASE::x87_fld1( UINT8 modrm) -{ - floatx80 value; - int tag; - - if (x87_dec_stack()) - { - cpustate->x87_sw &= ~X87_SW_C1; - value = fx80_one; - tag = X87_TW_VALID; - } - else - { - value = fx80_inan; - tag = X87_TW_SPECIAL; - } - - if (x87_check_exceptions()) - { - x87_set_tag( ST_TO_PHYS(0), tag); - x87_write_stack( 0, value, FALSE); - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fldl2t( UINT8 modrm) -{ - floatx80 value; - int tag; - - if (x87_dec_stack()) - { - tag = X87_TW_VALID; - value.high = 0x4000; - - if (X87_RC == X87_CW_RC_UP) - value.low = U64(0xd49a784bcd1b8aff); - else - value.low = U64(0xd49a784bcd1b8afe); - - cpustate->x87_sw &= ~X87_SW_C1; - } - else - { - value = fx80_inan; - tag = X87_TW_SPECIAL; - } - - if (x87_check_exceptions()) - { - x87_set_tag( ST_TO_PHYS(0), tag); - x87_write_stack( 0, value, FALSE); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fldl2e( UINT8 modrm) -{ - floatx80 value; - int tag; - - if (x87_dec_stack()) - { - int rc = X87_RC; - tag = X87_TW_VALID; - value.high = 0x3fff; - - if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) - value.low = U64(0xb8aa3b295c17f0bc); - else - value.low = U64(0xb8aa3b295c17f0bb); - - cpustate->x87_sw &= ~X87_SW_C1; - } - else - { - value = fx80_inan; - tag = X87_TW_SPECIAL; - } - - if (x87_check_exceptions()) - { - x87_set_tag( ST_TO_PHYS(0), tag); - x87_write_stack( 0, value, FALSE); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fldpi( UINT8 modrm) -{ - floatx80 value; - int tag; - - if (x87_dec_stack()) - { - int rc = X87_RC; - tag = X87_TW_VALID; - value.high = 0x4000; - - if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) - value.low = U64(0xc90fdaa22168c235); - else - value.low = U64(0xc90fdaa22168c234); - - cpustate->x87_sw &= ~X87_SW_C1; - } - else - { - value = fx80_inan; - tag = X87_TW_SPECIAL; - } - - if (x87_check_exceptions()) - { - x87_set_tag( ST_TO_PHYS(0), tag); - x87_write_stack( 0, value, FALSE); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fldlg2( UINT8 modrm) -{ - floatx80 value; - int tag; - - if (x87_dec_stack()) - { - int rc = X87_RC; - tag = X87_TW_VALID; - value.high = 0x3ffd; - - if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) - value.low = U64(0x9a209a84fbcff799); - else - value.low = U64(0x9a209a84fbcff798); - - cpustate->x87_sw &= ~X87_SW_C1; - } - else - { - value = fx80_inan; - tag = X87_TW_SPECIAL; - } - - if (x87_check_exceptions()) - { - x87_set_tag( ST_TO_PHYS(0), tag); - x87_write_stack( 0, value, FALSE); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fldln2( UINT8 modrm) -{ - floatx80 value; - int tag; - - if (x87_dec_stack()) - { - int rc = X87_RC; - tag = X87_TW_VALID; - value.high = 0x3ffe; - - if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) - value.low = U64(0xb17217f7d1cf79ac); - else - value.low = U64(0xb17217f7d1cf79ab); - - cpustate->x87_sw &= ~X87_SW_C1; - } - else - { - value = fx80_inan; - tag = X87_TW_SPECIAL; - } - - if (x87_check_exceptions()) - { - x87_set_tag( ST_TO_PHYS(0), tag); - x87_write_stack( 0, value, FALSE); - } - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_fldz( UINT8 modrm) -{ - floatx80 value; - int tag; - - if (x87_dec_stack()) - { - value = fx80_zero; - tag = X87_TW_ZERO; - cpustate->x87_sw &= ~X87_SW_C1; - } - else - { - value = fx80_inan; - tag = X87_TW_SPECIAL; - } - - if (x87_check_exceptions()) - { - x87_set_tag( ST_TO_PHYS(0), tag); - x87_write_stack( 0, value, FALSE); - } - - CYCLES( 4); -} - - -/************************************* - * - * Miscellaneous - * - *************************************/ - -void I386_OPS_BASE::x87_fnop( UINT8 modrm) -{ - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fchs( UINT8 modrm) -{ - floatx80 value; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - value = ST(0); - value.high ^= 0x8000; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, FALSE); - - CYCLES( 6); -} - -void I386_OPS_BASE::x87_fabs( UINT8 modrm) -{ - floatx80 value; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - value = ST(0); - value.high &= 0x7fff; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, FALSE); - - CYCLES( 6); -} - -void I386_OPS_BASE::x87_fscale( UINT8 modrm) -{ - floatx80 value; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - value = ST(0); - - // Set the rounding mode to truncate - UINT16 old_cw = cpustate->x87_cw; - UINT16 new_cw = (old_cw & ~(X87_CW_RC_MASK << X87_CW_RC_SHIFT)) | (X87_CW_RC_ZERO << X87_CW_RC_SHIFT); - x87_write_cw( new_cw); - - // Interpret ST(1) as an integer - UINT32 st1 = floatx80_to_int32(floatx80_round_to_int(ST(1))); - - // Restore the rounding mode - x87_write_cw( old_cw); - - // Get the unbiased exponent of ST(0) - INT16 exp = (ST(0).high & 0x7fff) - 0x3fff; - - // Calculate the new exponent - exp = (exp + st1 + 0x3fff) & 0x7fff; - - // Write it back - value.high = (value.high & ~0x7fff) + exp; - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, FALSE); - - CYCLES( 31); -} - -void I386_OPS_BASE::x87_frndint( UINT8 modrm) -{ - floatx80 value; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - value = fx80_inan; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - value = floatx80_round_to_int(ST(0)); - } - - if (x87_check_exceptions()) - x87_write_stack( 0, value, TRUE); - - CYCLES( 21); -} - -void I386_OPS_BASE::x87_fxtract( UINT8 modrm) -{ - floatx80 sig80, exp80; - - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - sig80 = exp80 = fx80_inan; - } - else if (!X87_IS_ST_EMPTY(7)) - { - x87_set_stack_overflow(); - sig80 = exp80 = fx80_inan; - } - else - { - floatx80 value = ST(0); - - if (floatx80_eq(value, fx80_zero)) - { - cpustate->x87_sw |= X87_SW_ZE; - - exp80 = fx80_ninf; - sig80 = fx80_zero; - } - else - { - // Extract the unbiased exponent - exp80 = int32_to_floatx80((value.high & 0x7fff) - 0x3fff); - - // For the significand, replicate the original value and set its true exponent to 0. - sig80 = value; - sig80.high &= ~0x7fff; - sig80.high |= 0x3fff; - } - } - - if (x87_check_exceptions()) - { - x87_write_stack( 0, exp80, TRUE); - x87_dec_stack(); - x87_write_stack( 0, sig80, TRUE); - } - - CYCLES( 21); -} - -/************************************* - * - * Comparison - * - *************************************/ - -void I386_OPS_BASE::x87_ftst( UINT8 modrm) -{ - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - if (floatx80_is_nan(ST(0))) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(ST(0), fx80_zero)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(ST(0), fx80_zero)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - x87_check_exceptions(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fxam( UINT8 modrm) -{ - floatx80 value = ST(0); - - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - // TODO: Unsupported and denormal values - if (X87_IS_ST_EMPTY(0)) - { - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C0; - } - else if (floatx80_is_zero(value)) - { - cpustate->x87_sw |= X87_SW_C3; - } - else if (floatx80_is_nan(value)) - { - cpustate->x87_sw |= X87_SW_C0; - } - else if (floatx80_is_inf(value)) - { - cpustate->x87_sw |= X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw |= X87_SW_C2; - } - - if (value.high & 0x8000) - cpustate->x87_sw |= X87_SW_C1; - - CYCLES( 8); -} - -void I386_OPS_BASE::x87_ficom_m16int( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - INT16 m16int = READ16( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m16int); - - if (floatx80_is_nan(a)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - x87_check_exceptions(); - - CYCLES( 16); -} - -void I386_OPS_BASE::x87_ficom_m32int( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - INT32 m32int = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m32int); - - if (floatx80_is_nan(a)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - x87_check_exceptions(); - - CYCLES( 15); -} - -void I386_OPS_BASE::x87_ficomp_m16int( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 2); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - INT16 m16int = READ16( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m16int); - - if (floatx80_is_nan(a)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 16); -} - -void I386_OPS_BASE::x87_ficomp_m32int( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - INT32 m32int = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = int32_to_floatx80(m32int); - - if (floatx80_is_nan(a)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 15); -} - - -void I386_OPS_BASE::x87_fcom_m32real( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - UINT32 m32real = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = float32_to_floatx80(m32real); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - x87_check_exceptions(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcom_m64real( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - UINT64 m64real = READ64( ea); - - floatx80 a = ST(0); - floatx80 b = float64_to_floatx80(m64real); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - x87_check_exceptions(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcom_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - x87_check_exceptions(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcomp_m32real( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 4); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - UINT32 m32real = READ32( ea); - - floatx80 a = ST(0); - floatx80 b = float32_to_floatx80(m32real); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcomp_m64real( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 8); - if (X87_IS_ST_EMPTY(0)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - UINT64 m64real = READ64( ea); - - floatx80 a = ST(0); - floatx80 b = float64_to_floatx80(m64real); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcomp_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fcomi_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - - if (floatx80_eq(a, b)) - cpustate->ZF = 1; - - if (floatx80_lt(a, b)) - cpustate->CF = 1; - } - } - - x87_check_exceptions(); - - CYCLES( 4); // TODO: correct cycle count -} - -void I386_OPS_BASE::x87_fcomip_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - - if (floatx80_eq(a, b)) - cpustate->ZF = 1; - - if (floatx80_lt(a, b)) - cpustate->CF = 1; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 4); // TODO: correct cycle count -} - -void I386_OPS_BASE::x87_fucomi_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_quiet_nan(a) || floatx80_is_quiet_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - - if (floatx80_eq(a, b)) - cpustate->ZF = 1; - - if (floatx80_lt(a, b)) - cpustate->CF = 1; - } - } - - x87_check_exceptions(); - - CYCLES( 4); // TODO: correct cycle count -} - -void I386_OPS_BASE::x87_fucomip_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else - { - cpustate->x87_sw &= ~X87_SW_C1; - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_quiet_nan(a) || floatx80_is_quiet_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - } - else if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->ZF = 1; - cpustate->PF = 1; - cpustate->CF = 1; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - cpustate->ZF = 0; - cpustate->PF = 0; - cpustate->CF = 0; - - if (floatx80_eq(a, b)) - cpustate->ZF = 1; - - if (floatx80_lt(a, b)) - cpustate->CF = 1; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 4); // TODO: correct cycle count -} - -void I386_OPS_BASE::x87_fcompp( UINT8 modrm) -{ - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - floatx80 a = ST(0); - floatx80 b = ST(1); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - { - x87_inc_stack(); - x87_inc_stack(); - } - - CYCLES( 5); -} - - -/************************************* - * - * Unordererd comparison - * - *************************************/ - -void I386_OPS_BASE::x87_fucom_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - x87_check_exceptions(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fucomp_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - floatx80 a = ST(0); - floatx80 b = ST(i); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - x87_inc_stack(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fucompp( UINT8 modrm) -{ - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - { - x87_set_stack_underflow(); - cpustate->x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; - } - else - { - cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); - - floatx80 a = ST(0); - floatx80 b = ST(1); - - if (floatx80_is_nan(a) || floatx80_is_nan(b)) - { - cpustate->x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; - - if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) - cpustate->x87_sw |= X87_SW_IE; - } - else - { - if (floatx80_eq(a, b)) - cpustate->x87_sw |= X87_SW_C3; - - if (floatx80_lt(a, b)) - cpustate->x87_sw |= X87_SW_C0; - } - } - - if (x87_check_exceptions()) - { - x87_inc_stack(); - x87_inc_stack(); - } - - CYCLES( 4); -} - - -/************************************* - * - * Control - * - *************************************/ - -void I386_OPS_BASE::x87_fdecstp( UINT8 modrm) -{ - cpustate->x87_sw &= ~X87_SW_C1; - - x87_set_stack_top(ST_TO_PHYS(7)); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fincstp( UINT8 modrm) -{ - cpustate->x87_sw &= ~X87_SW_C1; - - x87_set_stack_top(ST_TO_PHYS(1)); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fclex( UINT8 modrm) -{ - cpustate->x87_sw &= ~0x80ff; - -// ferr_handler(cpustate, 0); - CYCLES( 7); -} - -void I386_OPS_BASE::x87_feni(UINT8 modrm) -{ - cpustate->x87_cw &= ~X87_CW_IEM; - x87_check_exceptions(); - - CYCLES(5); -} - -void I386_OPS_BASE::x87_fdisi( UINT8 modrm) -{ - cpustate->x87_cw |= X87_CW_IEM; - - CYCLES(5); -} - - -void I386_OPS_BASE::x87_ffree( UINT8 modrm) -{ - x87_set_tag( ST_TO_PHYS(modrm & 7), X87_TW_EMPTY); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_finit( UINT8 modrm) -{ - x87_reset(); - - CYCLES( 17); -} - -void I386_OPS_BASE::x87_fldcw( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 2); - UINT16 cw = READ16( ea); - - x87_write_cw( cw); - - x87_check_exceptions(); - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fstcw( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 1, 2); - WRITE16( ea, cpustate->x87_cw); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fldenv( UINT8 modrm) -{ - // TODO: Pointers and selectors - UINT32 ea = GetEA( modrm, 0, 2); - - if (cpustate->operand_size) - { - // 32-bit real/protected mode - x87_write_cw( READ16( ea)); - cpustate->x87_sw = READ16( ea + 4); - cpustate->x87_tw = READ16( ea + 8); - } - else - { - // 16-bit real/protected mode - x87_write_cw( READ16( ea)); - cpustate->x87_sw = READ16( ea + 2); - cpustate->x87_tw = READ16( ea + 4); - } - - x87_check_exceptions(); - - CYCLES((cpustate->cr[0] & 1) ? 34 : 44); -} - -void I386_OPS_BASE::x87_fstenv( UINT8 modrm) -{ - UINT32 ea; - - // TODO: Pointers and selectors - switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1) - { - case 0: // 16-bit real mode - ea = GetEA( modrm, 1, 6); - WRITE16( ea + 0, cpustate->x87_cw); - WRITE16( ea + 2, cpustate->x87_sw); - WRITE16( ea + 4, cpustate->x87_tw); -// WRITE16( ea + 6, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16( ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16( ea + 10, cpustate->fpu_data_ptr & 0xffff); -// WRITE16( ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4); - break; - case 1: // 16-bit protected mode - ea = GetEA( modrm, 1, 6); - WRITE16(ea + 0, cpustate->x87_cw); - WRITE16(ea + 2, cpustate->x87_sw); - WRITE16(ea + 4, cpustate->x87_tw); -// WRITE16(ea + 6, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16(ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16(ea + 10, cpustate->fpu_data_ptr & 0xffff); -// WRITE16(ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4); - break; - case 2: // 32-bit real mode - ea = GetEA( modrm, 1, 10); - WRITE16( ea + 0, cpustate->x87_cw); - WRITE16( ea + 4, cpustate->x87_sw); - WRITE16( ea + 8, cpustate->x87_tw); -// WRITE16( ea + 12, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16( ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16( ea + 20, cpustate->fpu_data_ptr & 0xffff); -// WRITE16( ea + 12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE32( ea + 24, (cpustate->fpu_data_ptr >> 16) << 12); - break; - case 3: // 32-bit protected mode - ea = GetEA( modrm, 1, 10); - WRITE16( ea + 0, cpustate->x87_cw); - WRITE16( ea + 4, cpustate->x87_sw); - WRITE16( ea + 8, cpustate->x87_tw); -// WRITE32( ea + 12, cpustate->fpu_inst_ptr); -// WRITE32( ea + 16, cpustate->fpu_opcode); -// WRITE32( ea + 20, cpustate->fpu_data_ptr); -// WRITE32( ea + 24, cpustate->fpu_inst_ptr); - break; - } - cpustate->x87_cw |= 0x3f; // set all masks - - CYCLES((cpustate->cr[0] & 1) ? 56 : 67); -} - -void I386_OPS_BASE::x87_fsave( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 1, 80); - - // TODO: Pointers and selectors - switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1) - { - case 0: // 16-bit real mode - WRITE16( ea + 0, cpustate->x87_cw); - WRITE16( ea + 2, cpustate->x87_sw); - WRITE16( ea + 4, cpustate->x87_tw); -// WRITE16( ea + 6, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16( ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16( ea + 10, cpustate->fpu_data_ptr & 0xffff); -// WRITE16( ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4); - ea += 14; - break; - case 1: // 16-bit protected mode - WRITE16(ea + 0, cpustate->x87_cw); - WRITE16(ea + 2, cpustate->x87_sw); - WRITE16(ea + 4, cpustate->x87_tw); -// WRITE16(ea + 6, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16(ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16(ea + 10, cpustate->fpu_data_ptr & 0xffff); -// WRITE16(ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4); - ea += 14; - break; - case 2: // 32-bit real mode - WRITE16( ea + 0, cpustate->x87_cw); - WRITE16( ea + 4, cpustate->x87_sw); - WRITE16( ea + 8, cpustate->x87_tw); -// WRITE16( ea + 12, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16( ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16( ea + 20, cpustate->fpu_data_ptr & 0xffff); -// WRITE16( ea + 12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE32( ea + 24, (cpustate->fpu_data_ptr >> 16) << 12); - ea += 28; - break; - case 3: // 32-bit protected mode - WRITE16( ea + 0, cpustate->x87_cw); - WRITE16( ea + 4, cpustate->x87_sw); - WRITE16( ea + 8, cpustate->x87_tw); -// WRITE32( ea + 12, cpustate->fpu_inst_ptr); -// WRITE32( ea + 16, cpustate->fpu_opcode); -// WRITE32( ea + 20, cpustate->fpu_data_ptr); -// WRITE32( ea + 24, cpustate->fpu_inst_ptr); - ea += 28; - break; - } - - for (int i = 0; i < 8; ++i) - WRITE80( ea + i*10, ST(i)); - - CYCLES((cpustate->cr[0] & 1) ? 56 : 67); -} - -void I386_OPS_BASE::x87_frstor( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 0, 80); - - // TODO: Pointers and selectors - switch((cpustate->cr[0] & 1)|(cpustate->operand_size & 1)<<1) - { - case 0: // 16-bit real mode - x87_write_cw( READ16( ea)); - cpustate->x87_sw = READ16( ea + 2); - cpustate->x87_tw = READ16( ea + 4); -// WRITE16( ea + 6, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16( ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16( ea + 10, cpustate->fpu_data_ptr & 0xffff); -// WRITE16( ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4); - ea += 14; - break; - case 1: // 16-bit protected mode - x87_write_cw( READ16( ea)); - cpustate->x87_sw = READ16( ea + 2); - cpustate->x87_tw = READ16( ea + 4); -// WRITE16(ea + 6, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16(ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16(ea + 10, cpustate->fpu_data_ptr & 0xffff); -// WRITE16(ea + 12, (cpustate->fpu_inst_ptr & 0x0f0000) >> 4); - ea += 14; - break; - case 2: // 32-bit real mode - x87_write_cw( READ16( ea)); - cpustate->x87_sw = READ16( ea + 4); - cpustate->x87_tw = READ16( ea + 8); -// WRITE16( ea + 12, cpustate->fpu_inst_ptr & 0xffff); -// WRITE16( ea + 8, (cpustate->fpu_opcode & 0x07ff) | ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE16( ea + 20, cpustate->fpu_data_ptr & 0xffff); -// WRITE16( ea + 12, ((cpustate->fpu_inst_ptr & 0x0f0000) >> 4)); -// WRITE32( ea + 24, (cpustate->fpu_data_ptr >> 16) << 12); - ea += 28; - break; - case 3: // 32-bit protected mode - x87_write_cw( READ16( ea)); - cpustate->x87_sw = READ16( ea + 4); - cpustate->x87_tw = READ16( ea + 8); -// WRITE32( ea + 12, cpustate->fpu_inst_ptr); -// WRITE32( ea + 16, cpustate->fpu_opcode); -// WRITE32( ea + 20, cpustate->fpu_data_ptr); -// WRITE32( ea + 24, cpustate->fpu_inst_ptr); - ea += 28; - break; - } - - for (int i = 0; i < 8; ++i) - x87_write_stack( i, READ80( ea + i*10), FALSE); - - CYCLES((cpustate->cr[0] & 1) ? 34 : 44); -} - -void I386_OPS_BASE::x87_fxch( UINT8 modrm) -{ - if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) - x87_set_stack_underflow(); - - if (x87_check_exceptions()) - { - floatx80 tmp = ST(0); - ST(0) = ST(1); - ST(1) = tmp; - - // Swap the tags - int tag0 = X87_TAG(ST_TO_PHYS(0)); - x87_set_tag( ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(1))); - x87_set_tag( ST_TO_PHYS(1), tag0); - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fxch_sti( UINT8 modrm) -{ - int i = modrm & 7; - - if (X87_IS_ST_EMPTY(0)) - { - ST(0) = fx80_inan; - x87_set_tag( ST_TO_PHYS(0), X87_TW_SPECIAL); - x87_set_stack_underflow(); - } - if (X87_IS_ST_EMPTY(i)) - { - ST(i) = fx80_inan; - x87_set_tag( ST_TO_PHYS(i), X87_TW_SPECIAL); - x87_set_stack_underflow(); - } - - if (x87_check_exceptions()) - { - floatx80 tmp = ST(0); - ST(0) = ST(i); - ST(i) = tmp; - - // Swap the tags - int tag0 = X87_TAG(ST_TO_PHYS(0)); - x87_set_tag( ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(i))); - x87_set_tag( ST_TO_PHYS(i), tag0); - } - - CYCLES( 4); -} - -void I386_OPS_BASE::x87_fstsw_ax( UINT8 modrm) -{ - REG16(AX) = cpustate->x87_sw; - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_fstsw_m2byte( UINT8 modrm) -{ - UINT32 ea = GetEA( modrm, 1, 2); - - WRITE16( ea, cpustate->x87_sw); - - CYCLES( 3); -} - -void I386_OPS_BASE::x87_invalid( UINT8 modrm) -{ - // TODO - report_invalid_opcode(); - i386_trap(6, 0, 0); -} - - - -/************************************* - * - * Instruction dispatch - * - *************************************/ - -void I386_OPS_BASE::I386OP(x87_group_d8)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_d8[modrm])(modrm); -} - -void I386_OPS_BASE::I386OP(x87_group_d9)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_d9[modrm])(modrm); -} - -void I386_OPS_BASE::I386OP(x87_group_da)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_da[modrm])( modrm); -} - -void I386_OPS_BASE::I386OP(x87_group_db)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_db[modrm])( modrm); -} - -void I386_OPS_BASE::I386OP(x87_group_dc)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_dc[modrm])( modrm); -} - -void I386_OPS_BASE::I386OP(x87_group_dd)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_dd[modrm])( modrm); -} - -void I386_OPS_BASE::I386OP(x87_group_de)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_de[modrm])( modrm); -} - -void I386_OPS_BASE::I386OP(x87_group_df)() -{ - UINT8 modrm = FETCH(); - (this->*cpustate->opcode_table_x87_df[modrm])(modrm); -} - - -/************************************* - * - * Opcode table building - * - *************************************/ - -void I386_OPS_BASE::build_x87_opcode_table_d8() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)(UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fadd_m32real; break; - case 0x01: ptr = &I386_OPS_BASE::x87_fmul_m32real; break; - case 0x02: ptr = &I386_OPS_BASE::x87_fcom_m32real; break; - case 0x03: ptr = &I386_OPS_BASE::x87_fcomp_m32real; break; - case 0x04: ptr = &I386_OPS_BASE::x87_fsub_m32real; break; - case 0x05: ptr = &I386_OPS_BASE::x87_fsubr_m32real; break; - case 0x06: ptr = &I386_OPS_BASE::x87_fdiv_m32real; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fdivr_m32real; break; - } - } - else - { - switch (modrm) - { - case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &I386_OPS_BASE::x87_fadd_st_sti; break; - case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &I386_OPS_BASE::x87_fmul_st_sti; break; - case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &I386_OPS_BASE::x87_fcom_sti; break; - case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &I386_OPS_BASE::x87_fcomp_sti; break; - case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &I386_OPS_BASE::x87_fsub_st_sti; break; - case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &I386_OPS_BASE::x87_fsubr_st_sti; break; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &I386_OPS_BASE::x87_fdiv_st_sti; break; - case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &I386_OPS_BASE::x87_fdivr_st_sti; break; - } - } - - cpustate->opcode_table_x87_d8[modrm] = ptr; - } -} - - -void I386_OPS_BASE::build_x87_opcode_table_d9() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)( UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fld_m32real; break; - case 0x02: ptr = &I386_OPS_BASE::x87_fst_m32real; break; - case 0x03: ptr = &I386_OPS_BASE::x87_fstp_m32real; break; - case 0x04: ptr = &I386_OPS_BASE::x87_fldenv; break; - case 0x05: ptr = &I386_OPS_BASE::x87_fldcw; break; - case 0x06: ptr = &I386_OPS_BASE::x87_fstenv; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fstcw; break; - } - } - else - { - switch (modrm) - { - case 0xc0: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: ptr = &I386_OPS_BASE::x87_fld_sti; break; - - case 0xc8: - case 0xc9: - case 0xca: - case 0xcb: - case 0xcc: - case 0xcd: - case 0xce: - case 0xcf: ptr = &I386_OPS_BASE::x87_fxch_sti; break; - - case 0xd0: ptr = &I386_OPS_BASE::x87_fnop; break; - case 0xe0: ptr = &I386_OPS_BASE::x87_fchs; break; - case 0xe1: ptr = &I386_OPS_BASE::x87_fabs; break; - case 0xe4: ptr = &I386_OPS_BASE::x87_ftst; break; - case 0xe5: ptr = &I386_OPS_BASE::x87_fxam; break; - case 0xe8: ptr = &I386_OPS_BASE::x87_fld1; break; - case 0xe9: ptr = &I386_OPS_BASE::x87_fldl2t; break; - case 0xea: ptr = &I386_OPS_BASE::x87_fldl2e; break; - case 0xeb: ptr = &I386_OPS_BASE::x87_fldpi; break; - case 0xec: ptr = &I386_OPS_BASE::x87_fldlg2; break; - case 0xed: ptr = &I386_OPS_BASE::x87_fldln2; break; - case 0xee: ptr = &I386_OPS_BASE::x87_fldz; break; - case 0xf0: ptr = &I386_OPS_BASE::x87_f2xm1; break; - case 0xf1: ptr = &I386_OPS_BASE::x87_fyl2x; break; - case 0xf2: ptr = &I386_OPS_BASE::x87_fptan; break; - case 0xf3: ptr = &I386_OPS_BASE::x87_fpatan; break; - case 0xf4: ptr = &I386_OPS_BASE::x87_fxtract; break; - case 0xf5: ptr = &I386_OPS_BASE::x87_fprem1; break; - case 0xf6: ptr = &I386_OPS_BASE::x87_fdecstp; break; - case 0xf7: ptr = &I386_OPS_BASE::x87_fincstp; break; - case 0xf8: ptr = &I386_OPS_BASE::x87_fprem; break; - case 0xf9: ptr = &I386_OPS_BASE::x87_fyl2xp1; break; - case 0xfa: ptr = &I386_OPS_BASE::x87_fsqrt; break; - case 0xfb: ptr = &I386_OPS_BASE::x87_fsincos; break; - case 0xfc: ptr = &I386_OPS_BASE::x87_frndint; break; - case 0xfd: ptr = &I386_OPS_BASE::x87_fscale; break; - case 0xfe: ptr = &I386_OPS_BASE::x87_fsin; break; - case 0xff: ptr = &I386_OPS_BASE::x87_fcos; break; - } - } - - cpustate->opcode_table_x87_d9[modrm] = ptr; - } -} - -void I386_OPS_BASE::build_x87_opcode_table_da() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)( UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fiadd_m32int; break; - case 0x01: ptr = &I386_OPS_BASE::x87_fimul_m32int; break; - case 0x02: ptr = &I386_OPS_BASE::x87_ficom_m32int; break; - case 0x03: ptr = &I386_OPS_BASE::x87_ficomp_m32int; break; - case 0x04: ptr = &I386_OPS_BASE::x87_fisub_m32int; break; - case 0x05: ptr = &I386_OPS_BASE::x87_fisubr_m32int; break; - case 0x06: ptr = &I386_OPS_BASE::x87_fidiv_m32int; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fidivr_m32int; break; - } - } - else - { - switch (modrm) - { - case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &I386_OPS_BASE::x87_fcmovb_sti; break; - case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &I386_OPS_BASE::x87_fcmove_sti; break; - case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &I386_OPS_BASE::x87_fcmovbe_sti; break; - case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &I386_OPS_BASE::x87_fcmovu_sti; break; - case 0xe9: ptr = &I386_OPS_BASE::x87_fucompp; break; - } - } - - cpustate->opcode_table_x87_da[modrm] = ptr; - } -} - - -void I386_OPS_BASE::build_x87_opcode_table_db() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)( UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fild_m32int; break; - case 0x02: ptr = &I386_OPS_BASE::x87_fist_m32int; break; - case 0x03: ptr = &I386_OPS_BASE::x87_fistp_m32int; break; - case 0x05: ptr = &I386_OPS_BASE::x87_fld_m80real; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fstp_m80real; break; - } - } - else - { - switch (modrm) - { - case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &I386_OPS_BASE::x87_fcmovnb_sti; break; - case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &I386_OPS_BASE::x87_fcmovne_sti; break; - case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &I386_OPS_BASE::x87_fcmovnbe_sti; break; - case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &I386_OPS_BASE::x87_fcmovnu_sti; break; - case 0xe0: ptr = &I386_OPS_BASE::x87_feni; break; /* FENI */ - case 0xe1: ptr = &I386_OPS_BASE::x87_fdisi; break; /* FDISI */ - case 0xe2: ptr = &I386_OPS_BASE::x87_fclex; break; - case 0xe3: ptr = &I386_OPS_BASE::x87_finit; break; - case 0xe4: ptr = &I386_OPS_BASE::x87_fnop; break; /* FSETPM */ - case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &I386_OPS_BASE::x87_fucomi_sti; break; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &I386_OPS_BASE::x87_fcomi_sti; break; - } - } - - cpustate->opcode_table_x87_db[modrm] = ptr; - } -} - - -void I386_OPS_BASE::build_x87_opcode_table_dc() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)( UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fadd_m64real; break; - case 0x01: ptr = &I386_OPS_BASE::x87_fmul_m64real; break; - case 0x02: ptr = &I386_OPS_BASE::x87_fcom_m64real; break; - case 0x03: ptr = &I386_OPS_BASE::x87_fcomp_m64real; break; - case 0x04: ptr = &I386_OPS_BASE::x87_fsub_m64real; break; - case 0x05: ptr = &I386_OPS_BASE::x87_fsubr_m64real; break; - case 0x06: ptr = &I386_OPS_BASE::x87_fdiv_m64real; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fdivr_m64real; break; - } - } - else - { - switch (modrm) - { - case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &I386_OPS_BASE::x87_fadd_sti_st; break; - case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &I386_OPS_BASE::x87_fmul_sti_st; break; - case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &I386_OPS_BASE::x87_fsubr_sti_st; break; - case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &I386_OPS_BASE::x87_fsub_sti_st; break; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &I386_OPS_BASE::x87_fdivr_sti_st; break; - case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &I386_OPS_BASE::x87_fdiv_sti_st; break; - } - } - - cpustate->opcode_table_x87_dc[modrm] = ptr; - } -} - - -void I386_OPS_BASE::build_x87_opcode_table_dd() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)( UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fld_m64real; break; - case 0x02: ptr = &I386_OPS_BASE::x87_fst_m64real; break; - case 0x03: ptr = &I386_OPS_BASE::x87_fstp_m64real; break; - case 0x04: ptr = &I386_OPS_BASE::x87_frstor; break; - case 0x06: ptr = &I386_OPS_BASE::x87_fsave; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fstsw_m2byte; break; - } - } - else - { - switch (modrm) - { - case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &I386_OPS_BASE::x87_ffree; break; - case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &I386_OPS_BASE::x87_fxch_sti; break; - case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &I386_OPS_BASE::x87_fst_sti; break; - case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &I386_OPS_BASE::x87_fstp_sti; break; - case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &I386_OPS_BASE::x87_fucom_sti; break; - case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &I386_OPS_BASE::x87_fucomp_sti; break; - } - } - - cpustate->opcode_table_x87_dd[modrm] = ptr; - } -} - - -void I386_OPS_BASE::build_x87_opcode_table_de() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)( UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fiadd_m16int; break; - case 0x01: ptr = &I386_OPS_BASE::x87_fimul_m16int; break; - case 0x02: ptr = &I386_OPS_BASE::x87_ficom_m16int; break; - case 0x03: ptr = &I386_OPS_BASE::x87_ficomp_m16int; break; - case 0x04: ptr = &I386_OPS_BASE::x87_fisub_m16int; break; - case 0x05: ptr = &I386_OPS_BASE::x87_fisubr_m16int; break; - case 0x06: ptr = &I386_OPS_BASE::x87_fidiv_m16int; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fidivr_m16int; break; - } - } - else - { - switch (modrm) - { - case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &I386_OPS_BASE::x87_faddp; break; - case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &I386_OPS_BASE::x87_fmulp; break; - case 0xd9: ptr = &I386_OPS_BASE::x87_fcompp; break; - case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &I386_OPS_BASE::x87_fsubrp; break; - case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &I386_OPS_BASE::x87_fsubp; break; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &I386_OPS_BASE::x87_fdivrp; break; - case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &I386_OPS_BASE::x87_fdivp; break; - } - } - - cpustate->opcode_table_x87_de[modrm] = ptr; - } -} - - -void I386_OPS_BASE::build_x87_opcode_table_df() -{ - int modrm = 0; - - for (modrm = 0; modrm < 0x100; ++modrm) - { - void (I386_OPS_BASE::*ptr)(UINT8 modrm) = &I386_OPS_BASE::x87_invalid; - - if (modrm < 0xc0) - { - switch ((modrm >> 3) & 0x7) - { - case 0x00: ptr = &I386_OPS_BASE::x87_fild_m16int; break; - case 0x02: ptr = &I386_OPS_BASE::x87_fist_m16int; break; - case 0x03: ptr = &I386_OPS_BASE::x87_fistp_m16int; break; - case 0x04: ptr = &I386_OPS_BASE::x87_fbld; break; - case 0x05: ptr = &I386_OPS_BASE::x87_fild_m64int; break; - case 0x06: ptr = &I386_OPS_BASE::x87_fbstp; break; - case 0x07: ptr = &I386_OPS_BASE::x87_fistp_m64int; break; - } - } - else - { - switch (modrm) - { - case 0xe0: ptr = &I386_OPS_BASE::x87_fstsw_ax; break; - case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &I386_OPS_BASE::x87_fucomip_sti; break; - case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &I386_OPS_BASE::x87_fcomip_sti; break; - } - } - - cpustate->opcode_table_x87_df[modrm] = ptr; - } -} - -extern "C" { - //extern void softfloat_fsincos_init(void); - //extern void softfloat_fyl2x_init(void); -}; - -void I386_OPS_BASE::build_x87_opcode_table() -{ - //softfloat_fsincos_init(); - //softfloat_fyl2x_init(); - build_x87_opcode_table_d8(); - build_x87_opcode_table_d9(); - build_x87_opcode_table_da(); - build_x87_opcode_table_db(); - build_x87_opcode_table_dc(); - build_x87_opcode_table_dd(); - build_x87_opcode_table_de(); - build_x87_opcode_table_df(); -} diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/README.txt b/source/src/vm/libcpu_newdev/libcpu_softfloat/README.txt deleted file mode 100644 index 9500d25e8..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/README.txt +++ /dev/null @@ -1,78 +0,0 @@ -MAME note: this package is derived from the following original SoftFloat -package and has been "re-packaged" to work with MAME's conventions and -build system. The source files come from bits64/ and bits64/templates -in the original distribution as MAME requires a compiler with a 64-bit -integer type. - - -Package Overview for SoftFloat Release 2b - -John R. Hauser -2002 May 27 - - ----------------------------------------------------------------------------- -Overview - -SoftFloat is a software implementation of floating-point that conforms to -the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat is -distributed in the form of C source code. Compiling the SoftFloat sources -generates two things: - --- A SoftFloat object file (typically `softfloat.o') containing the complete - set of IEC/IEEE floating-point routines. - --- A `timesoftfloat' program for evaluating the speed of the SoftFloat - routines. (The SoftFloat module is linked into this program.) - -The SoftFloat package is documented in four text files: - - SoftFloat.txt Documentation for using the SoftFloat functions. - SoftFloat-source.txt Documentation for compiling SoftFloat. - SoftFloat-history.txt History of major changes to SoftFloat. - timesoftfloat.txt Documentation for using `timesoftfloat'. - -Other files in the package comprise the source code for SoftFloat. - -Please be aware that some work is involved in porting this software to other -targets. It is not just a matter of getting `make' to complete without -error messages. I would have written the code that way if I could, but -there are fundamental differences between systems that can't be hidden. -You should not attempt to compile SoftFloat without first reading both -`SoftFloat.txt' and `SoftFloat-source.txt'. - - ----------------------------------------------------------------------------- -Legal Notice - -SoftFloat was written by me, John R. Hauser. This work was made possible in -part by the International Computer Science Institute, located at Suite 600, -1947 Center Street, Berkeley, California 94704. Funding was partially -provided by the National Science Foundation under grant MIP-9311980. The -original version of this code was written as part of a project to build -a fixed-point vector processor in collaboration with the University of -California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort -has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT -TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO -PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL -LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO -FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER -SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, -COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE -SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, provided -that the minimal documentation requirements stated in the source code are -satisfied. - - ----------------------------------------------------------------------------- -Contact Information - -At the time of this writing, the most up-to-date information about -SoftFloat and the latest release can be found at the Web page `http:// -www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html'. - - diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/fpu_constant.h b/source/src/vm/libcpu_newdev/libcpu_softfloat/fpu_constant.h deleted file mode 100644 index 3ac8862ba..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/fpu_constant.h +++ /dev/null @@ -1,80 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#ifndef _FPU_CONSTANTS_H_ -#define _FPU_CONSTANTS_H_ - -// Pentium CPU uses only 68-bit precision M_PI approximation -#define BETTER_THAN_PENTIUM - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -////////////////////////////// -// PI, PI/2, PI/4 constants -////////////////////////////// - -#define FLOATX80_PI_EXP (0x4000) - -// 128-bit PI fraction -#ifdef BETTER_THAN_PENTIUM -#define FLOAT_PI_HI (U64(0xc90fdaa22168c234)) -#define FLOAT_PI_LO (U64(0xc4c6628b80dc1cd1)) -#else -#define FLOAT_PI_HI (U64(0xc90fdaa22168c234)) -#define FLOAT_PI_LO (U64(0xC000000000000000)) -#endif - -#define FLOATX80_PI2_EXP (0x3FFF) -#define FLOATX80_PI4_EXP (0x3FFE) - -////////////////////////////// -// 3PI/4 constant -////////////////////////////// - -#define FLOATX80_3PI4_EXP (0x4000) - -// 128-bit 3PI/4 fraction -#ifdef BETTER_THAN_PENTIUM -#define FLOAT_3PI4_HI (U64(0x96cbe3f9990e91a7)) -#define FLOAT_3PI4_LO (U64(0x9394c9e8a0a5159c)) -#else -#define FLOAT_3PI4_HI (U64(0x96cbe3f9990e91a7)) -#define FLOAT_3PI4_LO (U64(0x9000000000000000)) -#endif - -////////////////////////////// -// 1/LN2 constant -////////////////////////////// - -#define FLOAT_LN2INV_EXP (0x3FFF) - -// 128-bit 1/LN2 fraction -#ifdef BETTER_THAN_PENTIUM -#define FLOAT_LN2INV_HI (U64(0xb8aa3b295c17f0bb)) -#define FLOAT_LN2INV_LO (U64(0xbe87fed0691d3e89)) -#else -#define FLOAT_LN2INV_HI (U64(0xb8aa3b295c17f0bb)) -#define FLOAT_LN2INV_LO (U64(0xC000000000000000)) -#endif - -#endif diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/fsincos.c b/source/src/vm/libcpu_newdev/libcpu_softfloat/fsincos.c deleted file mode 100644 index d2349a7fc..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/fsincos.c +++ /dev/null @@ -1,655 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#define FLOAT128 - -#define USE_estimateDiv128To64 -#include "mamesf.h" -#include "softfloat.h" -//#include "softfloat-specialize" -#include "fpu_constant.h" - -//static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, U64(0x8000000000000000)); -//static const floatx80 floatx80_default_nan = packFloatx80(0, 0xffff, U64(0xffffffffffffffff)); - -#define packFloat2x128m(zHi, zLo) {(zHi), (zLo)} -#define PACK_FLOAT_128(hi,lo) packFloat2x128m(LIT64(hi),LIT64(lo)) - -#define EXP_BIAS 0x3FFF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -#if 0 -INLINE bits64 extractFloatx80Frac( floatx80 a ) -{ - return a.low; - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -#if 0 -INLINE int32 extractFloatx80Exp( floatx80 a ) -{ - return a.high & 0x7FFF; - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -#if 0 -INLINE flag extractFloatx80Sign( floatx80 a ) -{ - return a.high>>15; - -} -#endif - -/*---------------------------------------------------------------------------- -| Takes extended double-precision floating-point NaN `a' and returns the -| appropriate NaN result. If `a' is a signaling NaN, the invalid exception -| is raised. -*----------------------------------------------------------------------------*/ - -#if 0 -INLINE floatx80 propagateFloatx80NaNOneArg(floatx80 a) -{ - if (floatx80_is_signaling_nan(a)) - float_raise(float_flag_invalid); - - a.low |= U64(0xC000000000000000); - - return a; -} -#endif - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -#if 0 -void normalizeFloatx80Subnormal(UINT64 aSig, INT32 *zExpPtr, UINT64 *zSigPtr) -{ - int shiftCount = countLeadingZeros64(aSig); - *zSigPtr = aSig< 0) { - q = argument_reduction_kernel(aSig0, expDiff, &aSig0, &aSig1); - } - else { - if (FLOAT_PI_HI <= aSig0) { - aSig0 -= FLOAT_PI_HI; - q = 1; - } - } - - shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); - if (! lt128(aSig0, aSig1, term0, term1)) - { - int lt = lt128(term0, term1, aSig0, aSig1); - int eq = eq128(aSig0, aSig1, term0, term1); - - if ((eq && (q & 1)) || lt) { - zSign = !zSign; - ++q; - } - if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, aSig0, aSig1, &aSig0, &aSig1); - } - - return (int)(q & 3); -} - -#define SIN_ARR_SIZE 11 -#define COS_ARR_SIZE 11 - -static float128 sin_arr[SIN_ARR_SIZE] = -{ - PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ - PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ - PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /* 5 */ - PACK_FLOAT_128(0xbff2a01a01a01a01, 0xa01a01a01a01a01a), /* 7 */ - PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /* 9 */ - PACK_FLOAT_128(0xbfe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */ - PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */ - PACK_FLOAT_128(0xbfd6ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 15 */ - PACK_FLOAT_128(0x3fce952c77030ad4, 0xa6b2605197771b00), /* 17 */ - PACK_FLOAT_128(0xbfc62f49b4681415, 0x724ca1ec3b7b9675), /* 19 */ - PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45) /* 21 */ -}; - -static float128 cos_arr[COS_ARR_SIZE] = -{ - PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ - PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ - PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /* 4 */ - PACK_FLOAT_128(0xbff56c16c16c16c1, 0x6c16c16c16c16c17), /* 6 */ - PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /* 8 */ - PACK_FLOAT_128(0xbfe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */ - PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */ - PACK_FLOAT_128(0xbfda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */ - PACK_FLOAT_128(0x3fd2ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 16 */ - PACK_FLOAT_128(0xbfca6827863b97d9, 0x77bb004886a2c2ab), /* 18 */ - PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb) /* 20 */ -}; - -extern float128 OddPoly (float128 x, float128 *arr, unsigned n); - -/* 0 <= x <= pi/4 */ -INLINE float128 poly_sin(float128 x) -{ - // 3 5 7 9 11 13 15 - // x x x x x x x - // sin (x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- = - // 3! 5! 7! 9! 11! 13! 15! - // - // 2 4 6 8 10 12 14 - // x x x x x x x - // = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- ] = - // 3! 5! 7! 9! 11! 13! 15! - // - // 3 3 - // -- 4k -- 4k+2 - // p(x) = > C * x > 0 q(x) = > C * x < 0 - // -- 2k -- 2k+1 - // k=0 k=0 - // - // 2 - // sin(x) ~ x * [ p(x) + x * q(x) ] - // - - return OddPoly(x, sin_arr, SIN_ARR_SIZE); -} - -extern float128 EvenPoly(float128 x, float128 *arr, unsigned n); - -/* 0 <= x <= pi/4 */ -INLINE float128 poly_cos(float128 x) -{ - // 2 4 6 8 10 12 14 - // x x x x x x x - // cos (x) ~ 1 - --- + --- - --- + --- - ---- + ---- - ---- - // 2! 4! 6! 8! 10! 12! 14! - // - // 3 3 - // -- 4k -- 4k+2 - // p(x) = > C * x > 0 q(x) = > C * x < 0 - // -- 2k -- 2k+1 - // k=0 k=0 - // - // 2 - // cos(x) ~ [ p(x) + x * q(x) ] - // - - return EvenPoly(x, cos_arr, COS_ARR_SIZE); -} - -INLINE void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) -{ - if (sin_a) *sin_a = a; - if (cos_a) *cos_a = a; -} - -INLINE void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) -{ - if (sin_a) *sin_a = a; - if (cos_a) *cos_a = floatx80_one; -} - -static floatx80 sincos_approximation(int neg, float128 r, UINT64 quotient) -{ - if (quotient & 0x1) { - r = poly_cos(r); - neg = 0; - } else { - r = poly_sin(r); - } - - floatx80 result = float128_to_floatx80(r); - if (quotient & 0x2) - neg = ! neg; - - if (neg) - result = floatx80_chs(result); - - return result; -} - -// ================================================= -// SFFSINCOS Compute sin(x) and cos(x) -// ================================================= - -// -// Uses the following identities: -// ---------------------------------------------------------- -// -// sin(-x) = -sin(x) -// cos(-x) = cos(x) -// -// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) -// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) -// -// sin(x+ pi/2) = cos(x) -// sin(x+ pi) = -sin(x) -// sin(x+3pi/2) = -cos(x) -// sin(x+2pi) = sin(x) -// - -int sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a) -{ - UINT64 aSig0, aSig1 = 0; - INT32 aExp, zExp, expDiff; - int aSign, zSign; - int q = 0; - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - /* invalid argument */ - if (aExp == 0x7FFF) { - if ((UINT64) (aSig0<<1)) { - sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOneArg(a)); - return 0; - } - - float_raise(float_flag_invalid); - sincos_invalid(sin_a, cos_a, floatx80_default_nan); - return 0; - } - - if (aExp == 0) { - if (aSig0 == 0) { - sincos_tiny_argument(sin_a, cos_a, a); - return 0; - } - -// float_raise(float_flag_denormal); - - /* handle pseudo denormals */ - if (! (aSig0 & U64(0x8000000000000000))) - { - float_raise(float_flag_inexact); - if (sin_a) - float_raise(float_flag_underflow); - sincos_tiny_argument(sin_a, cos_a, a); - return 0; - } - - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - - zSign = aSign; - zExp = EXP_BIAS; - expDiff = aExp - zExp; - - /* argument is out-of-range */ - if (expDiff >= 63) - return -1; - - float_raise(float_flag_inexact); - - if (expDiff < -1) { // doesn't require reduction - if (expDiff <= -68) { - a = packFloatx80(aSign, aExp, aSig0); - sincos_tiny_argument(sin_a, cos_a, a); - return 0; - } - zExp = aExp; - } - else { - q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); - } - - /* **************************** */ - /* argument reduction completed */ - /* **************************** */ - - /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); - - if (aSign) q = -q; - if (sin_a) *sin_a = sincos_approximation(zSign, r, q); - if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1); - - return 0; -} - -int floatx80_fsin(floatx80 &a) -{ - return sf_fsincos(a, &a, 0); -} - -int floatx80_fcos(floatx80 &a) -{ - return sf_fsincos(a, 0, &a); -} - -// ================================================= -// FPTAN Compute tan(x) -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// -// sin(-x) = -sin(x) -// cos(-x) = cos(x) -// -// sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y) -// cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y) -// -// sin(x+ pi/2) = cos(x) -// sin(x+ pi) = -sin(x) -// sin(x+3pi/2) = -cos(x) -// sin(x+2pi) = sin(x) -// -// 2. ---------------------------------------------------------- -// -// sin(x) -// tan(x) = ------ -// cos(x) -// - -int floatx80_ftan(floatx80 &a) -{ - UINT64 aSig0, aSig1 = 0; - INT32 aExp, zExp, expDiff; - int aSign, zSign; - int q = 0; - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - - /* invalid argument */ - if (aExp == 0x7FFF) { - if ((UINT64) (aSig0<<1)) - { - a = propagateFloatx80NaNOneArg(a); - return 0; - } - - float_raise(float_flag_invalid); - a = floatx80_default_nan; - return 0; - } - - if (aExp == 0) { - if (aSig0 == 0) return 0; -// float_raise(float_flag_denormal); - /* handle pseudo denormals */ - if (! (aSig0 & U64(0x8000000000000000))) - { - float_raise(float_flag_inexact | float_flag_underflow); - return 0; - } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - - zSign = aSign; - zExp = EXP_BIAS; - expDiff = aExp - zExp; - - /* argument is out-of-range */ - if (expDiff >= 63) - return -1; - - float_raise(float_flag_inexact); - - if (expDiff < -1) { // doesn't require reduction - if (expDiff <= -68) { - a = packFloatx80(aSign, aExp, aSig0); - return 0; - } - zExp = aExp; - } - else { - q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); - } - - /* **************************** */ - /* argument reduction completed */ - /* **************************** */ - - /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1); - - float128 sin_r = poly_sin(r); - float128 cos_r = poly_cos(r); - - if (q & 0x1) { - r = float128_div(cos_r, sin_r); - zSign = ! zSign; - } else { - r = float128_div(sin_r, cos_r); - } - - a = float128_to_floatx80(r); - if (zSign) - a = floatx80_chs(a); - - return 0; -} - -// 2 3 4 n -// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// -// -- 2k -- 2k+1 -// p(x) = > C * x q(x) = > C * x -// -- 2k -- 2k+1 -// -// f(x) ~ [ p(x) + x * q(x) ] -// - -float128 EvalPoly(float128 x, float128 *arr, unsigned n) -{ - float128 x2 = float128_mul(x, x); - unsigned i; - - assert(n > 1); - - float128 r1 = arr[--n]; - i = n; - while(i >= 2) { - r1 = float128_mul(r1, x2); - i -= 2; - r1 = float128_add(r1, arr[i]); - } - if (i) r1 = float128_mul(r1, x); - - float128 r2 = arr[--n]; - i = n; - while(i >= 2) { - r2 = float128_mul(r2, x2); - i -= 2; - r2 = float128_add(r2, arr[i]); - } - if (i) r2 = float128_mul(r2, x); - - return float128_add(r1, r2); -} - -// 2 4 6 8 2n -// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// -// -- 4k -- 4k+2 -// p(x) = > C * x q(x) = > C * x -// -- 2k -- 2k+1 -// -// 2 -// f(x) ~ [ p(x) + x * q(x) ] -// - -float128 EvenPoly(float128 x, float128 *arr, unsigned n) -{ - return EvalPoly(float128_mul(x, x), arr, n); -} - -// 3 5 7 9 2n+1 -// f(x) ~ (C * x) + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// 2 4 6 8 2n -// = x * [ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) -// 0 1 2 3 4 n -// -// -- 4k -- 4k+2 -// p(x) = > C * x q(x) = > C * x -// -- 2k -- 2k+1 -// -// 2 -// f(x) ~ x * [ p(x) + x * q(x) ] -// - -float128 OddPoly(float128 x, float128 *arr, unsigned n) -{ - return float128_mul(x, EvenPoly(x, arr, n)); -} - -/*---------------------------------------------------------------------------- -| Scales extended double-precision floating-point value in operand `a' by -| value `b'. The function truncates the value in the second operand 'b' to -| an integral value and adds that value to the exponent of the operand 'a'. -| The operation performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -extern floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ); - -floatx80 floatx80_scale(floatx80 a, floatx80 b) -{ - sbits32 aExp, bExp; - bits64 aSig, bSig; - - // handle unsupported extended double-precision floating encodings -/* if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(float_flag_invalid); - return floatx80_default_nan; - }*/ - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); - - if (aExp == 0x7FFF) { - if ((bits64) (aSig<<1) || ((bExp == 0x7FFF) && (bits64) (bSig<<1))) - { - return propagateFloatx80NaN(a, b); - } - if ((bExp == 0x7FFF) && bSign) { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((bits64) (bSig<<1)) return propagateFloatx80NaN(a, b); - if ((aExp | aSig) == 0) { - if (! bSign) { - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - return a; - } - if (aSig && (aExp == 0)) float_raise(float_flag_denormal); - if (bSign) return packFloatx80(aSign, 0, 0); - return packFloatx80(aSign, 0x7FFF, U64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) return a; - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return a; - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - - if (bExp > 0x400E) { - /* generate appropriate overflow/underflow */ - return roundAndPackFloatx80(80, aSign, - bSign ? -0x3FFF : 0x7FFF, aSig, 0); - } - if (bExp < 0x3FFF) return a; - - int shiftCount = 0x403E - bExp; - bSig >>= shiftCount; - sbits32 scale = bSig; - if (bSign) scale = -scale; /* -32768..32767 */ - return - roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0); -} diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/fyl2x.c b/source/src/vm/libcpu_newdev/libcpu_softfloat/fyl2x.c deleted file mode 100644 index 9599970d9..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/fyl2x.c +++ /dev/null @@ -1,484 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. -float_raise(float_flag_invalid) -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * Adapted for lib/softfloat in MESS by Hans Ostermeyer (03/2012) - * ==========================================================================*/ - -#define FLOAT128 - -#define USE_estimateDiv128To64 -#include "mamesf.h" -#include "softfloat.h" -//#include "softfloat-specialize" -#include "fpu_constant.h" - -static const floatx80 floatx80_log10_2 = packFloatx80(0, 0x3ffd, U64(0x9a209a84fbcff798)); -static const floatx80 floatx80_ln_2 = packFloatx80(0, 0x3ffe, U64(0xb17217f7d1cf79ac)); -static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, U64(0x8000000000000000)); -static const floatx80 floatx80_default_nan = packFloatx80(0, 0xffff, U64(0xffffffffffffffff)); - -#define packFloat_128(zHi, zLo) {(zHi), (zLo)} -#define PACK_FLOAT_128(hi,lo) packFloat_128(LIT64(hi),LIT64(lo)) - -#define EXP_BIAS 0x3FFF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -INLINE bits64 extractFloatx80Frac( floatx80 a ) -{ - return a.low; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -INLINE int32 extractFloatx80Exp( floatx80 a ) -{ - return a.high & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloatx80Sign( floatx80 a ) -{ - return a.high>>15; - -} - -/*---------------------------------------------------------------------------- -| Takes extended double-precision floating-point NaN `a' and returns the -| appropriate NaN result. If `a' is a signaling NaN, the invalid exception -| is raised. -*----------------------------------------------------------------------------*/ - -INLINE floatx80 propagateFloatx80NaNOneArg(floatx80 a) -{ - if (floatx80_is_signaling_nan(a)) - float_raise(float_flag_invalid); - - a.low |= U64(0xC000000000000000); - - return a; -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -INLINE void normalizeFloatx80Subnormal(UINT64 aSig, INT32 *zExpPtr, UINT64 *zSigPtr) -{ - int8_t shiftCount = countLeadingZeros64(aSig); - *zSigPtr = aSig< C * u q(u) = > C * u - // -- 2k -- 2k+1 - // k=0 k=0 - // - // 1+u 2 - // 1/2 ln --- ~ u * [ p(u) + u * q(u) ] - // 1-u - // -*/ - return OddPoly(x1, ln_arr, L2_ARR_SIZE); -} - -/* required sqrt(2)/2 < x < sqrt(2) */ -static float128 poly_l2(float128 x) -{ - /* using float128 for approximation */ - float128 x_p1 = float128_add(x, float128_one); - float128 x_m1 = float128_sub(x, float128_one); - x = float128_div(x_m1, x_p1); - x = poly_ln(x); - x = float128_mul(x, float128_ln2inv2); - return x; -} - -static float128 poly_l2p1(float128 x) -{ - /* using float128 for approximation */ - float128 x_p2 = float128_add(x, float128_two); - x = float128_div(x, x_p2); - x = poly_ln(x); - x = float128_mul(x, float128_ln2inv2); - return x; -} - -// ================================================= -// FYL2X Compute y * log (x) -// 2 -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// ln(x) -// log (x) = -------, ln (x*y) = ln(x) + ln(y) -// 2 ln(2) -// -// 2. ---------------------------------------------------------- -// 1+u x-1 -// ln (x) = ln -----, when u = ----- -// 1-u x+1 -// -// 3. ---------------------------------------------------------- -// 3 5 7 2n+1 -// 1+u u u u u -// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] -// 1-u 3 5 7 2n+1 -// - -static floatx80 fyl2x(floatx80 a, floatx80 b) -{ - UINT64 aSig = extractFloatx80Frac(a); - INT32 aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - UINT64 bSig = extractFloatx80Frac(b); - INT32 bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); - - int zSign = bSign ^ 1; - - if (aExp == 0x7FFF) { - if ((UINT64) (aSig<<1) - || ((bExp == 0x7FFF) && (UINT64) (bSig<<1))) - { - return propagateFloatx80NaN(a, b); - } - if (aSign) - { -invalid: - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(float_flag_denormal); - } - return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000)); - } - } - if (bExp == 0x7FFF) - { - if ((UINT64) (bSig<<1)) return propagateFloatx80NaN(a, b); - if (aSign && (UINT64)(aExp | aSig)) goto invalid; - if (aSig && (aExp == 0)) - float_raise(float_flag_denormal); - if (aExp < 0x3FFF) { - return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000)); - } - if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0)) goto invalid; - return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if ((bExp | bSig) == 0) goto invalid; - float_raise(float_flag_divbyzero); - return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000)); - } - if (aSign) goto invalid; - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (aSign) goto invalid; - if (bExp == 0) { - if (bSig == 0) { - if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); - return packFloatx80(bSign, 0, 0); - } - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0x3FFF && ((UINT64) (aSig<<1) == 0)) - return packFloatx80(bSign, 0, 0); - - float_raise(float_flag_inexact); - - int ExpDiff = aExp - 0x3FFF; - aExp = 0; - if (aSig >= SQRT2_HALF_SIG) { - ExpDiff++; - aExp--; - } - - /* ******************************** */ - /* using float128 for approximation */ - /* ******************************** */ - - UINT64 zSig0, zSig1; - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); - x = poly_l2(x); - x = float128_add(x, int64_to_float128((INT64) ExpDiff)); - return floatx80_mul(b, float128_to_floatx80(x)); -} - -// ================================================= -// FYL2XP1 Compute y * log (x + 1) -// 2 -// ================================================= - -// -// Uses the following identities: -// -// 1. ---------------------------------------------------------- -// ln(x) -// log (x) = ------- -// 2 ln(2) -// -// 2. ---------------------------------------------------------- -// 1+u x -// ln (x+1) = ln -----, when u = ----- -// 1-u x+2 -// -// 3. ---------------------------------------------------------- -// 3 5 7 2n+1 -// 1+u u u u u -// ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ] -// 1-u 3 5 7 2n+1 -// - -floatx80 fyl2xp1(floatx80 a, floatx80 b) -{ - INT32 aExp, bExp; - UINT64 aSig, bSig, zSig0, zSig1, zSig2; - int aSign, bSign; - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - int zSign = aSign ^ bSign; - - if (aExp == 0x7FFF) { - if ((UINT64) (aSig<<1) - || ((bExp == 0x7FFF) && (UINT64) (bSig<<1))) - { - return propagateFloatx80NaN(a, b); - } - if (aSign) - { -invalid: - float_raise(float_flag_invalid); - return floatx80_default_nan; - } - else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(float_flag_denormal); - } - return packFloatx80(bSign, 0x7FFF, U64(0x8000000000000000)); - } - } - if (bExp == 0x7FFF) - { - if ((UINT64) (bSig<<1)) - return propagateFloatx80NaN(a, b); - - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(float_flag_denormal); - } - - return packFloatx80(zSign, 0x7FFF, U64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - - float_raise(float_flag_inexact); - - if (aSign && aExp >= 0x3FFF) - return a; - - if (aExp >= 0x3FFC) // big argument - { - return fyl2x(floatx80_add(a, floatx80_one), b); - } - - // handle tiny argument - if (aExp < EXP_BIAS-70) - { - // first order approximation, return (a*b)/ln(2) - INT32 zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; - - mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (INT64) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - - zExp = zExp + bExp - 0x3FFE; - mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); - if (0 < (INT64) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - - return - roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1); - } - - /* ******************************** */ - /* using float128 for approximation */ - /* ******************************** */ - - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128(aSign, aExp, zSig0, zSig1); - x = poly_l2p1(x); - return floatx80_mul(b, float128_to_floatx80(x)); -} - -floatx80 floatx80_flognp1(floatx80 a) -{ - return fyl2xp1(a, floatx80_ln_2); -} - -floatx80 floatx80_flogn(floatx80 a) -{ - return fyl2x(a, floatx80_ln_2); -} - -floatx80 floatx80_flog2(floatx80 a) -{ - return fyl2x(a, floatx80_one); -} - -floatx80 floatx80_flog10(floatx80 a) -{ - return fyl2x(a, floatx80_log10_2); -} diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/mamesf.h b/source/src/vm/libcpu_newdev/libcpu_softfloat/mamesf.h deleted file mode 100644 index 7513e3702..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/mamesf.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -/*---------------------------------------------------------------------------- -| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. -*----------------------------------------------------------------------------*/ -#ifdef LSB_FIRST -#define LITTLEENDIAN -#else -#define BIGENDIAN -#endif - -/*---------------------------------------------------------------------------- -| The macro `BITS64' can be defined to indicate that 64-bit integer types are -| supported by the compiler. -*----------------------------------------------------------------------------*/ -#define BITS64 - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines the most convenient type that holds -| integers of at least as many bits as specified. For example, `uint8' should -| be the most convenient type that can hold unsigned integers of as many as -| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most -| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed -| to the same as `int'. -*----------------------------------------------------------------------------*/ -//#include "emu.h" - -typedef INT8 flag; -typedef UINT8 uint8; -typedef INT8 int8; -typedef UINT16 uint16; -typedef INT16 int16; -typedef UINT32 uint32; -typedef INT32 int32; -typedef UINT64 uint64; -typedef INT64 int64; - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines a type that holds integers -| of _exactly_ the number of bits specified. For instance, for most -| implementation of C, `bits16' and `sbits16' should be `typedef'ed to -| `unsigned short int' and `signed short int' (or `short int'), respectively. -*----------------------------------------------------------------------------*/ -typedef UINT8 bits8; -typedef INT8 sbits8; -typedef UINT16 bits16; -typedef INT16 sbits16; -typedef UINT32 bits32; -typedef INT32 sbits32; -typedef UINT64 bits64; -typedef INT64 sbits64; - -/*---------------------------------------------------------------------------- -| The `LIT64' macro takes as its argument a textual integer literal and -| if necessary ``marks'' the literal as having a 64-bit integer type. -| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be -| appended with the letters `LL' standing for `long long', which is `gcc's -| name for the 64-bit integer type. Some compilers may allow `LIT64' to be -| defined as the identity macro: `#define LIT64( a ) a'. -*----------------------------------------------------------------------------*/ -#define LIT64( a ) a##ULL - -/*---------------------------------------------------------------------------- -| The macro `INLINE' can be used before functions that should be inlined. If -| a compiler does not support explicit inlining, this macro should be defined -| to be `static'. -*----------------------------------------------------------------------------*/ -// MAME defines INLINE diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/milieu.h b/source/src/vm/libcpu_newdev/libcpu_softfloat/milieu.h deleted file mode 100644 index 10687b755..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/milieu.h +++ /dev/null @@ -1,42 +0,0 @@ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Include common integer types and flags. -*----------------------------------------------------------------------------*/ -#include "mamesf.h" - -/*---------------------------------------------------------------------------- -| Symbolic Boolean literals. -*----------------------------------------------------------------------------*/ -#define FALSE 0 -#define TRUE 1 diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/readme_takeda.txt b/source/src/vm/libcpu_newdev/libcpu_softfloat/readme_takeda.txt deleted file mode 100644 index 6f24f6ec6..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/readme_takeda.txt +++ /dev/null @@ -1 +0,0 @@ -Based on MAME 0.152. diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-macros b/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-macros deleted file mode 100644 index f58a30472..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-macros +++ /dev/null @@ -1,732 +0,0 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) -{ - bits32 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 32 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) -{ - bits64 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 64 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -INLINE void - shift64ExtraRightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else { - z1 = ( ( a0 | a1 ) != 0 ); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shift128Right( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ); - z0 = a0>>count; - } - else { - z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shift128RightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ) | ( ( a1<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else if ( count < 128 ) { - z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); - z0 = a0>>count; - } - else { - if ( count == 64 ) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if ( count < 128 ) { - z2 = a0<>( count & 63 ); - } - else { - z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); - z1 = 0; - } - } - z0 = 0; - } - z2 |= ( a2 != 0 ); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' must be less than 64. The result is broken into two 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shortShift128Left( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1<>( ( - count ) & 63 ) ); - -} - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left -| by the number of bits given in `count'. Any bits shifted off are lost. -| The value of `count' must be less than 64. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - shortShift192Left( - bits64 a0, - bits64 a1, - bits64 a2, - int16 count, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 negCount; - - z2 = a2<>negCount; - z0 |= a1>>negCount; - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - add128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z1; - - z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + ( z1 < a1 ); - -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - add192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - uint8 carry0, carry1; - - z2 = a2 + b2; - carry1 = ( z2 < a2 ); - z1 = a1 + b1; - carry0 = ( z1 < a1 ); - z0 = a0 + b0; - z1 += carry1; - z0 += ( z1 < carry1 ); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - sub128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - ( a1 < b1 ); - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - sub192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - uint8 borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = ( a2 < b2 ); - z1 = a1 - b1; - borrow0 = ( a1 < b1 ); - z0 = a0 - b0; - z0 -= ( z1 < borrow1 ); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits32 aHigh, aLow, bHigh, bLow; - bits64 z0, zMiddleA, zMiddleB, z1; - - aLow = a; - aHigh = a>>32; - bLow = b; - bHigh = b>>32; - z1 = ( (bits64) aLow ) * bLow; - zMiddleA = ( (bits64) aLow ) * bHigh; - zMiddleB = ( (bits64) aHigh ) * bLow; - z0 = ( (bits64) aHigh ) * bHigh; - zMiddleA += zMiddleB; - z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += ( z1 < zMiddleA ); - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - mul128By64To192( - bits64 a0, - bits64 a1, - bits64 b, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2, more1; - - mul64To128( a1, b, &z1, &z2 ); - mul64To128( a0, b, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -INLINE void - mul128To256( - bits64 a0, - bits64 a1, - bits64 b0, - bits64 b1, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr, - bits64 *z3Ptr - ) -{ - bits64 z0, z1, z2, z3; - bits64 more1, more2; - - mul64To128( a1, b1, &z2, &z3 ); - mul64To128( a1, b0, &z1, &more2 ); - add128( z1, more2, 0, z2, &z1, &z2 ); - mul64To128( a0, b0, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - mul64To128( a0, b1, &more1, &more2 ); - add128( more1, more2, 0, z2, &more1, &z2 ); - add128( z0, z1, 0, more1, &z0, &z1 ); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -INLINE bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) -{ - bits64 b0, b1; - bits64 rem0, rem1, term0, term1; - bits64 z; - - if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); - b0 = b>>32; - z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; - mul64To128( b, z, &term0, &term1 ); - sub128( a0, a1, term0, term1, &rem0, &rem1 ); - while ( ( (sbits64) rem0 ) < 0 ) { - z -= LIT64( 0x100000000 ); - b1 = b<<32; - add128( rem0, rem1, b0, b1, &rem0, &rem1 ); - } - rem0 = ( rem0<<32 ) | ( rem1>>32 ); - z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -INLINE bits32 estimateSqrt32( int16 aExp, bits32 a ) -{ - static const bits16 sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const bits16 sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - int8 index; - bits32 z; - - index = ( a>>27 ) & 15; - if ( aExp & 1 ) { - z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; - z = ( ( a / z )<<14 ) + ( z<<15 ); - a >>= 1; - } - else { - z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; - z = a / z + z; - z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); - if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); - } - return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros32( bits32 a ) -{ - static const int8 countLeadingZerosHigh[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - int8 shiftCount; - - shiftCount = 0; - if ( a < 0x10000 ) { - shiftCount += 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZerosHigh[ a>>24 ]; - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros64( bits64 a ) -{ - int8 shiftCount; - - shiftCount = 0; - if ( a < ( (bits64) 1 )<<32 ) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32( a ); - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 == b0 ) && ( a1 == b1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is -| not equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 != b0 ) || ( a1 != b1 ); - -} - -/*----------------------------------------------------------------------------- -| Changes the sign of the extended double-precision floating-point value 'a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -INLINE floatx80 floatx80_chs(floatx80 reg) -{ - reg.high ^= 0x8000; - return reg; -} - diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-specialize b/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-specialize deleted file mode 100644 index 8d8ad9675..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat-specialize +++ /dev/null @@ -1,471 +0,0 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Underflow tininess-detection mode, statically initialized to default value. -| (The declaration in `softfloat.h' must match the `int8' type here.) -*----------------------------------------------------------------------------*/ -int8 float_detect_tininess = float_tininess_after_rounding; - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap to -| substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void float_raise( int8 flags ) -{ - - float_exception_flags |= flags; - -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - bits64 high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define float32_default_nan 0xFFFFFFFF - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_nan( float32 a ) -{ - - return ( 0xFF000000 < (bits32) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_signaling_nan( float32 a ) -{ - - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float32ToCommonNaN( float32 a ) -{ - commonNaNT z; - - if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>31; - z.low = 0; - z.high = ( (bits64) a )<<41; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float32 commonNaNToFloat32( commonNaNT a ) -{ - - return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32NaN( float32 a, float32 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float32_is_nan( a ); - aIsSignalingNaN = float32_is_signaling_nan( a ); - bIsNaN = float32_is_nan( b ); - bIsSignalingNaN = float32_is_signaling_nan( b ); - a |= 0x00400000; - b |= 0x00400000; - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_nan( float64 a ) -{ - - return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_signaling_nan( float64 a ) -{ - - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN( float64 a ) -{ - commonNaNT z; - - if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>63; - z.low = 0; - z.high = a<<12; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64( commonNaNT a ) -{ - - return - ( ( (bits64) a.sign )<<63 ) - | LIT64( 0x7FF8000000000000 ) - | ( a.high>>12 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN( float64 a, float64 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float64_is_nan( a ); - aIsSignalingNaN = float64_is_signaling_nan( a ); - bIsNaN = float64_is_nan( b ); - bIsSignalingNaN = float64_is_signaling_nan( b ); - a |= LIT64( 0x0008000000000000 ); - b |= LIT64( 0x0008000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_high 0xFFFF -#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ -#if 0 -flag floatx80_is_nan( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); - -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_signaling_nan( floatx80 a ) -{ - bits64 aLow; - - aLow = a.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( a.high & 0x7FFF ) == 0x7FFF ) - && (bits64) ( aLow<<1 ) - && ( a.low == aLow ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN( floatx80 a ) -{ - commonNaNT z; - - if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>15; - z.low = 0; - z.high = a.low<<1; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80( commonNaNT a ) -{ - floatx80 z; - - z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); - z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ -#if 0 -floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = floatx80_is_nan( a ); - aIsSignalingNaN = floatx80_is_signaling_nan( a ); - bIsNaN = floatx80_is_nan( b ); - bIsSignalingNaN = floatx80_is_signaling_nan( b ); - a.low |= LIT64( 0xC000000000000000 ); - b.low |= LIT64( 0xC000000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} -#endif -#define EXP_BIAS 0x3FFF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ -#if 0 -INLINE bits64 extractFloatx80Frac( floatx80 a ) -{ - - return a.low; - -} -#endif -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ -#if 0 -INLINE int32 extractFloatx80Exp( floatx80 a ) -{ - - return a.high & 0x7FFF; - -} -#endif -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ -#if 0 -INLINE flag extractFloatx80Sign( floatx80 a ) -{ - - return a.high>>15; - -} -#endif -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) -#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_nan( float128 a ) -{ - - return - ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) - && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_signaling_nan( float128 a ) -{ - - return - ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) - && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN( float128 a ) -{ - commonNaNT z; - - if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>63; - shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128( commonNaNT a ) -{ - float128 z; - - shift128Right( a.high, a.low, 16, &z.high, &z.low ); - z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN( float128 a, float128 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float128_is_nan( a ); - aIsSignalingNaN = float128_is_signaling_nan( a ); - bIsNaN = float128_is_nan( b ); - bIsSignalingNaN = float128_is_signaling_nan( b ); - a.high |= LIT64( 0x0000800000000000 ); - b.high |= LIT64( 0x0000800000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#endif - diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.c b/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.c deleted file mode 100644 index e756dd67f..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.c +++ /dev/null @@ -1,4941 +0,0 @@ - -/*============================================================================ - -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "milieu.h" -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, extended double-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ -int8 float_exception_flags = 0; -#ifdef FLOATX80 -int8 floatx80_rounding_precision = 80; -#endif - -int8 float_rounding_mode = float_round_nearest_even; - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - z = absZ; - if ( zSign ) z = - z; - if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_raise( float_flag_invalid ); - return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) -{ - int8 roundingMode; - flag roundNearestEven, increment; - int64 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) absZ1 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && absZ1; - } - else { - increment = ( roundingMode == float_round_up ) && absZ1; - } - } - } - if ( increment ) { - ++absZ0; - if ( absZ0 == 0 ) goto overflow; - absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); - } - z = absZ0; - if ( zSign ) z = - z; - if ( z && ( ( z < 0 ) ^ zSign ) ) { - overflow: - float_raise( float_flag_invalid ); - return - zSign ? (sbits64) LIT64( 0x8000000000000000 ) - : LIT64( 0x7FFFFFFFFFFFFFFF ); - } - if ( absZ1 ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE bits32 extractFloat32Frac( float32 a ) -{ - return a & 0x007FFFFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE int16 extractFloat32Exp( float32 a ) -{ - return ( a>>23 ) & 0xFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat32Sign( float32 a ) -{ - return a>>31; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( aSig ) - 8; - *zSigPtr = aSig<>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat64Sign( float64 a ) -{ - return a>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ) - 11; - *zSigPtr = aSig<>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -INLINE flag extractFloat128Sign( float128 a ) -{ - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat128Subnormal( - bits64 aSig0, - bits64 aSig1, - int32 *zExpPtr, - bits64 *zSig0Ptr, - bits64 *zSig1Ptr - ) -{ - int8 shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>( - shiftCount ); - if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64, aSigExtra; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = 0xBE - aExp; - if ( shiftCount < 0 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - if ( aExp ) aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); - return roundAndPackInt64( aSign, aSig64, aSigExtra ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64_round_to_zero( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64; - int64 z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0xBE; - if ( 0 <= shiftCount ) { - if ( a != 0xDF000000 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>( - shiftCount ); - if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); - return packFloat64( aSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float32_to_floatx80( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - aSig |= 0x00800000; - return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 lastBitMask, roundBitsMask; - int8 roundingMode; - float32 z; - - aExp = extractFloat32Exp( a ); - if ( 0x96 <= aExp ) { - if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN( a, a ); - } - return a; - } - if ( aExp <= 0x7E ) { - if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_down: - return aSign ? 0xBF800000 : 0; - case float_round_up: - return aSign ? 0x80000000 : 0x3F800000; - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if ( 0 < expDiff ) { - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x20000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x20000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits32) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign ^ 1, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x40000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x40000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); - } - else { - return subFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); - } - else { - return addFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig; - bits64 zSig64; - bits32 zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x7F; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); - zSig = zSig64; - if ( 0 <= (sbits32) ( zSig<<1 ) ) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat32( zSign, 0xFF, 0 ); - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x7D; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = ( ( (bits64) aSig )<<32 ) / bSig; - if ( ( zSig & 0x3F ) == 0 ) { - zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the single-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_rem( float32 a, float32 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits32 aSig, bSig; - bits32 q; - bits64 aSig64, bSig64, q64; - bits32 alternateASig; - sbits32 sigMean; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); -// bSign = extractFloat32Sign( b ); - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig |= 0x00800000; - bSig |= 0x00800000; - if ( expDiff < 32 ) { - aSig <<= 8; - bSig <<= 8; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - if ( 0 < expDiff ) { - q = ( ( (bits64) aSig )<<32 ) / bSig; - q >>= 32 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - } - else { - if ( bSig <= aSig ) aSig -= bSig; - aSig64 = ( (bits64) aSig )<<40; - bSig64 = ( (bits64) bSig )<<40; - expDiff -= 64; - while ( 0 < expDiff ) { - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - aSig64 = - ( ( bSig * q64 )<<38 ); - expDiff -= 62; - } - expDiff += 64; - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - q = q64>>( 64 - expDiff ); - bSig <<= 6; - aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits32) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits32) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt( float32 a ) -{ - flag aSign; - int16 aExp, zExp; - bits32 aSig, zSig; - bits64 rem, term; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, 0 ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; - aSig = ( aSig | 0x00800000 )<<8; - zSig = estimateSqrt32( aExp, aSig ) + 2; - if ( ( zSig & 0x7F ) <= 5 ) { - if ( zSig < 2 ) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ( (bits64) zSig ) * zSig; - rem = ( ( (bits64) aSig )<<32 ) - term; - while ( (sbits64) rem < 0 ) { - --zSig; - rem += ( ( (bits64) zSig )<<1 ) | 1; - } - zSig |= ( rem != 0 ); - } - shift32RightJamming( zSig, 1, &zSig ); - roundAndPack: - return roundAndPackFloat32( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq_signaling( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x42C - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32_round_to_zero( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x41E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - bits32 zSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 22, &aSig ); - zSig = aSig; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float64_to_floatx80( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - return - packFloatx80( - aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float64 z; - - aExp = extractFloat64Exp( a ); - if ( 0x433 <= aExp ) { - if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (bits64) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_down: - return aSign ? LIT64( 0xBFF0000000000000 ) : 0; - case float_round_up: - return - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if ( 0 < expDiff ) { - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); - zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64( 0x2000000000000000 ); - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits64) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign ^ 1, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - bSig |= LIT64( 0x4000000000000000 ); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - aSig |= LIT64( 0x4000000000000000 ); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); - } - else { - return subFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); - } - else { - return addFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FF; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - zSig0 |= ( zSig1 != 0 ); - if ( 0 <= (sbits64) ( zSig0<<1 ) ) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64( zSign, zExp, zSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - bits64 rem0, rem1; - bits64 term0, term1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat64( zSign, 0x7FF, 0 ); - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FD; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64( aSig, 0, bSig ); - if ( ( zSig & 0x1FF ) <= 2 ) { - mul64To128( bSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig |= ( rem1 != 0 ); - } - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_rem( float64 a, float64 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits64 aSig, bSig; - bits64 q, alternateASig; - sbits64 sigMean; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); -// bSign = extractFloat64Sign( b ); - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - aSig = - ( ( bSig>>2 ) * q ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits64) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits64) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt( float64 a ) -{ - flag aSign; - int16 aExp, zExp; - bits64 aSig, zSig, doubleZSig; - bits64 rem0, rem1, term0, term1; -// float64 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, a ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; - aSig |= LIT64( 0x0010000000000000 ); - zSig = estimateSqrt32( aExp, aSig>>21 ); - aSig <<= 9 - ( aExp & 1 ); - zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); - if ( ( zSig & 0x1FF ) <= 5 ) { - doubleZSig = zSig<<1; - mul64To128( zSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - doubleZSig -= 2; - add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); - } - zSig |= ( ( rem0 | rem1 ) != 0 ); - } - return roundAndPackFloat64( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The invalid exception is raised -| if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq_signaling( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic---which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN, the -| largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - shiftCount = 0x4037 - aExp; - if ( shiftCount <= 0 ) shiftCount = 1; - shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN, the largest positive integer is returned. -| Otherwise, if the conversion overflows, the largest integer with the same -| sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_round_to_zero( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128( floatx80 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); - } - shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended quadruple-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp( a ); - if ( 0x403E <= aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { - return propagateFloatx80NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FFF ) { - if ( ( aExp == 0 ) - && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { - return a; - } - float_exception_flags |= float_flag_inexact; - aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) - ) { - return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - break; - case float_round_down: - return - aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) - : packFloatx80( 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - return packFloatx80( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.low += lastBitMask>>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (sbits64) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (sbits64) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - bits64 rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (bits64) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig; - bits64 q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); -// bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (bits64) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32( aSign, aSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1, savedASig; - int32 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (bits64) ( aSig1<>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - bits32 zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64( aSign, aExp, aSig0 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN( a, a ); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (sbits64) z.low < 0 ) { - ++z.high; - if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); - } - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem( float128 a, float128 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - bits64 allZero, alternateASig0, alternateASig1, sigMean1; - sbits64 sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); -// bSign = extractFloat128Sign( b ); - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return a; - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - expDiff = aExp - bExp; - if ( expDiff < -1 ) return a; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), - aSig1, - 15 - ( expDiff < 0 ), - &aSig0, - &aSig1 - ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - q = le128( bSig0, bSig1, aSig0, aSig1 ); - if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); - shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); - sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); - expDiff -= 61; - } - if ( -64 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - q >>= - expDiff; - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - expDiff += 52; - if ( expDiff < 0 ) { - shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - } - else { - shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); - } - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); - } - else { - shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - } while ( 0 <= (sbits64) aSig0 ); - add128( - aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 ); - if ( ( sigMean0 < 0 ) - || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ( (sbits64) aSig0 < 0 ); - if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); - return - normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt( float128 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, aSig0>>17 ); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq_signaling( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif diff --git a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.h b/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.h deleted file mode 100644 index aa5669137..000000000 --- a/source/src/vm/libcpu_newdev/libcpu_softfloat/softfloat.h +++ /dev/null @@ -1,461 +0,0 @@ -#pragma once - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the extended double-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#define FLOATX80 -#define FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -typedef bits32 float32; -typedef bits64 float64; -#ifdef FLOATX80 -typedef struct { - bits16 high; - bits64 low; -} floatx80; -#endif -#ifdef FLOAT128 -typedef struct { - bits64 high, low; -} float128; -#endif - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target if -| desired.) -*----------------------------------------------------------------------------*/ -#include "softfloat-macros" - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -extern int8 float_detect_tininess; -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -extern int8 float_rounding_mode; -enum { - float_round_nearest_even = 0, - float_round_to_zero = 1, - float_round_down = 2, - float_round_up = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -extern int8 float_exception_flags; -enum { - float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, - float_flag_underflow = 0x10, float_flag_inexact = 0x20 -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -void float_raise( int8 ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int32 ); -float64 int32_to_float64( int32 ); -#ifdef FLOATX80 -floatx80 int32_to_floatx80( int32 ); -#endif -#ifdef FLOAT128 -float128 int32_to_float128( int32 ); -#endif -float32 int64_to_float32( int64 ); -float64 int64_to_float64( int64 ); -#ifdef FLOATX80 -floatx80 int64_to_floatx80( int64 ); -#endif -#ifdef FLOAT128 -float128 int64_to_float128( int64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float32_to_int32( float32 ); -int32 float32_to_int32_round_to_zero( float32 ); -int64 float32_to_int64( float32 ); -int64 float32_to_int64_round_to_zero( float32 ); -float64 float32_to_float64( float32 ); -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 ); -#endif -#ifdef FLOAT128 -float128 float32_to_float128( float32 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); -flag float32_eq( float32, float32 ); -flag float32_le( float32, float32 ); -flag float32_lt( float32, float32 ); -flag float32_eq_signaling( float32, float32 ); -flag float32_le_quiet( float32, float32 ); -flag float32_lt_quiet( float32, float32 ); -flag float32_is_signaling_nan( float32 ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float64_to_int32( float64 ); -int32 float64_to_int32_round_to_zero( float64 ); -int64 float64_to_int64( float64 ); -int64 float64_to_int64_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 ); -#endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); -flag float64_eq( float64, float64 ); -flag float64_le( float64, float64 ); -flag float64_lt( float64, float64 ); -flag float64_eq_signaling( float64, float64 ); -flag float64_le_quiet( float64, float64 ); -flag float64_lt_quiet( float64, float64 ); -flag float64_is_signaling_nan( float64 ); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 floatx80_to_int32( floatx80 ); -int32 floatx80_to_int32_round_to_zero( floatx80 ); -int64 floatx80_to_int64( floatx80 ); -int64 floatx80_to_int64_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); -#ifdef FLOAT128 -float128 floatx80_to_float128( floatx80 ); -#endif -floatx80 floatx80_scale(floatx80 a, floatx80 b); - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an -| extended double-precision floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) -{ - floatx80 z; - - z.low = zSig; - z.high = ( ( (bits16) zSign )<<15 ) + zExp; - return z; - -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision rounding precision. Valid -| values are 32, 64, and 80. -*----------------------------------------------------------------------------*/ -extern int8 floatx80_rounding_precision; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); -flag floatx80_eq( floatx80, floatx80 ); -flag floatx80_le( floatx80, floatx80 ); -flag floatx80_lt( floatx80, floatx80 ); -flag floatx80_eq_signaling( floatx80, floatx80 ); -flag floatx80_le_quiet( floatx80, floatx80 ); -flag floatx80_lt_quiet( floatx80, floatx80 ); -flag floatx80_is_signaling_nan( floatx80 ); - -int floatx80_fsin(floatx80 &a); -int floatx80_fcos(floatx80 &a); -int floatx80_ftan(floatx80 &a); - -floatx80 floatx80_flognp1(floatx80 a); -floatx80 floatx80_flogn(floatx80 a); -floatx80 floatx80_flog2(floatx80 a); -floatx80 floatx80_flog10(floatx80 a); - -// roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c -floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1); - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float128_to_int32( float128 ); -int32 float128_to_int32_round_to_zero( float128 ); -int64 float128_to_int64( float128 ); -int64 float128_to_int64_round_to_zero( float128 ); -float32 float128_to_float32( float128 ); -float64 float128_to_float64( float128 ); -#ifdef FLOATX80 -floatx80 float128_to_floatx80( float128 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int( float128 ); -float128 float128_add( float128, float128 ); -float128 float128_sub( float128, float128 ); -float128 float128_mul( float128, float128 ); -float128 float128_div( float128, float128 ); -float128 float128_rem( float128, float128 ); -float128 float128_sqrt( float128 ); -flag float128_eq( float128, float128 ); -flag float128_le( float128, float128 ); -flag float128_lt( float128, float128 ); -flag float128_eq_signaling( float128, float128 ); -flag float128_le_quiet( float128, float128 ); -flag float128_lt_quiet( float128, float128 ); -flag float128_is_signaling_nan( float128 ); - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', the exponent `zExp', and the significand formed -| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision -| floating-point value, returning the result. After being shifted into the -| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply -| added together to form the most significant 32 bits of the result. This -| means that any integer portion of `zSig0' will be added into the exponent. -| Since a properly normalized significand will have an integer portion equal -| to 1, the `zExp' input should be 1 less than the desired result exponent -| whenever `zSig0' and `zSig1' concatenated form a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -INLINE float128 - packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) -{ - float128 z; - - z.low = zSig1; - z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -INLINE float128 - roundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 ) -{ - int8 roundingMode; - flag roundNearestEven, increment, isTiny; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) zSig2 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - if ( 0x7FFD <= (bits32) zExp ) { - if ( ( 0x7FFD < zExp ) - || ( ( zExp == 0x7FFD ) - && eq128( - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ), - zSig0, - zSig1 - ) - && increment - ) - ) { - float_raise( float_flag_overflow | float_flag_inexact ); - if ( ( roundingMode == float_round_to_zero ) - || ( zSign && ( roundingMode == float_round_up ) ) - || ( ! zSign && ( roundingMode == float_round_down ) ) - ) { - return - packFloat128( - zSign, - 0x7FFE, - LIT64( 0x0000FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( zExp < 0 ) { - isTiny = - ( float_detect_tininess == float_tininess_before_rounding ) - || ( zExp < -1 ) - || ! increment - || lt128( - zSig0, - zSig1, - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); - zExp = 0; - if ( isTiny && zSig2 ) float_raise( float_flag_underflow ); - if ( roundNearestEven ) { - increment = ( (sbits64) zSig2 < 0 ); - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - } - if ( zSig2 ) float_exception_flags |= float_flag_inexact; - if ( increment ) { - add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); - zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); - } - else { - if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; - } - return packFloat128( zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -INLINE float128 - normalizeRoundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) -{ - int8 shiftCount; - bits64 zSig2; - - if ( zSig0 == 0 ) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - shiftCount = countLeadingZeros64( zSig0 ) - 15; - if ( 0 <= shiftCount ) { - zSig2 = 0; - shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); - } - else { - shift128ExtraRightJamming( - zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); - } - zExp -= shiftCount; - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} -#endif -- 2.11.0