OSDN Git Service

[VM][I386] TRY: Import from DOSBOX(J3100) v.2019-05-20.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Tue, 21 May 2019 07:17:01 +0000 (16:17 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Tue, 21 May 2019 07:17:01 +0000 (16:17 +0900)
109 files changed:
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile.am [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile.in [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/cache.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/decoder.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/dyn_fpu.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/dyn_fpu_dh.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/helpers.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/risc_x86.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/string.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile.am [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile.in [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/cache.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder_basic.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder_opcodes.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/dyn_fpu.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/operators.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-common.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-o3.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-s3.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb-iw.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb-niw.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_mipsel32.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_x64.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_x86.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile.am [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile.in [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/ea_lookup.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/load.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/loadwrite.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/op.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/optable.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/save.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/string.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_full/support.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile.am [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile.in [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/helpers.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_0f.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_66.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_66_0f.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_none.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/string.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/support.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_normal/table_ea.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_prefetch.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/core_simple.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/cpu.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/flags.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile.am [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile.in [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/bios.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/bios_disk.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/callback.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/control.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/cpu.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/cross.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/debug.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/dma.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/dos_inc.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/dos_system.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/dosbox.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/dosv.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/fpu.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/hardware.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/inout.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/ipx.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/ipxserver.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/j3.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/jega.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/jfont.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/joystick.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/keyboard.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/logging.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/mapper.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/mem.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/midi.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/mixer.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/modules.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/mouse.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/paging.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/pci_bus.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/pic.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/programs.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/regs.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/render.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/serialport.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/setup.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/shell.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/support.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/timer.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/vga.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/include/video.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/instructions.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/lazyflags.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/modrm.cpp [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/modrm.h [new file with mode: 0644]
source/src/vm/libcpu_newdev/dosbox-i386/paging.cpp [new file with mode: 0644]

diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86.cpp
new file mode 100644 (file)
index 0000000..0045394
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "dosbox.h"
+
+#if (C_DYNAMIC_X86)
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#if defined (WIN32)
+#include <windows.h>
+#include <winbase.h>
+#endif
+
+#if (C_HAVE_MPROTECT)
+#include <sys/mman.h>
+
+#include <limits.h>
+#ifndef PAGESIZE
+#define PAGESIZE 4096
+#endif
+#endif /* C_HAVE_MPROTECT */
+
+#include "callback.h"
+#include "regs.h"
+#include "mem.h"
+#include "cpu.h"
+#include "debug.h"
+#include "paging.h"
+#include "inout.h"
+#include "fpu.h"
+
+#define CACHE_MAXSIZE  (4096*3)
+#define CACHE_TOTAL            (1024*1024*8)
+#define CACHE_PAGES            (512)
+#define CACHE_BLOCKS   (64*1024)
+#define CACHE_ALIGN            (16)
+#define DYN_HASH_SHIFT (4)
+#define DYN_PAGE_HASH  (4096>>DYN_HASH_SHIFT)
+#define DYN_LINKS              (16)
+
+//#define DYN_LOG 1 //Turn logging on
+
+
+#if C_FPU
+#define CPU_FPU 1                                               //Enable FPU escape instructions
+#endif
+
+enum {
+       G_EAX,G_ECX,G_EDX,G_EBX,
+       G_ESP,G_EBP,G_ESI,G_EDI,
+       G_ES,G_CS,G_SS,G_DS,G_FS,G_GS,
+       G_FLAGS,G_NEWESP,G_EIP,
+       G_EA,G_STACK,G_CYCLES,
+       G_TMPB,G_TMPW,G_SHIFT,
+       G_EXIT,
+       G_MAX,
+};
+
+enum SingleOps {
+       SOP_INC,SOP_DEC,
+       SOP_NOT,SOP_NEG,
+};
+
+enum DualOps {
+       DOP_ADD,DOP_ADC,
+       DOP_SUB,DOP_SBB,
+       DOP_CMP,DOP_XOR,
+       DOP_AND,DOP_OR,
+       DOP_TEST,
+       DOP_MOV,
+       DOP_XCHG,
+};
+
+enum ShiftOps {
+       SHIFT_ROL,SHIFT_ROR,
+       SHIFT_RCL,SHIFT_RCR,
+       SHIFT_SHL,SHIFT_SHR,
+       SHIFT_SAL,SHIFT_SAR,
+};
+
+enum BranchTypes {
+       BR_O,BR_NO,BR_B,BR_NB,
+       BR_Z,BR_NZ,BR_BE,BR_NBE,
+       BR_S,BR_NS,BR_P,BR_NP,
+       BR_L,BR_NL,BR_LE,BR_NLE
+};
+
+
+enum BlockReturn {
+       BR_Normal=0,
+       BR_Cycles,
+       BR_Link1,BR_Link2,
+       BR_Opcode,
+#if (C_DEBUG)
+       BR_OpcodeFull,
+#endif
+       BR_Iret,
+       BR_CallBack,
+       BR_SMCBlock
+};
+
+#define SMC_CURRENT_BLOCK      0xffff
+
+
+#define DYNFLG_HAS16           0x1             //Would like 8-bit host reg support
+#define DYNFLG_HAS8                    0x2             //Would like 16-bit host reg support
+#define DYNFLG_LOAD                    0x4             //Load value when accessed
+#define DYNFLG_SAVE                    0x8             //Needs to be saved back at the end of block
+#define DYNFLG_CHANGED         0x10    //Value is in a register and changed from load
+#define DYNFLG_ACTIVE          0x20    //Register has an active value
+
+class GenReg;
+class CodePageHandler;
+
+struct DynReg {
+       Bitu flags;
+       GenReg * genreg;
+       void * data;
+}; 
+
+enum DynAccess {
+       DA_d,DA_w,
+       DA_bh,DA_bl
+};
+
+enum ByteCombo {
+       BC_ll,BC_lh,
+       BC_hl,BC_hh,
+};
+
+static DynReg DynRegs[G_MAX];
+#define DREG(_WHICH_) &DynRegs[G_ ## _WHICH_ ]
+
+static struct {
+       Bitu ea,tmpb,tmpd,stack,shift,newesp;
+} extra_regs;
+
+static void IllegalOption(const char* msg) {
+       E_Exit("DynCore: illegal option in %s",msg);
+}
+
+#include "core_dyn_x86/cache.h" 
+
+static struct {
+       Bitu callback;
+       Bit32u readdata;
+} core_dyn;
+
+static struct {
+       Bit32u          state[32];
+       FPU_P_Reg       temp,temp2;
+       Bit32u          dh_fpu_enabled;
+       Bit32u          state_used;
+       Bit32u          cw,host_cw;
+       Bit8u           temp_state[128];
+} dyn_dh_fpu;
+
+
+#include "core_dyn_x86/risc_x86.h"
+
+struct DynState {
+       DynReg regs[G_MAX];
+};
+
+static void dyn_flags_host_to_gen(void) {
+       gen_dop_word(DOP_MOV,true,DREG(EXIT),DREG(FLAGS));
+       gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST);
+       gen_load_flags(DREG(EXIT));
+       gen_releasereg(DREG(EXIT));
+       gen_releasereg(DREG(FLAGS));
+}
+
+static void dyn_flags_gen_to_host(void) {
+       gen_save_flags(DREG(EXIT));
+       gen_dop_word_imm(DOP_AND,true,DREG(EXIT),FMASK_TEST);
+       gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FMASK_TEST);
+       gen_dop_word(DOP_OR,true,DREG(FLAGS),DREG(EXIT)); //flags are marked for save
+       gen_releasereg(DREG(EXIT));
+       gen_releasereg(DREG(FLAGS));
+}
+
+static void dyn_savestate(DynState * state) {
+       for (Bitu i=0;i<G_MAX;i++) {
+               state->regs[i].flags=DynRegs[i].flags;
+               state->regs[i].genreg=DynRegs[i].genreg;
+       }
+}
+
+static void dyn_loadstate(DynState * state) {
+       for (Bitu i=0;i<G_MAX;i++) {
+               gen_setupreg(&DynRegs[i],&state->regs[i]);
+       }
+}
+
+static void dyn_synchstate(DynState * state) {
+       for (Bitu i=0;i<G_MAX;i++) {
+               gen_synchreg(&DynRegs[i],&state->regs[i]);
+       }
+}
+
+static void dyn_saveregister(DynReg * src_reg, DynReg * dst_reg) {
+       dst_reg->flags=src_reg->flags;
+       dst_reg->genreg=src_reg->genreg;
+}
+
+static void dyn_restoreregister(DynReg * src_reg, DynReg * dst_reg) {
+       dst_reg->flags=src_reg->flags;
+       dst_reg->genreg=src_reg->genreg;
+       dst_reg->genreg->dynreg=dst_reg;        // necessary when register has been released
+}
+
+#include "core_dyn_x86/decoder.h"
+
+#if defined (_MSC_VER)
+#define DH_FPU_SAVE_REINIT                             \
+{                                                                              \
+       __asm {                                                         \
+       __asm   fnsave  dyn_dh_fpu.state[0]     \
+       }                                                                       \
+       dyn_dh_fpu.state_used=false;            \
+       dyn_dh_fpu.state[0]|=0x3f;                      \
+}
+#else
+#define DH_FPU_SAVE_REINIT                             \
+{                                                                              \
+       __asm__ volatile (                                      \
+               "fnsave         %0                      \n"             \
+               :       "=m" (dyn_dh_fpu.state[0])      \
+               :                                                               \
+               :       "memory"                                        \
+       );                                                                      \
+       dyn_dh_fpu.state_used=false;            \
+       dyn_dh_fpu.state[0]|=0x3f;                      \
+}
+#endif
+
+
+Bits CPU_Core_Dyn_X86_Run(void) {
+       /* Determine the linear address of CS:EIP */
+restart_core:
+       PhysPt ip_point=SegPhys(cs)+reg_eip;
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+               if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
+#endif
+#endif
+       CodePageHandler * chandler=0;
+       if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) {
+               CPU_Exception(cpu.exception.which,cpu.exception.error);
+               goto restart_core;
+       }
+       if (!chandler) {
+               if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
+               return CPU_Core_Normal_Run();
+       }
+       /* Find correct Dynamic Block to run */
+       CacheBlock * block=chandler->FindCacheBlock(ip_point&4095);
+       if (!block) {
+               if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) {
+                       block=CreateCacheBlock(chandler,ip_point,32);
+               } else {
+                       Bitu old_cycles=CPU_Cycles;
+                       CPU_Cycles=1;
+                       Bits nc_retcode=CPU_Core_Normal_Run();
+                       if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
+                       if (!nc_retcode) {
+                               CPU_Cycles=old_cycles-1;
+                               goto restart_core;
+                       }
+                       CPU_CycleLeft+=old_cycles;
+                       return nc_retcode; 
+               }
+       }
+run_block:
+       cache.block.running=0;
+       BlockReturn ret=gen_runcode(block->cache.start);
+       switch (ret) {
+       case BR_Iret:
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+               if (DEBUG_HeavyIsBreakpoint()) {
+                       if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
+                       return debugCallback;
+               }
+#endif
+#endif
+               if (!GETFLAG(TF)) {
+                       if (GETFLAG(IF) && PIC_IRQCheck) {
+                               if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
+                               return CBRET_NONE;
+                       }
+                       goto restart_core;
+               }
+               cpudecoder=CPU_Core_Dyn_X86_Trap_Run;
+               if (!dyn_dh_fpu.state_used) return CBRET_NONE;
+               DH_FPU_SAVE_REINIT
+               return CBRET_NONE;
+       case BR_Normal:
+               /* Maybe check if we staying in the same page? */
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+               if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
+#endif
+#endif
+               goto restart_core;
+       case BR_Cycles:
+#if C_DEBUG
+#if C_HEAVY_DEBUG                      
+               if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
+#endif
+#endif
+               if (!dyn_dh_fpu.state_used) return CBRET_NONE;
+               DH_FPU_SAVE_REINIT
+               return CBRET_NONE;
+       case BR_CallBack:
+               if (!dyn_dh_fpu.state_used) return core_dyn.callback;
+               DH_FPU_SAVE_REINIT
+               return core_dyn.callback;
+       case BR_SMCBlock:
+//             LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip);
+               cpu.exception.which=0;
+               // fallthrough, let the normal core handle the block-modifying instruction
+       case BR_Opcode:
+               CPU_CycleLeft+=CPU_Cycles;
+               CPU_Cycles=1;
+               if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
+               return CPU_Core_Normal_Run();
+#if (C_DEBUG)
+       case BR_OpcodeFull:
+               CPU_CycleLeft+=CPU_Cycles;
+               CPU_Cycles=1;
+               if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
+               return CPU_Core_Full_Run();
+#endif
+       case BR_Link1:
+       case BR_Link2:
+               {
+                       Bitu temp_ip=SegPhys(cs)+reg_eip;
+                       CodePageHandler * temp_handler=(CodePageHandler *)get_tlb_readhandler(temp_ip);
+                       if (temp_handler->flags & PFLAG_HASCODE) {
+                               block=temp_handler->FindCacheBlock(temp_ip & 4095);
+                               if (!block) goto restart_core;
+                               cache.block.running->LinkTo(ret==BR_Link2,block);
+                               goto run_block;
+                       }
+               }
+               goto restart_core;
+       }
+       if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
+       return CBRET_NONE;
+}
+
+Bits CPU_Core_Dyn_X86_Trap_Run(void) {
+       Bits oldCycles = CPU_Cycles;
+       CPU_Cycles = 1;
+       cpu.trap_skip = false;
+
+       Bits ret=CPU_Core_Normal_Run();
+       if (!cpu.trap_skip) CPU_HW_Interrupt(1);
+       CPU_Cycles = oldCycles-1;
+       cpudecoder = &CPU_Core_Dyn_X86_Run;
+
+       return ret;
+}
+
+void CPU_Core_Dyn_X86_Init(void) {
+       Bits i;
+       /* Setup the global registers and their flags */
+       for (i=0;i<G_MAX;i++) DynRegs[i].genreg=0;
+       DynRegs[G_EAX].data=&reg_eax;
+       DynRegs[G_EAX].flags=DYNFLG_HAS8|DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_ECX].data=&reg_ecx;
+       DynRegs[G_ECX].flags=DYNFLG_HAS8|DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_EDX].data=&reg_edx;
+       DynRegs[G_EDX].flags=DYNFLG_HAS8|DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_EBX].data=&reg_ebx;
+       DynRegs[G_EBX].flags=DYNFLG_HAS8|DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+
+       DynRegs[G_EBP].data=&reg_ebp;
+       DynRegs[G_EBP].flags=DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_ESP].data=&reg_esp;
+       DynRegs[G_ESP].flags=DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_EDI].data=&reg_edi;
+       DynRegs[G_EDI].flags=DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_ESI].data=&reg_esi;
+       DynRegs[G_ESI].flags=DYNFLG_HAS16|DYNFLG_LOAD|DYNFLG_SAVE;
+
+       DynRegs[G_ES].data=&Segs.phys[es];
+       DynRegs[G_ES].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_CS].data=&Segs.phys[cs];
+       DynRegs[G_CS].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_SS].data=&Segs.phys[ss];
+       DynRegs[G_SS].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_DS].data=&Segs.phys[ds];
+       DynRegs[G_DS].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_FS].data=&Segs.phys[fs];
+       DynRegs[G_FS].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_GS].data=&Segs.phys[gs];
+       DynRegs[G_GS].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+
+       DynRegs[G_FLAGS].data=&reg_flags;
+       DynRegs[G_FLAGS].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+
+       DynRegs[G_NEWESP].data=&extra_regs.newesp;
+       DynRegs[G_NEWESP].flags=0;
+
+       DynRegs[G_EIP].data=&reg_eip;
+       DynRegs[G_EIP].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+
+       DynRegs[G_EA].data=&extra_regs.ea;
+       DynRegs[G_EA].flags=0;
+       DynRegs[G_STACK].data=&extra_regs.stack;
+       DynRegs[G_STACK].flags=0;
+       DynRegs[G_CYCLES].data=&CPU_Cycles;
+       DynRegs[G_CYCLES].flags=DYNFLG_LOAD|DYNFLG_SAVE;
+       DynRegs[G_TMPB].data=&extra_regs.tmpb;
+       DynRegs[G_TMPB].flags=DYNFLG_HAS8|DYNFLG_HAS16;
+       DynRegs[G_TMPW].data=&extra_regs.tmpd;
+       DynRegs[G_TMPW].flags=DYNFLG_HAS16;
+       DynRegs[G_SHIFT].data=&extra_regs.shift;
+       DynRegs[G_SHIFT].flags=DYNFLG_HAS8|DYNFLG_HAS16;
+       DynRegs[G_EXIT].data=0;
+       DynRegs[G_EXIT].flags=DYNFLG_HAS16;
+       /* Init the generator */
+       gen_init();
+
+       /* Init the fpu state */
+       dyn_dh_fpu.dh_fpu_enabled=true;
+       dyn_dh_fpu.state_used=false;
+       dyn_dh_fpu.cw=0x37f;
+#if defined (_MSC_VER)
+       __asm {
+       __asm   finit
+       __asm   fsave   dyn_dh_fpu.state[0]
+       __asm   fstcw   dyn_dh_fpu.host_cw
+       }
+#else
+       __asm__ volatile (
+               "finit                                  \n"
+               "fsave          %0                      \n"
+               "fstcw          %1                      \n"
+               :       "=m" (dyn_dh_fpu.state[0]), "=m" (dyn_dh_fpu.host_cw)
+               :
+               :       "memory"
+       );
+#endif
+
+       return;
+}
+
+void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache) {
+       /* Initialize code cache and dynamic blocks */
+       cache_init(enable_cache);
+}
+
+void CPU_Core_Dyn_X86_Cache_Close(void) {
+       cache_close();
+}
+
+void CPU_Core_Dyn_X86_Cache_Reset(void) {
+       cache_reset();
+}
+
+void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu) {
+       dyn_dh_fpu.dh_fpu_enabled=dh_fpu;
+}
+
+Bit32u fpu_state[32];
+
+void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
+       if (dyn_dh_fpu.dh_fpu_enabled) {
+               if (dyn_dh_fpu.state_used!=0) {
+#if defined (_MSC_VER)
+                       __asm {
+                       __asm   fsave   fpu_state[0]
+                       __asm   finit
+                       }
+#else
+                       __asm__ volatile (
+                               "fsave          %0                      \n"
+                               "finit                                  \n"
+                               :       "=m" (fpu_state[0])
+                               :
+                               :       "memory"
+                       );
+#endif
+               }
+       }
+}
+
+void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
+       if (dyn_dh_fpu.dh_fpu_enabled) {
+               if (dyn_dh_fpu.state_used!=0) {
+#if defined (_MSC_VER)
+                       __asm {
+                       __asm   frstor  fpu_state[0]
+                       }
+#else
+                       __asm__ volatile (
+                               "frstor         %0                      \n"
+                               :
+                               :       "m" (fpu_state[0])
+                               :
+                       );
+#endif
+               }
+       }
+}
+
+#else
+
+void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
+}
+
+void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile
new file mode 100644 (file)
index 0000000..1a46e4c
--- /dev/null
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# src/cpu/core_dyn_x86/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/dosbox
+pkgincludedir = $(includedir)/dosbox
+pkglibdir = $(libdir)/dosbox
+pkglibexecdir = $(libexecdir)/dosbox
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-pc-linux-gnu
+host_triplet = x86_64-pc-linux-gnu
+subdir = src/cpu/core_dyn_x86
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = aclocal-1.16
+ALSA_CFLAGS = 
+ALSA_LIBS =  -lasound -lm -ldl -lpthread
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AUTOCONF = autoconf
+AUTOHEADER = autoheader
+AUTOMAKE = automake-1.16
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =  -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = 
+LIBOBJS = 
+LIBS = -lasound -lm -ldl -lpthread -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpng -lz -lX11 -lGL
+LTLIBOBJS = 
+MAKEINFO = makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = dosbox
+PACKAGE_BUGREPORT = 
+PACKAGE_NAME = dosbox
+PACKAGE_STRING = dosbox 0.74
+PACKAGE_TARNAME = dosbox
+PACKAGE_URL = 
+PACKAGE_VERSION = 0.74
+PATH_SEPARATOR = :
+RANLIB = ranlib
+SDL_CFLAGS = -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+SDL_CONFIG = /usr/local/bin/sdl-config
+SDL_LIBS = -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpthread
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = 
+VERSION = 0.74
+WINDRES = :
+abs_builddir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_dyn_x86
+abs_srcdir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_dyn_x86
+abs_top_builddir = /home/whatisthis/src/DOSVAXJ3
+abs_top_srcdir = /home/whatisthis/src/DOSVAXJ3
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-pc-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-pc-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/whatisthis/src/DOSVAXJ3/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+runstatedir = ${localstatedir}/run
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias = 
+top_build_prefix = ../../../
+top_builddir = ../../..
+top_srcdir = ../../..
+noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h string.h \
+                 dyn_fpu.h dyn_fpu_dh.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_dyn_x86/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_dyn_x86/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile.am b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile.am
new file mode 100644 (file)
index 0000000..3d9be09
--- /dev/null
@@ -0,0 +1,2 @@
+noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h string.h \
+                 dyn_fpu.h dyn_fpu_dh.h
\ No newline at end of file
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile.in b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/Makefile.in
new file mode 100644 (file)
index 0000000..a838bb7
--- /dev/null
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/cpu/core_dyn_x86
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h string.h \
+                 dyn_fpu.h dyn_fpu_dh.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_dyn_x86/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_dyn_x86/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/cache.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/cache.h
new file mode 100644 (file)
index 0000000..23b6a53
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+class CacheBlock {
+public:
+       void Clear(void);
+       void LinkTo(Bitu index,CacheBlock * toblock) {
+               assert(toblock);
+               link[index].to=toblock;
+               link[index].next=toblock->link[index].from;
+               toblock->link[index].from=this;
+       }
+       struct {
+               Bit16u start,end;                               //Where the page is the original code
+               CodePageHandler * handler;              //Page containing this code
+       } page;
+       struct {
+               Bit8u * start;                                  //Where in the cache are we
+               Bitu size;
+               CacheBlock * next;
+               Bit8u * wmapmask;
+               Bit16u maskstart;
+               Bit16u masklen;
+       } cache;
+       struct {
+               Bitu index;
+               CacheBlock * next;
+       } hash;
+       struct {
+               CacheBlock * to;
+               CacheBlock * next;
+               CacheBlock * from;
+       } link[2];
+       CacheBlock * crossblock;
+};
+
+static struct {
+       struct {
+               CacheBlock * first;
+               CacheBlock * active;
+               CacheBlock * free;
+               CacheBlock * running;
+       } block;
+       Bit8u * pos;
+       CodePageHandler * free_pages;
+       CodePageHandler * used_pages;
+       CodePageHandler * last_page;
+} cache;
+
+static CacheBlock link_blocks[2];
+
+class CodePageHandler : public PageHandler {
+public:
+       CodePageHandler() {
+               invalidation_map=NULL;
+       }
+       void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
+               phys_page=_phys_page;
+               old_pagehandler=_old_pagehandler;
+               flags=old_pagehandler->flags|PFLAG_HASCODE;
+               flags&=~PFLAG_WRITEABLE;
+               active_blocks=0;
+               active_count=16;
+               memset(&hash_map,0,sizeof(hash_map));
+               memset(&write_map,0,sizeof(write_map));
+               if (invalidation_map!=NULL) {
+                       free(invalidation_map);
+                       invalidation_map=NULL;
+               }
+       }
+       bool InvalidateRange(Bitu start,Bitu end) {
+               Bits index=1+(end>>DYN_HASH_SHIFT);
+               bool is_current_block=false;
+               Bit32u ip_point=SegPhys(cs)+reg_eip;
+               ip_point=(PAGING_GetPhysicalPage(ip_point)-(phys_page<<12))+(ip_point&0xfff);
+               while (index>=0) {
+                       Bitu map=0;
+                       for (Bitu count=start;count<=end;count++) map+=write_map[count];
+                       if (!map) return is_current_block;
+                       CacheBlock * block=hash_map[index];
+                       while (block) {
+                               CacheBlock * nextblock=block->hash.next;
+                               if (start<=block->page.end && end>=block->page.start) {
+                                       if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true;
+                                       block->Clear();
+                               }
+                               block=nextblock;
+                       }
+                       index--;
+               }
+               return is_current_block;
+       }
+       void writeb(PhysPt addr,Bitu val){
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("wb:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readb(hostmem+addr)==(Bit8u)val) return;
+               host_writeb(hostmem+addr,val);
+               if (!*(Bit8u*)&write_map[addr]) {
+                       if (active_blocks) return;
+                       active_count--;
+                       if (!active_count) Release();
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+               invalidation_map[addr]++;
+               InvalidateRange(addr,addr);
+       }
+       void writew(PhysPt addr,Bitu val){
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("ww:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readw(hostmem+addr)==(Bit16u)val) return;
+               host_writew(hostmem+addr,val);
+               if (!*(Bit16u*)&write_map[addr]) {
+                       if (active_blocks) return;
+                       active_count--;
+                       if (!active_count) Release();
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+               (*(Bit16u*)&invalidation_map[addr])+=0x101;
+               InvalidateRange(addr,addr+1);
+       }
+       void writed(PhysPt addr,Bitu val){
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("wd:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readd(hostmem+addr)==(Bit32u)val) return;
+               host_writed(hostmem+addr,val);
+               if (!*(Bit32u*)&write_map[addr]) {
+                       if (active_blocks) return;
+                       active_count--;
+                       if (!active_count) Release();
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+               (*(Bit32u*)&invalidation_map[addr])+=0x1010101;
+               InvalidateRange(addr,addr+3);
+       }
+       bool writeb_checked(PhysPt addr,Bitu val) {
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("cb:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readb(hostmem+addr)==(Bit8u)val) return false;
+               if (!*(Bit8u*)&write_map[addr]) {
+                       if (!active_blocks) {
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+                       invalidation_map[addr]++;
+                       if (InvalidateRange(addr,addr)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writeb(hostmem+addr,val);
+               return false;
+       }
+       bool writew_checked(PhysPt addr,Bitu val) {
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("cw:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readw(hostmem+addr)==(Bit16u)val) return false;
+               if (!*(Bit16u*)&write_map[addr]) {
+                       if (!active_blocks) {
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+                       (*(Bit16u*)&invalidation_map[addr])+=0x101;
+                       if (InvalidateRange(addr,addr+1)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writew(hostmem+addr,val);
+               return false;
+       }
+       bool writed_checked(PhysPt addr,Bitu val) {
+               if (GCC_UNLIKELY(old_pagehandler->flags&PFLAG_HASROM)) return false;
+               if (GCC_UNLIKELY((old_pagehandler->flags&PFLAG_READABLE)!=PFLAG_READABLE)) {
+                       E_Exit("cd:non-readable code page found that is no ROM page");
+               }
+               addr&=4095;
+               if (host_readd(hostmem+addr)==(Bit32u)val) return false;
+               if (!*(Bit32u*)&write_map[addr]) {
+                       if (!active_blocks) {
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+                       (*(Bit32u*)&invalidation_map[addr])+=0x1010101;
+                       if (InvalidateRange(addr,addr+3)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writed(hostmem+addr,val);
+               return false;
+       }
+    void AddCacheBlock(CacheBlock * block) {
+               Bitu index=1+(block->page.start>>DYN_HASH_SHIFT);
+               block->hash.next=hash_map[index];
+               block->hash.index=index;
+               hash_map[index]=block;
+               block->page.handler=this;
+               active_blocks++;
+       }
+    void AddCrossBlock(CacheBlock * block) {
+               block->hash.next=hash_map[0];
+               block->hash.index=0;
+               hash_map[0]=block;
+               block->page.handler=this;
+               active_blocks++;
+       }
+       void DelCacheBlock(CacheBlock * block) {
+               active_blocks--;
+               active_count=16;
+               CacheBlock * * where=&hash_map[block->hash.index];
+               while (*where!=block) {
+                       where=&((*where)->hash.next);
+                       //Will crash if a block isn't found, which should never happen.
+               }
+               *where=block->hash.next;
+               if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) {
+                       for (Bitu i=block->page.start;i<block->cache.maskstart;i++) {
+                               if (write_map[i]) write_map[i]--;
+                       }
+                       Bitu maskct=0;
+                       for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) {
+                               if (write_map[i]) {
+                                       if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--;
+                               }
+                       }
+                       free(block->cache.wmapmask);
+                       block->cache.wmapmask=NULL;
+               } else {
+                       for (Bitu i=block->page.start;i<=block->page.end;i++) {
+                               if (write_map[i]) write_map[i]--;
+                       }
+               }
+       }
+       void Release(void) {
+               MEM_SetPageHandler(phys_page,1,old_pagehandler);
+               PAGING_ClearTLB();
+               if (prev) prev->next=next;
+               else cache.used_pages=next;
+               if (next) next->prev=prev;
+               else cache.last_page=prev;
+               next=cache.free_pages;
+               cache.free_pages=this;
+               prev=0;
+       }
+       void ClearRelease(void) {
+               for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) {
+                       CacheBlock * block=hash_map[index];
+                       while (block) {
+                               CacheBlock * nextblock=block->hash.next;
+                               block->page.handler=0;                  //No need, full clear
+                               block->Clear();
+                               block=nextblock;
+                       }
+               }
+               Release();
+       }
+       CacheBlock * FindCacheBlock(Bitu start) {
+               CacheBlock * block=hash_map[1+(start>>DYN_HASH_SHIFT)];
+               while (block) {
+                       if (block->page.start==start) return block;
+                       block=block->hash.next;
+               }
+               return 0;
+       }
+       HostPt GetHostReadPt(Bitu phys_page) { 
+               hostmem=old_pagehandler->GetHostReadPt(phys_page);
+               return hostmem;
+       }
+       HostPt GetHostWritePt(Bitu phys_page) { 
+               return GetHostReadPt( phys_page );
+       }
+public:
+       Bit8u write_map[4096];
+       Bit8u * invalidation_map;
+       CodePageHandler * next, * prev;
+private:
+       PageHandler * old_pagehandler;
+       CacheBlock * hash_map[1+DYN_PAGE_HASH];
+       Bitu active_blocks;
+       Bitu active_count;
+       HostPt hostmem; 
+       Bitu phys_page;
+};
+
+
+static INLINE void cache_addunsedblock(CacheBlock * block) {
+       block->cache.next=cache.block.free;
+       cache.block.free=block;
+}
+
+static CacheBlock * cache_getblock(void) {
+       CacheBlock * ret=cache.block.free;
+       if (!ret) E_Exit("Ran out of CacheBlocks" );
+       cache.block.free=ret->cache.next;
+       ret->cache.next=0;
+       return ret;
+}
+
+void CacheBlock::Clear(void) {
+       Bitu ind;
+       /* Check if this is not a cross page block */
+       if (hash.index) for (ind=0;ind<2;ind++) {
+               CacheBlock * fromlink=link[ind].from;
+               link[ind].from=0;
+               while (fromlink) {
+                       CacheBlock * nextlink=fromlink->link[ind].next;
+                       fromlink->link[ind].next=0;
+                       fromlink->link[ind].to=&link_blocks[ind];
+                       fromlink=nextlink;
+               }
+               if (link[ind].to!=&link_blocks[ind]) {
+                       CacheBlock * * wherelink=&link[ind].to->link[ind].from;
+                       while (*wherelink != this && *wherelink) {
+                               wherelink = &(*wherelink)->link[ind].next;
+                       }
+                       if(*wherelink) 
+                               *wherelink = (*wherelink)->link[ind].next;
+                       else
+                               LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate");
+               }
+       } else 
+               cache_addunsedblock(this);
+       if (crossblock) {
+               crossblock->crossblock=0;
+               crossblock->Clear();
+               crossblock=0;
+       }
+       if (page.handler) {
+               page.handler->DelCacheBlock(this);
+               page.handler=0;
+       }
+       if (cache.wmapmask){
+               free(cache.wmapmask);
+               cache.wmapmask=NULL;
+       }
+}
+
+
+static CacheBlock * cache_openblock(void) {
+       CacheBlock * block=cache.block.active;
+       /* check for enough space in this block */
+       Bitu size=block->cache.size;
+       CacheBlock * nextblock=block->cache.next;
+       if (block->page.handler) 
+               block->Clear();
+       while (size<CACHE_MAXSIZE) {
+               if (!nextblock) 
+                       goto skipresize;
+               size+=nextblock->cache.size;
+               CacheBlock * tempblock=nextblock->cache.next;
+               if (nextblock->page.handler) 
+                       nextblock->Clear();
+               cache_addunsedblock(nextblock);
+               nextblock=tempblock;
+       }
+skipresize:
+       block->cache.size=size;
+       block->cache.next=nextblock;
+       cache.pos=block->cache.start;
+       return block;
+}
+
+static void cache_closeblock(void) {
+       CacheBlock * block=cache.block.active;
+       block->link[0].to=&link_blocks[0];
+       block->link[1].to=&link_blocks[1];
+       block->link[0].from=0;
+       block->link[1].from=0;
+       block->link[0].next=0;
+       block->link[1].next=0;
+       /* Close the block with correct alignments */
+       Bitu written=cache.pos-block->cache.start;
+       if (written>block->cache.size) {
+               if (!block->cache.next) {
+                       if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size);       
+               } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size);     
+       } else {
+               Bitu new_size;
+               Bitu left=block->cache.size-written;
+               /* Smaller than cache align then don't bother to resize */
+               if (left>CACHE_ALIGN) {
+                       new_size=((written-1)|(CACHE_ALIGN-1))+1;
+                       CacheBlock * newblock=cache_getblock();
+                       newblock->cache.start=block->cache.start+new_size;
+                       newblock->cache.size=block->cache.size-new_size;
+                       newblock->cache.next=block->cache.next;
+                       block->cache.next=newblock;
+                       block->cache.size=new_size;
+               }
+       }
+       /* Advance the active block pointer */
+       if (!block->cache.next) {
+//             LOG_MSG("Cache full restarting");
+               cache.block.active=cache.block.first;
+       } else {
+               cache.block.active=block->cache.next;
+       }
+}
+
+static INLINE void cache_addb(Bit8u val) {
+       *cache.pos++=val;
+}
+
+static INLINE void cache_addw(Bit16u val) {
+       *(Bit16u*)cache.pos=val;
+       cache.pos+=2;
+}
+
+static INLINE void cache_addd(Bit32u val) {
+       *(Bit32u*)cache.pos=val;
+       cache.pos+=4;
+}
+
+
+static void gen_return(BlockReturn retcode);
+
+static Bit8u * cache_code_start_ptr=NULL;
+static Bit8u * cache_code=NULL;
+static Bit8u * cache_code_link_blocks=NULL;
+static CacheBlock * cache_blocks=NULL;
+
+/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */
+#if (C_HAVE_MPROTECT)
+#define PAGESIZE_TEMP PAGESIZE
+#else 
+#define PAGESIZE_TEMP 4096
+#endif
+
+static bool cache_initialized = false;
+
+static void cache_init(bool enable) {
+       Bits i;
+       if (enable) {
+               if (cache_initialized) return;
+               cache_initialized = true;
+               if (cache_blocks == NULL) {
+                       cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock));
+                       if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
+                       memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS);
+                       cache.block.free=&cache_blocks[0];
+                       for (i=0;i<CACHE_BLOCKS-1;i++) {
+                               cache_blocks[i].link[0].to=(CacheBlock *)1;
+                               cache_blocks[i].link[1].to=(CacheBlock *)1;
+                               cache_blocks[i].cache.next=&cache_blocks[i+1];
+                       }
+               }
+               if (cache_code_start_ptr==NULL) {
+#if defined (WIN32)
+                       cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
+                               MEM_COMMIT,PAGE_EXECUTE_READWRITE);
+                       if (!cache_code_start_ptr)
+                               cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#else
+                       cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#endif
+                       if(!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
+
+                       cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //Bitu is same size as a pointer.
+
+                       cache_code_link_blocks=cache_code;
+                       cache_code+=PAGESIZE_TEMP;
+
+#if (C_HAVE_MPROTECT)
+                       if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
+                               LOG_MSG("Setting excute permission on the code cache has failed!");
+#endif
+                       CacheBlock * block=cache_getblock();
+                       cache.block.first=block;
+                       cache.block.active=block;
+                       block->cache.start=&cache_code[0];
+                       block->cache.size=CACHE_TOTAL;
+                       block->cache.next=0;                                                            //Last block in the list
+               }
+               /* Setup the default blocks for block linkage returns */
+               cache.pos=&cache_code_link_blocks[0];
+               link_blocks[0].cache.start=cache.pos;
+               gen_return(BR_Link1);
+               cache.pos=&cache_code_link_blocks[32];
+               link_blocks[1].cache.start=cache.pos;
+               gen_return(BR_Link2);
+               cache.free_pages=0;
+               cache.last_page=0;
+               cache.used_pages=0;
+               /* Setup the code pages */
+               for (i=0;i<CACHE_PAGES;i++) {
+                       CodePageHandler * newpage=new CodePageHandler();
+                       newpage->next=cache.free_pages;
+                       cache.free_pages=newpage;
+               }
+       }
+}
+
+static void cache_close(void) {
+/*     for (;;) {
+               if (cache.used_pages) {
+                       CodePageHandler * cpage=cache.used_pages;
+                       CodePageHandler * npage=cache.used_pages->next;
+                       cpage->ClearRelease();
+                       delete cpage;
+                       cache.used_pages=npage;
+               } else break;
+       }
+       if (cache_blocks != NULL) {
+               free(cache_blocks);
+               cache_blocks = NULL;
+       }
+       if (cache_code_start_ptr != NULL) {
+               ### care: under windows VirtualFree() has to be used if
+               ###       VirtualAlloc was used for memory allocation
+               free(cache_code_start_ptr);
+               cache_code_start_ptr = NULL;
+       }
+       cache_code = NULL;
+       cache_code_link_blocks = NULL;
+       cache_initialized = false; */
+}
+
+static void cache_reset(void) {
+       if (cache_initialized) {
+               for (;;) {
+                       if (cache.used_pages) {
+                               CodePageHandler * cpage=cache.used_pages;
+                               CodePageHandler * npage=cache.used_pages->next;
+                               cpage->ClearRelease();
+                               delete cpage;
+                               cache.used_pages=npage;
+                       } else break;
+               }
+
+               if (cache_blocks == NULL) {
+                       cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock));
+                       if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
+               }
+               memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS);
+               cache.block.free=&cache_blocks[0];
+               for (Bits i=0;i<CACHE_BLOCKS-1;i++) {
+                       cache_blocks[i].link[0].to=(CacheBlock *)1;
+                       cache_blocks[i].link[1].to=(CacheBlock *)1;
+                       cache_blocks[i].cache.next=&cache_blocks[i+1];
+               }
+
+               if (cache_code_start_ptr==NULL) {
+#if defined (WIN32)
+                       cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
+                               MEM_COMMIT,PAGE_EXECUTE_READWRITE);
+                       if (!cache_code_start_ptr)
+                               cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#else
+                       cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#endif
+                       if (!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
+
+                       cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //Bitu is same size as a pointer.
+
+                       cache_code_link_blocks=cache_code;
+                       cache_code+=PAGESIZE_TEMP;
+
+#if (C_HAVE_MPROTECT)
+                       if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
+                               LOG_MSG("Setting excute permission on the code cache has failed!");
+#endif
+               }
+
+               CacheBlock * block=cache_getblock();
+               cache.block.first=block;
+               cache.block.active=block;
+               block->cache.start=&cache_code[0];
+               block->cache.size=CACHE_TOTAL;
+               block->cache.next=0;                                                            //Last block in the list
+
+               /* Setup the default blocks for block linkage returns */
+               cache.pos=&cache_code_link_blocks[0];
+               link_blocks[0].cache.start=cache.pos;
+               gen_return(BR_Link1);
+               cache.pos=&cache_code_link_blocks[32];
+               link_blocks[1].cache.start=cache.pos;
+               gen_return(BR_Link2);
+               cache.free_pages=0;
+               cache.last_page=0;
+               cache.used_pages=0;
+               /* Setup the code pages */
+               for (Bitu i=0;i<CACHE_PAGES;i++) {
+                       CodePageHandler * newpage=new CodePageHandler();
+                       newpage->next=cache.free_pages;
+                       cache.free_pages=newpage;
+               }
+       }
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/decoder.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/decoder.h
new file mode 100644 (file)
index 0000000..18bf1e1
--- /dev/null
@@ -0,0 +1,2713 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#define X86_DYNFPU_DH_ENABLED
+#define X86_INLINED_MEMACCESS
+
+
+enum REP_Type {
+       REP_NONE=0,REP_NZ,REP_Z
+};
+
+static struct DynDecode {
+       PhysPt code;
+       PhysPt code_start;
+       PhysPt op_start;
+       bool big_op;
+       bool big_addr;
+       REP_Type rep;
+       Bitu cycles;
+       CacheBlock * block;
+       CacheBlock * active_block;
+       struct {
+               CodePageHandler * code; 
+               Bitu index;
+               Bit8u * wmap;
+               Bit8u * invmap;
+               Bitu first;
+       } page;
+       struct {
+               Bitu val;
+               Bitu mod;
+               Bitu rm;
+               Bitu reg;
+       } modrm;
+       DynReg * segprefix;
+} decode;
+
+static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) {
+       Bit8u rdval;
+       //Ensure page contains memory:
+       if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true;
+       PageHandler * handler=get_tlb_readhandler(lin_addr);
+       if (handler->flags & PFLAG_HASCODE) {
+               cph=( CodePageHandler *)handler;
+               return false;
+       }
+       if (handler->flags & PFLAG_NOCODE) {
+               if (PAGING_ForcePageInit(lin_addr)) {
+                       handler=get_tlb_readhandler(lin_addr);
+                       if (handler->flags & PFLAG_HASCODE) {
+                               cph=( CodePageHandler *)handler;
+                               return false;
+                       }
+               }
+               if (handler->flags & PFLAG_NOCODE) {
+                       LOG_MSG("DYNX86:Can't run code in this page!");
+                       cph=0;          return false;
+               }
+       } 
+       Bitu lin_page=lin_addr >> 12;
+       Bitu phys_page=lin_page;
+       if (!PAGING_MakePhysPage(phys_page)) {
+               LOG_MSG("DYNX86:Can't find physpage");
+               cph=0;          return false;
+       }
+       /* Find a free CodePage */
+       if (!cache.free_pages) {
+               if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease();
+               else {
+                       if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code))
+                               cache.used_pages->next->ClearRelease();
+                       else {
+                               LOG_MSG("DYNX86:Invalid cache links");
+                               cache.used_pages->ClearRelease();
+                       }
+               }
+       }
+       CodePageHandler * cpagehandler=cache.free_pages;
+       cache.free_pages=cache.free_pages->next;
+       cpagehandler->prev=cache.last_page;
+       cpagehandler->next=0;
+       if (cache.last_page) cache.last_page->next=cpagehandler;
+       cache.last_page=cpagehandler;
+       if (!cache.used_pages) cache.used_pages=cpagehandler;
+       cpagehandler->SetupAt(phys_page,handler);
+       MEM_SetPageHandler(phys_page,1,cpagehandler);
+       PAGING_UnlinkPages(lin_page,1);
+       cph=cpagehandler;
+       return false;
+}
+
+static Bit8u decode_fetchb(void) {
+       if (GCC_UNLIKELY(decode.page.index>=4096)) {
+        /* Advance to the next page */
+               decode.active_block->page.end=4095;
+               /* trigger possible page fault here */
+               decode.page.first++;
+               Bitu fetchaddr=decode.page.first << 12;
+               mem_readb(fetchaddr);
+               MakeCodePage(fetchaddr,decode.page.code);
+               CacheBlock * newblock=cache_getblock();
+               decode.active_block->crossblock=newblock;
+               newblock->crossblock=decode.active_block;
+               decode.active_block=newblock;
+               decode.active_block->page.start=0;
+               decode.page.code->AddCrossBlock(decode.active_block);
+               decode.page.wmap=decode.page.code->write_map;
+               decode.page.invmap=decode.page.code->invalidation_map;
+               decode.page.index=0;
+       }
+       decode.page.wmap[decode.page.index]+=0x01;
+       decode.page.index++;
+       decode.code+=1;
+       return mem_readb(decode.code-1);
+}
+static Bit16u decode_fetchw(void) {
+       if (GCC_UNLIKELY(decode.page.index>=4095)) {
+               Bit16u val=decode_fetchb();
+               val|=decode_fetchb() << 8;
+               return val;
+       }
+       *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101;
+       decode.code+=2;decode.page.index+=2;
+       return mem_readw(decode.code-2);
+}
+static Bit32u decode_fetchd(void) {
+       if (GCC_UNLIKELY(decode.page.index>=4093)) {
+               Bit32u val=decode_fetchb();
+               val|=decode_fetchb() << 8;
+               val|=decode_fetchb() << 16;
+               val|=decode_fetchb() << 24;
+               return val;
+        /* Advance to the next page */
+       }
+       *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101;
+       decode.code+=4;decode.page.index+=4;
+       return mem_readd(decode.code-4);
+}
+
+#define START_WMMEM 64
+
+static INLINE void decode_increase_wmapmask(Bitu size) {
+       Bitu mapidx;
+       CacheBlock* activecb=decode.active_block; 
+       if (GCC_UNLIKELY(!activecb->cache.wmapmask)) {
+               activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM);
+               memset(activecb->cache.wmapmask,0,START_WMMEM);
+               activecb->cache.maskstart=decode.page.index;
+               activecb->cache.masklen=START_WMMEM;
+               mapidx=0;
+       } else {
+               mapidx=decode.page.index-activecb->cache.maskstart;
+               if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) {
+                       Bitu newmasklen=activecb->cache.masklen*4;
+                       if (newmasklen<mapidx+size) newmasklen=((mapidx+size)&~3)*2;
+                       Bit8u* tempmem=(Bit8u*)malloc(newmasklen);
+                       memset(tempmem,0,newmasklen);
+                       memcpy(tempmem,activecb->cache.wmapmask,activecb->cache.masklen);
+                       free(activecb->cache.wmapmask);
+                       activecb->cache.wmapmask=tempmem;
+                       activecb->cache.masklen=newmasklen;
+               }
+       }
+       switch (size) {
+               case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break;
+               case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break;
+               case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break;
+       }
+}
+
+static bool decode_fetchb_imm(Bitu & val) {
+       if (decode.page.index<4096) {
+               if (decode.page.invmap != NULL) {
+                       if (decode.page.invmap[decode.page.index] == 0) {
+                               val=(Bit32u)decode_fetchb();
+                               return false;
+                       }
+                       HostPt tlb_addr=get_tlb_read(decode.code);
+                       if (tlb_addr) {
+                               val=(Bitu)(tlb_addr+decode.code);
+                               decode_increase_wmapmask(1);
+                               decode.code++;
+                               decode.page.index++;
+                               return true;
+                       }
+               }
+       }
+       val=(Bit32u)decode_fetchb();
+       return false;
+}
+static bool decode_fetchw_imm(Bitu & val) {
+       if (decode.page.index<4095) {
+        if (decode.page.invmap != NULL) {
+            if ((decode.page.invmap[decode.page.index] == 0) &&
+                (decode.page.invmap[decode.page.index + 1] == 0)
+            ) {
+                               val=decode_fetchw();
+                               return false;
+                       }
+                       HostPt tlb_addr=get_tlb_read(decode.code);
+                       if (tlb_addr) {
+                               val=(Bitu)(tlb_addr+decode.code);
+                               decode_increase_wmapmask(2);
+                               decode.code+=2;
+                               decode.page.index+=2;
+                               return true;
+                       }
+               }
+       }
+       val=decode_fetchw();
+       return false;
+}
+static bool decode_fetchd_imm(Bitu & val) {
+       if (decode.page.index<4093) {
+        if (decode.page.invmap != NULL) {
+            if ((decode.page.invmap[decode.page.index] == 0) &&
+                (decode.page.invmap[decode.page.index + 1] == 0) &&
+                (decode.page.invmap[decode.page.index + 2] == 0) &&
+                (decode.page.invmap[decode.page.index + 3] == 0)
+            ) {
+                               val=decode_fetchd();
+                               return false;
+                       }
+                       HostPt tlb_addr=get_tlb_read(decode.code);
+                       if (tlb_addr) {
+                               val=(Bitu)(tlb_addr+decode.code);
+                               decode_increase_wmapmask(4);
+                               decode.code+=4;
+                               decode.page.index+=4;
+                               return true;
+                       }
+               }
+       }
+       val=decode_fetchd();
+       return false;
+}
+
+
+static void dyn_reduce_cycles(void) {
+       gen_protectflags();
+       if (!decode.cycles) decode.cycles++;
+       gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);
+}
+
+static void dyn_save_noncritical_regs(void) {
+       gen_releasereg(DREG(EAX));
+       gen_releasereg(DREG(ECX));
+       gen_releasereg(DREG(EDX));
+       gen_releasereg(DREG(EBX));
+       gen_releasereg(DREG(ESP));
+       gen_releasereg(DREG(EBP));
+       gen_releasereg(DREG(ESI));
+       gen_releasereg(DREG(EDI));
+}
+
+static void dyn_save_critical_regs(void) {
+       dyn_save_noncritical_regs();
+       gen_releasereg(DREG(FLAGS));
+       gen_releasereg(DREG(EIP));
+       gen_releasereg(DREG(CYCLES));
+}
+
+static void dyn_set_eip_last_end(DynReg * endreg) {
+       gen_protectflags();
+       gen_lea(endreg,DREG(EIP),0,0,decode.code-decode.code_start);
+       gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),decode.op_start-decode.code_start);
+}
+
+static INLINE void dyn_set_eip_end(void) {
+       gen_protectflags();
+       gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.code-decode.code_start);
+}
+
+static INLINE void dyn_set_eip_end(DynReg * endreg) {
+       gen_protectflags();
+       if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EIP));
+       else gen_extend_word(false,DREG(TMPW),DREG(EIP));
+       gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start);
+}
+
+static INLINE void dyn_set_eip_last(void) {
+       gen_protectflags();
+       gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(EIP),decode.op_start-decode.code_start);
+}
+
+
+enum save_info_type {db_exception, cycle_check, normal, fpu_restore};
+
+
+static struct {
+       save_info_type type;
+       DynState state;
+       Bit8u * branch_pos;
+       Bit32u eip_change;
+       Bitu cycles;
+       Bit8u * return_pos;
+} save_info[512];
+
+Bitu used_save_info=0;
+
+
+static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags) {
+       reg_flags=(dflags&FMASK_TEST) | (reg_flags&(~FMASK_TEST));
+       reg_eip+=eip_add;
+       CPU_Cycles-=cycle_sub;
+       if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock;
+       CPU_Exception(cpu.exception.which,cpu.exception.error);
+       return BR_Normal;
+}
+
+static void dyn_check_bool_exception(DynReg * check) {
+       gen_dop_byte(DOP_OR,check,0,check,0);
+       save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
+       dyn_savestate(&save_info[used_save_info].state);
+       if (!decode.cycles) decode.cycles++;
+       save_info[used_save_info].cycles=decode.cycles;
+       save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
+       if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
+       save_info[used_save_info].type=db_exception;
+       used_save_info++;
+}
+
+static void dyn_check_bool_exception_al(void) {
+       cache_addw(0xc00a);             // or al, al
+       save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
+       dyn_savestate(&save_info[used_save_info].state);
+       if (!decode.cycles) decode.cycles++;
+       save_info[used_save_info].cycles=decode.cycles;
+       save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
+       if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
+       save_info[used_save_info].type=db_exception;
+       used_save_info++;
+}
+
+#include "pic.h"
+
+static void dyn_check_irqrequest(void) {
+       gen_load_host(&PIC_IRQCheck,DREG(TMPB),4);
+       gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB));
+       save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
+       gen_releasereg(DREG(TMPB));
+       dyn_savestate(&save_info[used_save_info].state);
+       if (!decode.cycles) decode.cycles++;
+       save_info[used_save_info].cycles=decode.cycles;
+       save_info[used_save_info].eip_change=decode.code-decode.code_start;
+       if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
+       save_info[used_save_info].type=normal;
+       used_save_info++;
+}
+
+static void dyn_check_bool_exception_ne(void) {
+       save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z);
+       dyn_savestate(&save_info[used_save_info].state);
+       if (!decode.cycles) decode.cycles++;
+       save_info[used_save_info].cycles=decode.cycles;
+       save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
+       if (!cpu.code.big) save_info[used_save_info].eip_change&=0xffff;
+       save_info[used_save_info].type=db_exception;
+       used_save_info++;
+}
+
+static void dyn_fill_blocks(void) {
+       for (Bitu sct=0; sct<used_save_info; sct++) {
+               gen_fill_branch_long(save_info[sct].branch_pos);
+               switch (save_info[sct].type) {
+                       case db_exception:
+                               dyn_loadstate(&save_info[sct].state);
+                               decode.cycles=save_info[sct].cycles;
+                               dyn_save_critical_regs();
+                               if (cpu.code.big) gen_call_function((void *)&DynRunException,"%Id%Id%F",save_info[sct].eip_change,save_info[sct].cycles);
+                               else gen_call_function((void *)&DynRunException,"%Iw%Id%F",save_info[sct].eip_change,save_info[sct].cycles);
+                               gen_return_fast(BR_Normal,true);
+                               break;
+                       case cycle_check:
+                               gen_return(BR_Cycles);
+                               break;
+                       case normal:
+                               dyn_loadstate(&save_info[sct].state);
+                               gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),save_info[sct].eip_change);
+                               dyn_save_critical_regs();
+                               gen_return(BR_Cycles);
+                               break;
+                       case fpu_restore:
+                               dyn_loadstate(&save_info[sct].state);
+                               gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4);
+                               gen_sop_word(SOP_INC,true,DREG(TMPB));
+                               GenReg * gr1=FindDynReg(DREG(TMPB));
+                               cache_addb(0xdd);       // FRSTOR fpu.state (fpu_restore)
+                               cache_addb(0x25);
+                               cache_addd((Bit32u)(&(dyn_dh_fpu.state[0])));
+                               cache_addb(0x89);       // mov fpu.state_used,1
+                               cache_addb(0x05|(gr1->index<<3));
+                               cache_addd((Bit32u)(&(dyn_dh_fpu.state_used)));
+                               gen_releasereg(DREG(TMPB));
+                               dyn_synchstate(&save_info[sct].state);
+                               gen_create_jump(save_info[sct].return_pos);
+                               break;
+               }
+       }
+       used_save_info=0;
+}
+
+
+#if !defined(X86_INLINED_MEMACCESS)
+static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
+       gen_protectflags();
+       gen_call_function((void *)&mem_readb_checked,"%Dd%Id",addr,&core_dyn.readdata);
+       dyn_check_bool_exception_al();
+       gen_mov_host(&core_dyn.readdata,dst,1,high);
+}
+static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) {
+       gen_protectflags();
+       if (high) gen_call_function((void *)&mem_writeb_checked,"%Dd%Dh",addr,val);
+       else gen_call_function((void *)&mem_writeb_checked,"%Dd%Dd",addr,val);
+       dyn_check_bool_exception_al();
+}
+static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
+       gen_protectflags();
+       if (dword) gen_call_function((void *)&mem_readd_checked,"%Dd%Id",addr,&core_dyn.readdata);
+       else gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
+       dyn_check_bool_exception_al();
+       gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
+}
+static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
+       gen_protectflags();
+       if (dword) gen_call_function((void *)&mem_writed_checked,"%Dd%Dd",addr,val);
+       else gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val);
+       dyn_check_bool_exception_al();
+}
+static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
+       gen_protectflags();
+       gen_call_function((void *)&mem_readb_checked,"%Ddr%Id",addr,&core_dyn.readdata);
+       dyn_check_bool_exception_al();
+       gen_mov_host(&core_dyn.readdata,dst,1,high);
+}
+static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) {
+       gen_protectflags();
+       if (high) gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dh",addr,val);
+       else gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dd",addr,val);
+       dyn_check_bool_exception_al();
+}
+static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
+       gen_protectflags();
+       if (dword) gen_call_function((void *)&mem_readd_checked,"%Ddr%Id",addr,&core_dyn.readdata);
+       else gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
+       dyn_check_bool_exception_al();
+       gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
+}
+static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
+       gen_protectflags();
+       if (dword) gen_call_function((void *)&mem_writed_checked,"%Ddr%Dd",addr,val);
+       else gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
+       dyn_check_bool_exception_al();
+}
+
+#else
+
+static void dyn_read_intro(DynReg * addr,bool release_addr=true) {
+       gen_protectflags();
+
+       if (addr->genreg) {
+               // addr already in a register
+               Bit8u reg_idx=(Bit8u)addr->genreg->index;
+               x86gen.regs[X86_REG_ECX]->Clear();
+               if (reg_idx!=1) {
+                       cache_addw(0xc88b+(reg_idx<<8));        //Mov ecx,reg
+               }
+               x86gen.regs[X86_REG_EAX]->Clear();
+               if (release_addr) gen_releasereg(addr);
+       } else {
+               // addr still in memory, directly move into ecx
+               x86gen.regs[X86_REG_EAX]->Clear();
+               x86gen.regs[X86_REG_ECX]->Clear();
+               cache_addw(0x0d8b);             //Mov ecx,[data]
+               cache_addd((Bit32u)addr->data);
+       }
+       x86gen.regs[X86_REG_EDX]->Clear();
+
+       cache_addw(0xc18b);             // mov eax,ecx
+}
+
+bool mem_readb_checked_dcx86(PhysPt address) {
+       return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dyn.readdata));
+}
+
+static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
+       dyn_read_intro(addr,false);
+
+       cache_addw(0xe8c1);             // shr eax,0x0c
+       cache_addb(0x0c);
+       cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
+       cache_addb(0x85);
+       cache_addd((Bit32u)(&paging.tlb.read[0]));
+       cache_addw(0xc085);             // test eax,eax
+       Bit8u* je_loc=gen_create_branch(BR_Z);
+
+
+       cache_addw(0x048a);             // mov al,[eax+ecx]
+       cache_addb(0x08);
+
+       Bit8u* jmp_loc=gen_create_jump();
+       gen_fill_branch(je_loc);
+       cache_addb(0x51);               // push ecx
+       cache_addb(0xe8);
+       cache_addd(((Bit32u)&mem_readb_checked_dcx86) - (Bit32u)cache.pos-4);
+       cache_addw(0xc483);             // add esp,4
+       cache_addb(0x04);
+       cache_addw(0x012c);             // sub al,1
+
+       dyn_check_bool_exception_ne();
+
+       cache_addw(0x058a);             //mov al,[]
+       cache_addd((Bit32u)(&core_dyn.readdata));
+
+       gen_fill_jump(jmp_loc);
+
+       x86gen.regs[X86_REG_EAX]->notusable=true;
+       GenReg * genreg=FindDynReg(dst);
+       x86gen.regs[X86_REG_EAX]->notusable=false;
+       cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0));
+       dst->flags|=DYNFLG_CHANGED;
+}
+
+static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
+       dyn_read_intro(addr);
+
+       cache_addw(0xe8c1);             // shr eax,0x0c
+       cache_addb(0x0c);
+       cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
+       cache_addb(0x85);
+       cache_addd((Bit32u)(&paging.tlb.read[0]));
+       cache_addw(0xc085);             // test eax,eax
+       Bit8u* je_loc=gen_create_branch(BR_Z);
+
+
+       cache_addw(0x048a);             // mov al,[eax+ecx]
+       cache_addb(0x08);
+
+       Bit8u* jmp_loc=gen_create_jump();
+       gen_fill_branch(je_loc);
+       cache_addb(0x51);               // push ecx
+       cache_addb(0xe8);
+       cache_addd(((Bit32u)&mem_readb_checked_dcx86) - (Bit32u)cache.pos-4);
+       cache_addw(0xc483);             // add esp,4
+       cache_addb(0x04);
+       cache_addw(0x012c);             // sub al,1
+
+       dyn_check_bool_exception_ne();
+
+       cache_addw(0x058a);             //mov al,[]
+       cache_addd((Bit32u)(&core_dyn.readdata));
+
+       gen_fill_jump(jmp_loc);
+
+       x86gen.regs[X86_REG_EAX]->notusable=true;
+       GenReg * genreg=FindDynReg(dst);
+       x86gen.regs[X86_REG_EAX]->notusable=false;
+       cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0));
+       dst->flags|=DYNFLG_CHANGED;
+}
+
+bool mem_readd_checked_dcx86(PhysPt address) {
+       if ((address & 0xfff)<0xffd) {
+               HostPt tlb_addr=get_tlb_read(address);
+               if (tlb_addr) {
+                       core_dyn.readdata=host_readd(tlb_addr+address);
+                       return false;
+               } else {
+                       return get_tlb_readhandler(address)->readd_checked(address, &core_dyn.readdata);
+               }
+       } else return mem_unalignedreadd_checked(address, &core_dyn.readdata);
+}
+
+static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
+       if (dword) {
+               dyn_read_intro(addr,false);
+
+               cache_addw(0xe8d1);             // shr eax,0x1
+               Bit8u* jb_loc1=gen_create_branch(BR_B);
+               cache_addw(0xe8d1);             // shr eax,0x1
+               Bit8u* jb_loc2=gen_create_branch(BR_B);
+               cache_addw(0xe8c1);             // shr eax,0x0a
+               cache_addb(0x0a);
+               cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
+               cache_addb(0x85);
+               cache_addd((Bit32u)(&paging.tlb.read[0]));
+               cache_addw(0xc085);             // test eax,eax
+               Bit8u* je_loc=gen_create_branch(BR_Z);
+
+               GenReg * genreg=FindDynReg(dst,true);
+
+               cache_addw(0x048b+(genreg->index <<(8+3)));             // mov dest,[eax+ecx]
+               cache_addb(0x08);
+
+               Bit8u* jmp_loc=gen_create_jump();
+               gen_fill_branch(jb_loc1);
+               gen_fill_branch(jb_loc2);
+               gen_fill_branch(je_loc);
+               cache_addb(0x51);               // push ecx
+               cache_addb(0xe8);
+               cache_addd(((Bit32u)&mem_readd_checked_dcx86) - (Bit32u)cache.pos-4);
+               cache_addw(0xc483);             // add esp,4
+               cache_addb(0x04);
+               cache_addw(0x012c);             // sub al,1
+
+               dyn_check_bool_exception_ne();
+
+               gen_mov_host(&core_dyn.readdata,dst,4);
+               dst->flags|=DYNFLG_CHANGED;
+
+               gen_fill_jump(jmp_loc);
+       } else {
+               gen_protectflags();
+               gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
+               dyn_check_bool_exception_al();
+               gen_mov_host(&core_dyn.readdata,dst,2);
+       }
+}
+
+static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
+       if (dword) {
+               dyn_read_intro(addr);
+
+               cache_addw(0xe8d1);             // shr eax,0x1
+               Bit8u* jb_loc1=gen_create_branch(BR_B);
+               cache_addw(0xe8d1);             // shr eax,0x1
+               Bit8u* jb_loc2=gen_create_branch(BR_B);
+               cache_addw(0xe8c1);             // shr eax,0x0a
+               cache_addb(0x0a);
+               cache_addw(0x048b);             // mov eax,paging.tlb.read[eax*TYPE Bit32u]
+               cache_addb(0x85);
+               cache_addd((Bit32u)(&paging.tlb.read[0]));
+               cache_addw(0xc085);             // test eax,eax
+               Bit8u* je_loc=gen_create_branch(BR_Z);
+
+               GenReg * genreg=FindDynReg(dst,true);
+
+               cache_addw(0x048b+(genreg->index <<(8+3)));             // mov dest,[eax+ecx]
+               cache_addb(0x08);
+
+               Bit8u* jmp_loc=gen_create_jump();
+               gen_fill_branch(jb_loc1);
+               gen_fill_branch(jb_loc2);
+               gen_fill_branch(je_loc);
+               cache_addb(0x51);               // push ecx
+               cache_addb(0xe8);
+               cache_addd(((Bit32u)&mem_readd_checked_dcx86) - (Bit32u)cache.pos-4);
+               cache_addw(0xc483);             // add esp,4
+               cache_addb(0x04);
+               cache_addw(0x012c);             // sub al,1
+
+               dyn_check_bool_exception_ne();
+
+               gen_mov_host(&core_dyn.readdata,dst,4);
+               dst->flags|=DYNFLG_CHANGED;
+
+               gen_fill_jump(jmp_loc);
+       } else {
+               gen_protectflags();
+               gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
+               dyn_check_bool_exception_al();
+               gen_mov_host(&core_dyn.readdata,dst,2);
+       }
+}
+
+static void dyn_write_intro(DynReg * addr,bool release_addr=true) {
+       gen_protectflags();
+
+       if (addr->genreg) {
+               // addr in a register
+               Bit8u reg_idx_addr=(Bit8u)addr->genreg->index;
+
+               x86gen.regs[X86_REG_EAX]->Clear();
+               x86gen.regs[X86_REG_EAX]->notusable=true;
+               x86gen.regs[X86_REG_ECX]->Clear();
+               x86gen.regs[X86_REG_ECX]->notusable=true;
+
+               if (reg_idx_addr) {
+                       // addr!=eax
+                       cache_addb(0x8b);               //Mov eax,reg
+                       cache_addb(0xc0+reg_idx_addr);
+               }
+               if (release_addr) gen_releasereg(addr);
+       } else {
+               // addr still in memory, directly move into eax
+               x86gen.regs[X86_REG_EAX]->Clear();
+               x86gen.regs[X86_REG_EAX]->notusable=true;
+               x86gen.regs[X86_REG_ECX]->Clear();
+               x86gen.regs[X86_REG_ECX]->notusable=true;
+               cache_addb(0xa1);               //Mov eax,[data]
+               cache_addd((Bit32u)addr->data);
+       }
+
+       cache_addw(0xc88b);             // mov ecx,eax
+}
+
+static void dyn_write_byte(DynReg * addr,DynReg * val,bool high) {
+       dyn_write_intro(addr,false);
+
+       GenReg * genreg=FindDynReg(val);
+       cache_addw(0xe9c1);             // shr ecx,0x0c
+       cache_addb(0x0c);
+       cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
+       cache_addb(0x8d);
+       cache_addd((Bit32u)(&paging.tlb.write[0]));
+       cache_addw(0xc985);             // test ecx,ecx
+       Bit8u* je_loc=gen_create_branch(BR_Z);
+
+       cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0));         // mov [eax+ecx],reg
+       cache_addb(0x08);
+
+       Bit8u* jmp_loc=gen_create_jump();
+       gen_fill_branch(je_loc);
+
+       if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
+       cache_addb(0x52);       // push edx
+       cache_addb(0x50+genreg->index);
+       cache_addb(0x50);       // push eax
+       if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
+       cache_addb(0xe8);
+       cache_addd(((Bit32u)&mem_writeb_checked) - (Bit32u)cache.pos-4);
+       cache_addw(0xc483);             // add esp,8
+       cache_addb(0x08);
+       cache_addw(0x012c);             // sub al,1
+       cache_addb(0x5a);               // pop edx
+
+       // Restore registers to be used again
+       x86gen.regs[X86_REG_EAX]->notusable=false;
+       x86gen.regs[X86_REG_ECX]->notusable=false;
+
+       dyn_check_bool_exception_ne();
+
+       gen_fill_jump(jmp_loc);
+}
+
+static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
+       dyn_write_intro(addr);
+
+       GenReg * genreg=FindDynReg(val);
+       cache_addw(0xe9c1);             // shr ecx,0x0c
+       cache_addb(0x0c);
+       cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
+       cache_addb(0x8d);
+       cache_addd((Bit32u)(&paging.tlb.write[0]));
+       cache_addw(0xc985);             // test ecx,ecx
+       Bit8u* je_loc=gen_create_branch(BR_Z);
+
+       cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0));         // mov [eax+ecx],reg
+       cache_addb(0x08);
+
+       Bit8u* jmp_loc=gen_create_jump();
+       gen_fill_branch(je_loc);
+
+       cache_addb(0x52);       // push edx
+       if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
+       cache_addb(0x50+genreg->index);
+       cache_addb(0x50);       // push eax
+       if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
+       cache_addb(0xe8);
+       cache_addd(((Bit32u)&mem_writeb_checked) - (Bit32u)cache.pos-4);
+       cache_addw(0xc483);             // add esp,8
+       cache_addb(0x08);
+       cache_addw(0x012c);             // sub al,1
+       cache_addb(0x5a);               // pop edx
+
+       // Restore registers to be used again
+       x86gen.regs[X86_REG_EAX]->notusable=false;
+       x86gen.regs[X86_REG_ECX]->notusable=false;
+
+       dyn_check_bool_exception_ne();
+
+       gen_fill_jump(jmp_loc);
+}
+
+static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
+       if (dword) {
+               dyn_write_intro(addr,false);
+
+               GenReg * genreg=FindDynReg(val);
+               cache_addw(0xe9d1);             // shr ecx,0x1
+               Bit8u* jb_loc1=gen_create_branch(BR_B);
+               cache_addw(0xe9d1);             // shr ecx,0x1
+               Bit8u* jb_loc2=gen_create_branch(BR_B);
+               cache_addw(0xe9c1);             // shr ecx,0x0a
+               cache_addb(0x0a);
+               cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
+               cache_addb(0x8d);
+               cache_addd((Bit32u)(&paging.tlb.write[0]));
+               cache_addw(0xc985);             // test ecx,ecx
+               Bit8u* je_loc=gen_create_branch(BR_Z);
+
+               cache_addw(0x0489+(genreg->index <<(8+3)));             // mov [eax+ecx],reg
+               cache_addb(0x08);
+
+               Bit8u* jmp_loc=gen_create_jump();
+               gen_fill_branch(jb_loc1);
+               gen_fill_branch(jb_loc2);
+               gen_fill_branch(je_loc);
+
+               cache_addb(0x52);       // push edx
+               cache_addb(0x50+genreg->index);
+               cache_addb(0x50);       // push eax
+               cache_addb(0xe8);
+               cache_addd(((Bit32u)&mem_writed_checked) - (Bit32u)cache.pos-4);
+               cache_addw(0xc483);             // add esp,8
+               cache_addb(0x08);
+               cache_addw(0x012c);             // sub al,1
+               cache_addb(0x5a);               // pop edx
+
+               // Restore registers to be used again
+               x86gen.regs[X86_REG_EAX]->notusable=false;
+               x86gen.regs[X86_REG_ECX]->notusable=false;
+
+               dyn_check_bool_exception_ne();
+
+               gen_fill_jump(jmp_loc);
+       } else {
+               gen_protectflags();
+               gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val);
+               dyn_check_bool_exception_al();
+       }
+}
+
+static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
+       if (dword) {
+               dyn_write_intro(addr);
+
+               GenReg * genreg=FindDynReg(val);
+               cache_addw(0xe9d1);             // shr ecx,0x1
+               Bit8u* jb_loc1=gen_create_branch(BR_B);
+               cache_addw(0xe9d1);             // shr ecx,0x1
+               Bit8u* jb_loc2=gen_create_branch(BR_B);
+               cache_addw(0xe9c1);             // shr ecx,0x0a
+               cache_addb(0x0a);
+               cache_addw(0x0c8b);             // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
+               cache_addb(0x8d);
+               cache_addd((Bit32u)(&paging.tlb.write[0]));
+               cache_addw(0xc985);             // test ecx,ecx
+               Bit8u* je_loc=gen_create_branch(BR_Z);
+
+               cache_addw(0x0489+(genreg->index <<(8+3)));             // mov [eax+ecx],reg
+               cache_addb(0x08);
+
+               Bit8u* jmp_loc=gen_create_jump();
+               gen_fill_branch(jb_loc1);
+               gen_fill_branch(jb_loc2);
+               gen_fill_branch(je_loc);
+
+               cache_addb(0x52);       // push edx
+               cache_addb(0x50+genreg->index);
+               cache_addb(0x50);       // push eax
+               cache_addb(0xe8);
+               cache_addd(((Bit32u)&mem_writed_checked) - (Bit32u)cache.pos-4);
+               cache_addw(0xc483);             // add esp,8
+               cache_addb(0x08);
+               cache_addw(0x012c);             // sub al,1
+               cache_addb(0x5a);               // pop edx
+
+               // Restore registers to be used again
+               x86gen.regs[X86_REG_EAX]->notusable=false;
+               x86gen.regs[X86_REG_ECX]->notusable=false;
+
+               dyn_check_bool_exception_ne();
+
+               gen_fill_jump(jmp_loc);
+       } else {
+               gen_protectflags();
+               gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
+               dyn_check_bool_exception_al();
+       }
+}
+
+#endif
+
+
+static void dyn_push_unchecked(DynReg * dynreg) {
+       gen_protectflags();
+       gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2));
+       gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
+       gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask);
+       gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK));
+       gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
+       if (decode.big_op) {
+               gen_call_function((void *)&mem_writed,"%Drd%Dd",DREG(STACK),dynreg);
+       } else {
+               //Can just push the whole 32-bit word as operand
+               gen_call_function((void *)&mem_writew,"%Drd%Dd",DREG(STACK),dynreg);
+       }
+}
+
+static void dyn_push(DynReg * dynreg) {
+       gen_protectflags();
+       gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?(-4):(-2));
+       gen_dop_word(DOP_MOV,true,DREG(NEWESP),DREG(ESP));
+       gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
+       gen_dop_word_var(DOP_AND,true,DREG(NEWESP),&cpu.stack.notmask);
+       gen_dop_word(DOP_OR,true,DREG(NEWESP),DREG(STACK));
+       gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
+       if (decode.big_op) {
+               gen_call_function((void *)&mem_writed_checked,"%Drd%Dd",DREG(STACK),dynreg);
+       } else {
+               //Can just push the whole 32-bit word as operand
+               gen_call_function((void *)&mem_writew_checked,"%Drd%Dd",DREG(STACK),dynreg);
+       }
+       dyn_check_bool_exception_al();
+       /* everything was ok, change register now */
+       gen_dop_word(DOP_MOV,true,DREG(ESP),DREG(NEWESP));
+       gen_releasereg(DREG(NEWESP));
+}
+
+static void dyn_pop(DynReg * dynreg,bool checked=true) {
+       gen_protectflags();
+       gen_dop_word(DOP_MOV,true,DREG(STACK),DREG(ESP));
+       gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
+       gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
+       if (checked) {
+               if (decode.big_op) {
+                       gen_call_function((void *)&mem_readd_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
+               } else {
+                       gen_call_function((void *)&mem_readw_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
+               }
+               dyn_check_bool_exception_al();
+               gen_mov_host(&core_dyn.readdata,dynreg,decode.big_op?4:2);
+       } else {
+               if (decode.big_op) {
+                       gen_call_function((void *)&mem_readd,"%Rd%Drd",dynreg,DREG(STACK));
+               } else {
+                       gen_call_function((void *)&mem_readw,"%Rw%Drd",dynreg,DREG(STACK));
+               }
+       }
+       if (dynreg!=DREG(ESP)) {
+               gen_lea(DREG(STACK),DREG(ESP),0,0,decode.big_op?4:2);
+               gen_dop_word_var(DOP_AND,true,DREG(STACK),&cpu.stack.mask);
+               gen_dop_word_var(DOP_AND,true,DREG(ESP),&cpu.stack.notmask);
+               gen_dop_word(DOP_OR,true,DREG(ESP),DREG(STACK));
+       }
+}
+
+static INLINE void dyn_get_modrm(void) {
+       decode.modrm.val=decode_fetchb();
+       decode.modrm.mod=(decode.modrm.val >> 6) & 3;
+       decode.modrm.reg=(decode.modrm.val >> 3) & 7;
+       decode.modrm.rm=(decode.modrm.val & 7);
+}
+
+static void dyn_fill_ea(bool addseg=true, DynReg * reg_ea=DREG(EA)) {
+       DynReg * segbase;
+       if (!decode.big_addr) {
+               Bits imm;
+               switch (decode.modrm.mod) {
+               case 0:imm=0;break;
+               case 1:imm=(Bit8s)decode_fetchb();break;
+               case 2:imm=(Bit16s)decode_fetchw();break;
+               }
+               DynReg * extend_src=reg_ea;
+               switch (decode.modrm.rm) {
+               case 0:/* BX+SI */
+                       gen_lea(reg_ea,DREG(EBX),DREG(ESI),0,imm);
+                       segbase=DREG(DS);
+                       break;
+               case 1:/* BX+DI */
+                       gen_lea(reg_ea,DREG(EBX),DREG(EDI),0,imm);
+                       segbase=DREG(DS);
+                       break;
+               case 2:/* BP+SI */
+                       gen_lea(reg_ea,DREG(EBP),DREG(ESI),0,imm);
+                       segbase=DREG(SS);
+                       break;
+               case 3:/* BP+DI */
+                       gen_lea(reg_ea,DREG(EBP),DREG(EDI),0,imm);
+                       segbase=DREG(SS);
+                       break;
+               case 4:/* SI */
+                       if (imm) gen_lea(reg_ea,DREG(ESI),0,0,imm);
+                       else extend_src=DREG(ESI);
+                       segbase=DREG(DS);
+                       break;
+               case 5:/* DI */
+                       if (imm) gen_lea(reg_ea,DREG(EDI),0,0,imm);
+                       else extend_src=DREG(EDI);
+                       segbase=DREG(DS);
+                       break;
+               case 6:/* imm/BP */
+                       if (!decode.modrm.mod) {
+                               imm=decode_fetchw();
+                gen_dop_word_imm(DOP_MOV,true,reg_ea,imm);
+                               segbase=DREG(DS);
+                               goto skip_extend_word;
+                       } else {
+                               gen_lea(reg_ea,DREG(EBP),0,0,imm);
+                               segbase=DREG(SS);
+                       }
+                       break;
+               case 7: /* BX */
+                       if (imm) gen_lea(reg_ea,DREG(EBX),0,0,imm);
+                       else extend_src=DREG(EBX);
+                       segbase=DREG(DS);
+                       break;
+               }
+               gen_extend_word(false,reg_ea,extend_src);
+skip_extend_word:
+               if (addseg) {
+                       gen_lea(reg_ea,reg_ea,decode.segprefix ? decode.segprefix : segbase,0,0);
+               }
+       } else {
+               Bits imm=0;
+               DynReg * base=0;DynReg * scaled=0;Bitu scale=0;
+               switch (decode.modrm.rm) {
+               case 0:base=DREG(EAX);segbase=DREG(DS);break;
+               case 1:base=DREG(ECX);segbase=DREG(DS);break;
+               case 2:base=DREG(EDX);segbase=DREG(DS);break;
+               case 3:base=DREG(EBX);segbase=DREG(DS);break;
+               case 4: /* SIB */
+                       {
+                               Bitu sib=decode_fetchb();
+                               static DynReg * scaledtable[8]={
+                                       DREG(EAX),DREG(ECX),DREG(EDX),DREG(EBX),
+                                                       0,DREG(EBP),DREG(ESI),DREG(EDI),
+                               };
+                               scaled=scaledtable[(sib >> 3) &7];
+                               scale=(sib >> 6);
+                               switch (sib & 7) {
+                               case 0:base=DREG(EAX);segbase=DREG(DS);break;
+                               case 1:base=DREG(ECX);segbase=DREG(DS);break;
+                               case 2:base=DREG(EDX);segbase=DREG(DS);break;
+                               case 3:base=DREG(EBX);segbase=DREG(DS);break;
+                               case 4:base=DREG(ESP);segbase=DREG(SS);break;
+                               case 5:
+                                       if (decode.modrm.mod) {
+                                               base=DREG(EBP);segbase=DREG(SS);
+                                       } else {
+                                               segbase=DREG(DS);
+                                               Bitu val;
+                                               if (decode_fetchd_imm(val)) {
+                                                       gen_mov_host((void*)val,DREG(EA),4);
+                                                       if (!addseg) {
+                                                               gen_lea(reg_ea,DREG(EA),scaled,scale,0);
+                                                       } else {
+                                                               DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
+                                                               gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
+                                                               gen_lea(reg_ea,DREG(EA),*seg,0,0);
+                                                       }
+                                                       return;
+                                               }
+                                               imm=(Bit32s)val;
+                                       }
+                                       break;
+                               case 6:base=DREG(ESI);segbase=DREG(DS);break;
+                               case 7:base=DREG(EDI);segbase=DREG(DS);break;
+                               }
+                       }       
+                       break;  /* SIB Break */
+               case 5:
+                       if (decode.modrm.mod) {
+                               base=DREG(EBP);segbase=DREG(SS);
+                       } else {
+                               imm=(Bit32s)decode_fetchd();segbase=DREG(DS);
+                       }
+                       break;
+               case 6:base=DREG(ESI);segbase=DREG(DS);break;
+               case 7:base=DREG(EDI);segbase=DREG(DS);break;
+               }
+               switch (decode.modrm.mod) {
+               case 1:imm=(Bit8s)decode_fetchb();break;
+               case 2: {
+                       Bitu val;
+                       if (decode_fetchd_imm(val)) {
+                               gen_mov_host((void*)val,DREG(EA),4);
+                               if (!addseg) {
+                                       gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
+                                       gen_lea(reg_ea,DREG(EA),base,0,0);
+                               } else {
+                                       DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
+                                       if (!base) {
+                                               gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
+                                               gen_lea(reg_ea,DREG(EA),*seg,0,0);
+                                       } else if (!scaled) {
+                                               gen_lea(DREG(EA),DREG(EA),*seg,0,0);
+                                               gen_lea(reg_ea,DREG(EA),base,0,0);
+                                       } else {
+                                               gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
+                                               gen_lea(DREG(EA),DREG(EA),base,0,0);
+                                               gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0);
+                                       }
+                               }
+                               return;
+                       }
+                       
+                       imm=(Bit32s)val;
+                       break;
+                       }
+               }
+               if (!addseg) {
+                       gen_lea(reg_ea,base,scaled,scale,imm);
+               } else {
+                       DynReg** seg = decode.segprefix ? &decode.segprefix : &segbase;
+                       if (!base) gen_lea(reg_ea,*seg,scaled,scale,imm);
+                       else if (!scaled) gen_lea(reg_ea,base,*seg,0,imm);
+                       else {
+                               gen_lea(DREG(EA),base,scaled,scale,imm);
+                               gen_lea(reg_ea,DREG(EA),decode.segprefix ? decode.segprefix : segbase,0,0);
+                       }
+               }
+       }
+}
+
+
+static void dyn_dop_word_imm(DualOps op,bool dword,DynReg * dr1) {
+       Bitu val;
+       if (dword) {
+               if (decode_fetchd_imm(val)) {
+                       gen_dop_word_imm_mem(op,true,dr1,(void*)val);
+                       return;
+               }
+       } else {
+               if (decode_fetchw_imm(val)) {
+                       gen_dop_word_imm_mem(op,false,dr1,(void*)val);
+                       return;
+               }
+       }
+       gen_dop_word_imm(op,dword,dr1,val);
+}
+
+static void dyn_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1) {
+       Bitu val;
+       if (decode_fetchb_imm(val)) {
+               gen_dop_byte_imm_mem(op,dr1,di1,(void*)val);
+       } else {
+               gen_dop_byte_imm(op,dr1,di1,(Bit8u)val);
+       }
+}
+
+
+#include "helpers.h"
+#include "string.h"
+
+
+static void dyn_dop_ebgb(DualOps op) {
+       dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
+               dyn_read_byte(DREG(EA),DREG(TMPB),false);
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else set_skipflags(false);
+               }
+               gen_dop_byte(op,DREG(TMPB),0,rm_reg,decode.modrm.reg&4);
+               if (op!=DOP_CMP) dyn_write_byte_release(DREG(EA),DREG(TMPB),false);
+               else gen_releasereg(DREG(EA));
+               gen_releasereg(DREG(TMPB));
+       } else {
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else gen_discardflags();
+               }
+               gen_dop_byte(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,decode.modrm.reg&4);
+       }
+}
+
+
+static void dyn_dop_gbeb(DualOps op) {
+       dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
+               dyn_read_byte_release(DREG(EA),DREG(TMPB),false);
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else set_skipflags(false);
+               }
+               gen_dop_byte(op,rm_reg,decode.modrm.reg&4,DREG(TMPB),0);
+               gen_releasereg(DREG(TMPB));
+       } else {
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else gen_discardflags();
+               }
+               gen_dop_byte(op,rm_reg,decode.modrm.reg&4,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
+       }
+}
+
+static void dyn_mov_ebib(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               gen_call_write(DREG(EA),decode_fetchb(),1);
+               dyn_check_bool_exception_al();
+       } else {
+               gen_dop_byte_imm(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,decode_fetchb());
+       }
+}
+
+static void dyn_mov_ebgb(void) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_write_byte_release(DREG(EA),rm_reg,rm_regi==4);
+       } else {
+               gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi);
+       }
+}
+
+static void dyn_mov_gbeb(void) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_read_byte_release(DREG(EA),rm_reg,rm_regi);
+       } else {
+               gen_dop_byte(DOP_MOV,rm_reg,rm_regi,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
+       }
+}
+
+static void dyn_dop_evgv(DualOps op) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
+               dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else set_skipflags(false);
+               }
+               gen_dop_word(op,decode.big_op,DREG(TMPW),rm_reg);
+               if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+               else gen_releasereg(DREG(EA));
+               gen_releasereg(DREG(TMPW));
+       } else {
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else gen_discardflags();
+               }
+               gen_dop_word(op,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg);
+       }
+}
+
+static void dyn_imul_gvev(Bitu immsize) {
+       dyn_get_modrm();DynReg * src;
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+               src=DREG(TMPW);
+       } else {
+               src=&DynRegs[decode.modrm.rm];
+       }
+       gen_needflags();
+       switch (immsize) {
+       case 0:gen_imul_word(decode.big_op,rm_reg,src);break;
+       case 1:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit8s)decode_fetchb());break;
+       case 2:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit16s)decode_fetchw());break;
+       case 4:gen_imul_word_imm(decode.big_op,rm_reg,src,(Bit32s)decode_fetchd());break;
+       }
+       gen_releasereg(DREG(TMPW));
+}
+
+static void dyn_dop_gvev(DualOps op) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
+               dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else set_skipflags(false);
+               }
+               gen_dop_word(op,decode.big_op,rm_reg,DREG(TMPW));
+               gen_releasereg(DREG(TMPW));
+       } else {
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else gen_discardflags();
+               }
+               gen_dop_word(op,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]);
+       }
+}
+
+static void dyn_mov_evgv(void) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_write_word_release(DREG(EA),rm_reg,decode.big_op);
+       } else {
+               gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg);
+       }
+}
+
+static void dyn_mov_gvev(void) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_read_word_release(DREG(EA),rm_reg,decode.big_op);
+       } else {
+               gen_dop_word(DOP_MOV,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm]);
+       }
+}
+static void dyn_mov_eviv(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               gen_call_write(DREG(EA),decode.big_op ? decode_fetchd() : decode_fetchw(),decode.big_op?4:2);
+               dyn_check_bool_exception_al();
+       } else {
+               gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],decode.big_op ? decode_fetchd() : decode_fetchw());
+       }
+}
+
+static void dyn_mov_ev_gb(bool sign) {
+       dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_read_byte_release(DREG(EA),DREG(TMPB),false);
+               gen_extend_byte(sign,decode.big_op,rm_reg,DREG(TMPB),0);
+               gen_releasereg(DREG(TMPB));
+       } else {
+               gen_extend_byte(sign,decode.big_op,rm_reg,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
+       }
+}
+
+static void dyn_mov_ev_gw(bool sign) {
+       if (!decode.big_op) {
+               dyn_mov_gvev();
+               return;
+       }
+       dyn_get_modrm();DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_read_word_release(DREG(EA),DREG(TMPW),false);
+               gen_extend_word(sign,rm_reg,DREG(TMPW));
+               gen_releasereg(DREG(TMPW));
+       } else {
+               gen_extend_word(sign,rm_reg,&DynRegs[decode.modrm.rm]);
+       }
+}
+
+static void dyn_cmpxchg_evgv(void) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       gen_protectflags();
+       if (decode.modrm.mod<3) {
+               gen_releasereg(DREG(EAX));
+               gen_releasereg(DREG(TMPB));
+               gen_releasereg(rm_reg);
+
+               dyn_fill_ea();
+               dyn_read_word(DREG(EA),DREG(TMPB),decode.big_op);
+               gen_dop_word(DOP_CMP,decode.big_op,DREG(EAX),DREG(TMPB));
+               Bit8u * branch=gen_create_branch(BR_NZ);
+
+               // eax==mem -> mem:=rm_reg
+               dyn_write_word_release(DREG(EA),rm_reg,decode.big_op);
+               gen_setzeroflag();
+               gen_releasereg(DREG(EAX));
+               gen_releasereg(DREG(TMPB));
+               gen_releasereg(rm_reg);
+
+               Bit8u * jump=gen_create_jump();
+
+               gen_fill_branch(branch);
+               // eax!=mem -> eax:=mem
+               dyn_write_word_release(DREG(EA),DREG(TMPB),decode.big_op);      // cmpxchg always issues write
+               gen_dop_word(DOP_MOV,decode.big_op,DREG(EAX),DREG(TMPB));
+               gen_clearzeroflag();
+               gen_releasereg(DREG(EAX));
+               gen_releasereg(DREG(TMPB));
+               gen_releasereg(rm_reg);
+
+               gen_fill_jump(jump);
+       } else {
+               gen_releasereg(DREG(EAX));
+               gen_releasereg(&DynRegs[decode.modrm.rm]);
+               gen_releasereg(rm_reg);
+
+               gen_dop_word(DOP_CMP,decode.big_op,DREG(EAX),&DynRegs[decode.modrm.rm]);
+               Bit8u * branch=gen_create_branch(BR_NZ);
+
+               // eax==rm -> rm:=rm_reg
+               gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],rm_reg);
+               gen_setzeroflag();
+               gen_releasereg(DREG(EAX));
+               gen_releasereg(&DynRegs[decode.modrm.rm]);
+               gen_releasereg(rm_reg);
+
+               Bit8u * jump=gen_create_jump();
+
+               gen_fill_branch(branch);
+               // eax!=rm -> eax:=rm
+               gen_dop_word(DOP_MOV,decode.big_op,DREG(EAX),&DynRegs[decode.modrm.rm]);
+               gen_clearzeroflag();
+               gen_releasereg(DREG(EAX));
+               gen_releasereg(&DynRegs[decode.modrm.rm]);
+               gen_releasereg(rm_reg);
+
+               gen_fill_jump(jump);
+       }
+}
+
+static void dyn_dshift_ev_gv(bool left,bool immediate) {
+       dyn_get_modrm();
+       DynReg * rm_reg=&DynRegs[decode.modrm.reg];
+       DynReg * ea_reg;
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();ea_reg=DREG(TMPW);
+               dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
+       } else ea_reg=&DynRegs[decode.modrm.rm];
+       gen_needflags();
+       if (immediate) gen_dshift_imm(decode.big_op,left,ea_reg,rm_reg,decode_fetchb());
+       else gen_dshift_cl(decode.big_op,left,ea_reg,rm_reg,DREG(ECX));
+       if (decode.modrm.mod<3) {
+               dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+               gen_releasereg(DREG(TMPW));
+       }
+}
+
+
+static DualOps grp1_table[8]={DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP};
+static void dyn_grp1_eb_ib(void) {
+       dyn_get_modrm();
+       DualOps op=grp1_table[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
+               dyn_read_byte(DREG(EA),DREG(TMPB),false);
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else set_skipflags(false);
+               }
+               gen_dop_byte_imm(op,DREG(TMPB),0,decode_fetchb());
+               if (op!=DOP_CMP) dyn_write_byte_release(DREG(EA),DREG(TMPB),false);
+               else gen_releasereg(DREG(EA));
+               gen_releasereg(DREG(TMPB));
+       } else {
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else gen_discardflags();
+               }
+               dyn_dop_byte_imm(op,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
+       }
+}
+
+static void dyn_grp1_ev_ivx(bool withbyte) {
+       dyn_get_modrm();
+       DualOps op=grp1_table[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               if ((op<=DOP_TEST) && (op!=DOP_ADC && op!=DOP_SBB)) set_skipflags(true);
+               dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else set_skipflags(false);
+               }
+               if (!withbyte) {
+                       dyn_dop_word_imm(op,decode.big_op,DREG(TMPW));
+               } else {
+                       gen_dop_word_imm(op,decode.big_op,DREG(TMPW),(Bit8s)decode_fetchb());
+               }
+               if (op!=DOP_CMP) dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+               else gen_releasereg(DREG(EA));
+               gen_releasereg(DREG(TMPW));
+       } else {
+               if (op<=DOP_TEST) {
+                       if (op==DOP_ADC || op==DOP_SBB) gen_needcarry();
+                       else gen_discardflags();
+               }
+               if (!withbyte) {
+                       dyn_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm]);
+               } else {
+                       gen_dop_word_imm(op,decode.big_op,&DynRegs[decode.modrm.rm],(Bit8s)decode_fetchb());
+               }
+       }
+}
+
+enum grp2_types {
+       grp2_1,grp2_imm,grp2_cl,
+};
+
+static void dyn_grp2_eb(grp2_types type) {
+       dyn_get_modrm();DynReg * src;Bit8u src_i;
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false);
+               src=DREG(TMPB);
+               src_i=0;
+       } else {
+               src=&DynRegs[decode.modrm.rm&3];
+               src_i=decode.modrm.rm&4;
+       }
+       switch (type) {
+       case grp2_1:
+               /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
+               if (decode.modrm.reg < 4) gen_needflags();
+               else gen_discardflags();
+               gen_shift_byte_imm(decode.modrm.reg,src,src_i,1);
+               break;
+       case grp2_imm: {
+               Bit8u imm=decode_fetchb();
+               if (imm) {
+                       /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
+                       if (decode.modrm.reg < 4) gen_needflags();
+                       else gen_discardflags();
+                       gen_shift_byte_imm(decode.modrm.reg,src,src_i,imm);
+               } else return;
+               }
+               break;
+       case grp2_cl:
+               gen_needflags();        /* flags must not be changed on ecx==0 */
+               gen_shift_byte_cl (decode.modrm.reg,src,src_i,DREG(ECX));
+               break;
+       }
+       if (decode.modrm.mod<3) {
+               dyn_write_byte_release(DREG(EA),src,false);
+               gen_releasereg(src);
+       }
+}
+
+static void dyn_grp2_ev(grp2_types type) {
+       dyn_get_modrm();DynReg * src;
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
+               src=DREG(TMPW);
+       } else {
+               src=&DynRegs[decode.modrm.rm];
+       }
+       switch (type) {
+       case grp2_1:
+               /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
+               if (decode.modrm.reg < 4) gen_needflags();
+               else gen_discardflags();
+               gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,1);
+               break;
+       case grp2_imm: {
+               Bitu val;
+               if (decode_fetchb_imm(val)) {
+                       if (decode.modrm.reg < 4) gen_needflags();
+                       else gen_discardflags();
+                       gen_load_host((void*)val,DREG(TMPB),1);
+                       gen_shift_word_cl(decode.modrm.reg,decode.big_op,src,DREG(TMPB));
+                       gen_releasereg(DREG(TMPB));
+                       break;
+               }
+               Bit8u imm=(Bit8u)val;
+               if (imm) {
+                       /* rotates (first 4 ops) alter cf/of only; shifts (last 4 ops) alter all flags */
+                       if (decode.modrm.reg < 4) gen_needflags();
+                       else gen_discardflags();
+                       gen_shift_word_imm(decode.modrm.reg,decode.big_op,src,imm);
+               } else return;
+               }
+               break;
+       case grp2_cl:
+               gen_needflags();        /* flags must not be changed on ecx==0 */
+               gen_shift_word_cl (decode.modrm.reg,decode.big_op,src,DREG(ECX));
+               break;
+       }
+       if (decode.modrm.mod<3) {
+               dyn_write_word_release(DREG(EA),src,decode.big_op);
+               gen_releasereg(src);
+       }
+}
+
+static void dyn_grp3_eb(void) {
+       dyn_get_modrm();DynReg * src;Bit8u src_i;
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               if ((decode.modrm.reg==0) || (decode.modrm.reg==3)) set_skipflags(true);
+               dyn_read_byte(DREG(EA),DREG(TMPB),false);
+               src=DREG(TMPB);src_i=0;
+       } else {
+               src=&DynRegs[decode.modrm.rm&3];
+               src_i=decode.modrm.rm&4;
+       }
+       switch (decode.modrm.reg) {
+       case 0x0:       /* test eb,ib */
+               set_skipflags(false);gen_dop_byte_imm(DOP_TEST,src,src_i,decode_fetchb());
+               goto skipsave;
+       case 0x2:       /* NOT Eb */
+               gen_sop_byte(SOP_NOT,src,src_i);
+               break;
+       case 0x3:       /* NEG Eb */
+               set_skipflags(false);gen_sop_byte(SOP_NEG,src,src_i);
+               break;
+       case 0x4:       /* mul Eb */
+               gen_needflags();gen_mul_byte(false,DREG(EAX),src,src_i);
+               goto skipsave;
+       case 0x5:       /* imul Eb */
+               gen_needflags();gen_mul_byte(true,DREG(EAX),src,src_i);
+               goto skipsave;
+       case 0x6:       /* div Eb */
+       case 0x7:       /* idiv Eb */
+               /* EAX could be used, so precache it */
+               if (decode.modrm.mod==3)
+                       gen_dop_byte(DOP_MOV,DREG(TMPB),0,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
+               gen_releasereg(DREG(EAX));
+               gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb,
+                       "%Rd%Dd",DREG(TMPB),DREG(TMPB));
+               dyn_check_bool_exception(DREG(TMPB));
+               goto skipsave;
+       }
+       /* Save the result if memory op */
+       if (decode.modrm.mod<3) dyn_write_byte_release(DREG(EA),src,false);
+skipsave:
+       gen_releasereg(DREG(TMPB));gen_releasereg(DREG(EA));
+}
+
+static void dyn_grp3_ev(void) {
+       dyn_get_modrm();DynReg * src;
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();src=DREG(TMPW);
+               if ((decode.modrm.reg==0) || (decode.modrm.reg==3)) set_skipflags(true);
+               dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
+       } else src=&DynRegs[decode.modrm.rm];
+       switch (decode.modrm.reg) {
+       case 0x0:       /* test ev,iv */
+               set_skipflags(false);gen_dop_word_imm(DOP_TEST,decode.big_op,src,decode.big_op ? decode_fetchd() : decode_fetchw());
+               goto skipsave;
+       case 0x2:       /* NOT Ev */
+               gen_sop_word(SOP_NOT,decode.big_op,src);
+               break;
+       case 0x3:       /* NEG Eb */
+               set_skipflags(false);gen_sop_word(SOP_NEG,decode.big_op,src);
+               break;
+       case 0x4:       /* mul Eb */
+               gen_needflags();gen_mul_word(false,DREG(EAX),DREG(EDX),decode.big_op,src);
+               goto skipsave;
+       case 0x5:       /* imul Eb */
+               gen_needflags();gen_mul_word(true,DREG(EAX),DREG(EDX),decode.big_op,src);
+               goto skipsave;
+       case 0x6:       /* div Eb */
+       case 0x7:       /* idiv Eb */
+               /* EAX could be used, so precache it */
+               if (decode.modrm.mod==3)
+                       gen_dop_word(DOP_MOV,decode.big_op,DREG(TMPW),&DynRegs[decode.modrm.rm]);
+               gen_releasereg(DREG(EAX));gen_releasereg(DREG(EDX));
+               void * func=(decode.modrm.reg==6) ?
+                       (decode.big_op ? (void *)&dyn_helper_divd : (void *)&dyn_helper_divw) :
+                       (decode.big_op ? (void *)&dyn_helper_idivd : (void *)&dyn_helper_idivw);
+               gen_call_function(func,"%Rd%Dd",DREG(TMPB),DREG(TMPW));
+               dyn_check_bool_exception(DREG(TMPB));
+               gen_releasereg(DREG(TMPB));
+               goto skipsave;
+       }
+       /* Save the result if memory op */
+       if (decode.modrm.mod<3) dyn_write_word_release(DREG(EA),src,decode.big_op);
+skipsave:
+       gen_releasereg(DREG(TMPW));gen_releasereg(DREG(EA));
+}
+
+static void dyn_mov_ev_seg(void) {
+       dyn_get_modrm();
+       gen_load_host(&Segs.val[decode.modrm.reg],DREG(TMPW),2);
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_write_word_release(DREG(EA),DREG(TMPW),false);
+       } else {
+               gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW));
+       }
+       gen_releasereg(DREG(TMPW));
+}
+
+static void dyn_load_seg(SegNames seg,DynReg * src) {
+       gen_call_function((void *)&CPU_SetSegGeneral,"%Rd%Id%Drw",DREG(TMPB),seg,src);
+       dyn_check_bool_exception(DREG(TMPB));
+       gen_releasereg(DREG(TMPB));
+       gen_releasereg(&DynRegs[G_ES+seg]);
+}
+
+static void dyn_load_seg_off_ea(SegNames seg) {
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               gen_lea(DREG(TMPB),DREG(EA),0,0,decode.big_op ? 4:2);
+               dyn_read_word(DREG(TMPB),DREG(TMPB),false);
+               dyn_read_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+               dyn_load_seg(seg,DREG(TMPB));gen_releasereg(DREG(TMPB));
+               gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(TMPW));
+       } else {
+               IllegalOption("dyn_load_seg_off_ea");
+       }
+}
+
+static void dyn_mov_seg_ev(void) {
+       dyn_get_modrm();
+       SegNames seg=(SegNames)decode.modrm.reg;
+       if (GCC_UNLIKELY(seg==cs)) IllegalOption("dyn_mov_seg_ev");
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+               dyn_read_word(DREG(EA),DREG(EA),false);
+               dyn_load_seg(seg,DREG(EA));
+               gen_releasereg(DREG(EA));
+       } else {
+               dyn_load_seg(seg,&DynRegs[decode.modrm.rm]);
+       }
+}
+
+static void dyn_push_seg(SegNames seg) {
+       gen_load_host(&Segs.val[seg],DREG(TMPW),2);
+       dyn_push(DREG(TMPW));
+       gen_releasereg(DREG(TMPW));
+}
+
+static void dyn_pop_seg(SegNames seg) {
+       gen_releasereg(DREG(ESP));
+       gen_call_function((void *)&CPU_PopSeg,"%Rd%Id%Id",DREG(TMPB),seg,decode.big_op);
+       dyn_check_bool_exception(DREG(TMPB));
+       gen_releasereg(DREG(TMPB));
+       gen_releasereg(&DynRegs[G_ES+seg]);
+       gen_releasereg(DREG(ESP));
+}
+
+static void dyn_pop_ev(void) {
+       dyn_pop(DREG(TMPW));
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea();
+//             dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+               if (decode.big_op) gen_call_function((void *)&mem_writed_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
+               else gen_call_function((void *)&mem_writew_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
+       } else {
+               gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW));
+       }
+       gen_releasereg(DREG(TMPW));
+}
+
+static void dyn_enter(void) {
+       gen_releasereg(DREG(ESP));
+       gen_releasereg(DREG(EBP));
+       Bitu bytes=decode_fetchw();
+       Bitu level=decode_fetchb();
+       gen_call_function((void *)&CPU_ENTER,"%Id%Id%Id",decode.big_op,bytes,level);
+}
+
+static void dyn_leave(void) {
+       gen_protectflags();
+       gen_dop_word_var(DOP_MOV,true,DREG(TMPW),&cpu.stack.mask);
+       gen_sop_word(SOP_NOT,true,DREG(TMPW));
+       gen_dop_word(DOP_AND,true,DREG(ESP),DREG(TMPW));
+       gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EBP));
+       gen_dop_word_var(DOP_AND,true,DREG(TMPW),&cpu.stack.mask);
+       gen_dop_word(DOP_OR,true,DREG(ESP),DREG(TMPW));
+       dyn_pop(DREG(EBP),false);
+       gen_releasereg(DREG(TMPW));
+}
+
+static void dyn_segprefix(SegNames seg) {
+//     if (GCC_UNLIKELY((Bitu)(decode.segprefix))) IllegalOption("dyn_segprefix");
+       decode.segprefix=&DynRegs[G_ES+seg];
+}
+
+static void dyn_closeblock(void) {
+       //Shouldn't create empty block normally but let's do it like this
+       gen_protectflags();
+       dyn_fill_blocks();
+       cache_closeblock();
+}
+
+static void dyn_normal_exit(BlockReturn code) {
+       gen_protectflags();
+       dyn_reduce_cycles();
+       dyn_set_eip_last();
+       dyn_save_critical_regs();
+       gen_return(code);
+       dyn_closeblock();
+}
+
+static void dyn_exit_link(Bits eip_change) {
+       gen_protectflags();
+       gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),(decode.code-decode.code_start)+eip_change);
+       dyn_reduce_cycles();
+       dyn_save_critical_regs();
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
+       dyn_closeblock();
+}
+
+static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) {
+       Bitu eip_base=decode.code-decode.code_start;
+       gen_needflags();
+       gen_protectflags();
+       dyn_save_noncritical_regs();
+       gen_releasereg(DREG(FLAGS));
+       gen_releasereg(DREG(EIP));
+
+       gen_preloadreg(DREG(CYCLES));
+       gen_preloadreg(DREG(EIP));
+       DynReg save_cycles,save_eip;
+       dyn_saveregister(DREG(CYCLES),&save_cycles);
+       dyn_saveregister(DREG(EIP),&save_eip);
+       Bit8u * data=gen_create_branch(btype);
+
+       /* Branch not taken */
+       dyn_reduce_cycles();
+       gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base);
+       gen_releasereg(DREG(CYCLES));
+       gen_releasereg(DREG(EIP));
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
+       gen_fill_branch(data);
+
+       /* Branch taken */
+       dyn_restoreregister(&save_cycles,DREG(CYCLES));
+       dyn_restoreregister(&save_eip,DREG(EIP));
+       dyn_reduce_cycles();
+       gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(EIP),eip_base+eip_add);
+       gen_releasereg(DREG(CYCLES));
+       gen_releasereg(DREG(EIP));
+       gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start));
+       dyn_closeblock();
+}
+
+enum LoopTypes {
+       LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ
+};
+
+static void dyn_loop(LoopTypes type) {
+       dyn_reduce_cycles();
+       Bits eip_add=(Bit8s)decode_fetchb();
+       Bitu eip_base=decode.code-decode.code_start;
+       Bit8u * branch1=0;Bit8u * branch2=0;
+       dyn_save_critical_regs();
+       switch (type) {
+       case LOOP_E:
+               gen_needflags();
+               branch1=gen_create_branch(BR_NZ);
+               break;
+       case LOOP_NE:
+               gen_needflags();
+               branch1=gen_create_branch(BR_Z);
+               break;
+       }
+       gen_protectflags();
+       switch (type) {
+       case LOOP_E:
+       case LOOP_NE:
+       case LOOP_NONE:
+               gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX));
+               gen_releasereg(DREG(ECX));
+               branch2=gen_create_branch(BR_Z);
+               break;
+       case LOOP_JCXZ:
+               gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
+               gen_releasereg(DREG(ECX));
+               branch2=gen_create_branch(BR_NZ);
+               break;
+       }
+       gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base+eip_add);
+       gen_releasereg(DREG(EIP));
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
+       if (branch1) {
+               gen_fill_branch(branch1);
+               gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX));
+               gen_releasereg(DREG(ECX));
+       }
+       /* Branch taken */
+       gen_fill_branch(branch2);
+       gen_lea(DREG(EIP),DREG(EIP),0,0,eip_base);
+       gen_releasereg(DREG(EIP));
+       gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlock,cache.start));
+       dyn_closeblock();
+}
+
+static void dyn_ret_near(Bitu bytes) {
+       gen_protectflags();
+       dyn_reduce_cycles();
+       dyn_pop(DREG(EIP));
+       if (bytes) gen_dop_word_imm(DOP_ADD,true,DREG(ESP),bytes);
+       dyn_save_critical_regs();
+       gen_return(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_call_near_imm(void) {
+       Bits imm;
+       if (decode.big_op) imm=(Bit32s)decode_fetchd();
+       else imm=(Bit16s)decode_fetchw();
+       dyn_set_eip_end(DREG(TMPW));
+       dyn_push(DREG(TMPW));
+       gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(TMPW),imm);
+       if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(EIP),DREG(TMPW));
+       else gen_extend_word(false,DREG(EIP),DREG(TMPW));
+       dyn_reduce_cycles();
+       dyn_save_critical_regs();
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
+       dyn_closeblock();
+}
+
+static void dyn_ret_far(Bitu bytes) {
+       gen_protectflags();
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(DREG(TMPW));
+       dyn_flags_gen_to_host();
+       dyn_save_critical_regs();
+       gen_call_function((void*)&CPU_RET,"%Id%Id%Drd",decode.big_op,bytes,DREG(TMPW));
+       gen_return_fast(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_call_far_imm(void) {
+       Bitu sel,off;
+       off=decode.big_op ? decode_fetchd() : decode_fetchw();
+       sel=decode_fetchw();
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(DREG(TMPW));
+       dyn_flags_gen_to_host();
+       dyn_save_critical_regs();
+       gen_call_function((void*)&CPU_CALL,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW));
+       gen_return_fast(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_jmp_far_imm(void) {
+       Bitu sel,off;
+       gen_protectflags();
+       off=decode.big_op ? decode_fetchd() : decode_fetchw();
+       sel=decode_fetchw();
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(DREG(TMPW));
+       dyn_flags_gen_to_host();
+       dyn_save_critical_regs();
+       gen_call_function((void*)&CPU_JMP,"%Id%Id%Id%Drd",decode.big_op,sel,off,DREG(TMPW));
+       gen_return_fast(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_iret(void) {
+       gen_protectflags();
+       dyn_flags_gen_to_host();
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(DREG(TMPW));
+       dyn_save_critical_regs();
+       gen_call_function((void*)&CPU_IRET,"%Id%Drd",decode.big_op,DREG(TMPW));
+       gen_return_fast(BR_Iret);
+       dyn_closeblock();
+}
+
+static void dyn_interrupt(Bitu num) {
+       gen_protectflags();
+       dyn_flags_gen_to_host();
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(DREG(TMPW));
+       dyn_save_critical_regs();
+       gen_call_function((void*)&CPU_Interrupt,"%Id%Id%Drd",num,CPU_INT_SOFTWARE,DREG(TMPW));
+       gen_return_fast(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_add_iocheck(Bitu access_size) {
+       gen_call_function((void *)&CPU_IO_Exception,"%Dw%Id",DREG(EDX),access_size);
+       dyn_check_bool_exception_al();
+}
+
+static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) {
+       gen_call_function((void *)&CPU_IO_Exception,"%Id%Id",accessed_port,access_size);
+       dyn_check_bool_exception_al();
+}
+
+#ifdef X86_DYNFPU_DH_ENABLED
+#include "dyn_fpu_dh.h"
+#define dh_fpu_startup() {             \
+       fpu_used=true;                          \
+       gen_protectflags();                     \
+       gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4);     \
+       gen_dop_word_imm(DOP_CMP,true,DREG(TMPB),0);            \
+       gen_releasereg(DREG(TMPB));                                                     \
+       save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z);              \
+       dyn_savestate(&save_info[used_save_info].state);        \
+       save_info[used_save_info].return_pos=cache.pos;         \
+       save_info[used_save_info].type=fpu_restore;                     \
+       used_save_info++;                                                                       \
+}
+#endif
+#include "dyn_fpu.h"
+
+static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bitu max_opcodes) {
+       Bits i;
+/* Init a load of variables */
+       decode.code_start=start;
+       decode.code=start;
+       Bitu cycles=0;
+       decode.page.code=codepage;
+       decode.page.index=start&4095;
+       decode.page.wmap=codepage->write_map;
+       decode.page.invmap=codepage->invalidation_map;
+       decode.page.first=start >> 12;
+       decode.active_block=decode.block=cache_openblock();
+       decode.block->page.start=decode.page.index;
+       codepage->AddCacheBlock(decode.block);
+
+       gen_save_host_direct(&cache.block.running,(Bit32u)decode.block);
+       for (i=0;i<G_MAX;i++) {
+               DynRegs[i].flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED);
+               DynRegs[i].genreg=0;
+       }
+       gen_reinit();
+       /* Start with the cycles check */
+       gen_protectflags();
+       gen_dop_word_imm(DOP_CMP,true,DREG(CYCLES),0);
+       save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE);
+       save_info[used_save_info].type=cycle_check;
+       used_save_info++;
+       gen_releasereg(DREG(CYCLES));
+       decode.cycles=0;
+#ifdef X86_DYNFPU_DH_ENABLED
+       bool fpu_used=false;
+#endif
+       while (max_opcodes--) {
+/* Init prefixes */
+               decode.big_addr=cpu.code.big;
+               decode.big_op=cpu.code.big;
+               decode.segprefix=0;
+               decode.rep=REP_NONE;
+               decode.cycles++;
+               decode.op_start=decode.code;
+restart_prefix:
+               Bitu opcode;
+               if (!decode.page.invmap) opcode=decode_fetchb();
+               else {
+                       if (decode.page.index<4096) {
+                               if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode;
+                               opcode=decode_fetchb();
+                       } else {
+                               opcode=decode_fetchb();
+                               if (GCC_UNLIKELY(decode.page.invmap && 
+                                       (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode;
+                       }
+               }
+               switch (opcode) {
+
+               case 0x00:dyn_dop_ebgb(DOP_ADD);break;
+               case 0x01:dyn_dop_evgv(DOP_ADD);break;
+               case 0x02:dyn_dop_gbeb(DOP_ADD);break;
+               case 0x03:dyn_dop_gvev(DOP_ADD);break;
+               case 0x04:gen_discardflags();gen_dop_byte_imm(DOP_ADD,DREG(EAX),0,decode_fetchb());break;
+               case 0x05:gen_discardflags();dyn_dop_word_imm(DOP_ADD,decode.big_op,DREG(EAX));break;
+               case 0x06:dyn_push_seg(es);break;
+               case 0x07:dyn_pop_seg(es);break;
+
+               case 0x08:dyn_dop_ebgb(DOP_OR);break;
+               case 0x09:dyn_dop_evgv(DOP_OR);break;
+               case 0x0a:dyn_dop_gbeb(DOP_OR);break;
+               case 0x0b:dyn_dop_gvev(DOP_OR);break;
+               case 0x0c:gen_discardflags();gen_dop_byte_imm(DOP_OR,DREG(EAX),0,decode_fetchb());break;
+               case 0x0d:gen_discardflags();gen_dop_word_imm(DOP_OR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x0e:dyn_push_seg(cs);break;
+               case 0x0f:
+               {
+                       Bitu dual_code=decode_fetchb();
+                       switch (dual_code) {
+                       /* Short conditional jumps */
+                       case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87:        
+                       case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f:        
+                               dyn_branched_exit((BranchTypes)(dual_code&0xf),
+                                       decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());     
+                               goto finish_block;
+                       /* PUSH/POP FS */
+                       case 0xa0:dyn_push_seg(fs);break;
+                       case 0xa1:dyn_pop_seg(fs);break;
+                       /* SHLD Imm/cl*/
+                       case 0xa4:dyn_dshift_ev_gv(true,true);break;
+                       case 0xa5:dyn_dshift_ev_gv(true,false);break;
+                       /* PUSH/POP GS */
+                       case 0xa8:dyn_push_seg(gs);break;
+                       case 0xa9:dyn_pop_seg(gs);break;
+                       /* SHRD Imm/cl*/
+                       case 0xac:dyn_dshift_ev_gv(false,true);break;
+                       case 0xad:dyn_dshift_ev_gv(false,false);break;          
+                       /* Imul Ev,Gv */
+                       case 0xaf:dyn_imul_gvev(0);break;
+                       /* CMPXCHG */
+                       case 0xb1:dyn_cmpxchg_evgv();break;
+                       /* LFS,LGS */
+                       case 0xb4:
+                               dyn_get_modrm();
+                               if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                               dyn_load_seg_off_ea(fs);
+                               break;
+                       case 0xb5:
+                               dyn_get_modrm();
+                               if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                               dyn_load_seg_off_ea(gs);
+                               break;
+                       /* MOVZX Gv,Eb/Ew */
+                       case 0xb6:dyn_mov_ev_gb(false);break;
+                       case 0xb7:dyn_mov_ev_gw(false);break;
+                       /* MOVSX Gv,Eb/Ew */
+                       case 0xbe:dyn_mov_ev_gb(true);break;
+                       case 0xbf:dyn_mov_ev_gw(true);break;
+
+                       default:
+#if DYN_LOG
+                               LOG_MSG("Unhandled dual opcode 0F%02X",dual_code);
+#endif
+                               goto illegalopcode;
+                       }
+               }break;
+
+               case 0x10:dyn_dop_ebgb(DOP_ADC);break;
+               case 0x11:dyn_dop_evgv(DOP_ADC);break;
+               case 0x12:dyn_dop_gbeb(DOP_ADC);break;
+               case 0x13:dyn_dop_gvev(DOP_ADC);break;
+               case 0x14:gen_needcarry();gen_dop_byte_imm(DOP_ADC,DREG(EAX),0,decode_fetchb());break;
+               case 0x15:gen_needcarry();gen_dop_word_imm(DOP_ADC,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x16:dyn_push_seg(ss);break;
+               case 0x17:dyn_pop_seg(ss);break;
+
+               case 0x18:dyn_dop_ebgb(DOP_SBB);break;
+               case 0x19:dyn_dop_evgv(DOP_SBB);break;
+               case 0x1a:dyn_dop_gbeb(DOP_SBB);break;
+               case 0x1b:dyn_dop_gvev(DOP_SBB);break;
+               case 0x1c:gen_needcarry();gen_dop_byte_imm(DOP_SBB,DREG(EAX),0,decode_fetchb());break;
+               case 0x1d:gen_needcarry();gen_dop_word_imm(DOP_SBB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x1e:dyn_push_seg(ds);break;
+               case 0x1f:dyn_pop_seg(ds);break;
+               case 0x20:dyn_dop_ebgb(DOP_AND);break;
+               case 0x21:dyn_dop_evgv(DOP_AND);break;
+               case 0x22:dyn_dop_gbeb(DOP_AND);break;
+               case 0x23:dyn_dop_gvev(DOP_AND);break;
+               case 0x24:gen_discardflags();gen_dop_byte_imm(DOP_AND,DREG(EAX),0,decode_fetchb());break;
+               case 0x25:gen_discardflags();dyn_dop_word_imm(DOP_AND,decode.big_op,DREG(EAX));break;
+               case 0x26:dyn_segprefix(es);goto restart_prefix;
+
+               case 0x28:dyn_dop_ebgb(DOP_SUB);break;
+               case 0x29:dyn_dop_evgv(DOP_SUB);break;
+               case 0x2a:dyn_dop_gbeb(DOP_SUB);break;
+               case 0x2b:dyn_dop_gvev(DOP_SUB);break;
+               case 0x2c:gen_discardflags();gen_dop_byte_imm(DOP_SUB,DREG(EAX),0,decode_fetchb());break;
+               case 0x2d:gen_discardflags();gen_dop_word_imm(DOP_SUB,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x2e:dyn_segprefix(cs);goto restart_prefix;
+
+               case 0x30:dyn_dop_ebgb(DOP_XOR);break;
+               case 0x31:dyn_dop_evgv(DOP_XOR);break;
+               case 0x32:dyn_dop_gbeb(DOP_XOR);break;
+               case 0x33:dyn_dop_gvev(DOP_XOR);break;
+               case 0x34:gen_discardflags();gen_dop_byte_imm(DOP_XOR,DREG(EAX),0,decode_fetchb());break;
+               case 0x35:gen_discardflags();gen_dop_word_imm(DOP_XOR,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x36:dyn_segprefix(ss);goto restart_prefix;
+
+               case 0x38:dyn_dop_ebgb(DOP_CMP);break;
+               case 0x39:dyn_dop_evgv(DOP_CMP);break;
+               case 0x3a:dyn_dop_gbeb(DOP_CMP);break;
+               case 0x3b:dyn_dop_gvev(DOP_CMP);break;
+               case 0x3c:gen_discardflags();gen_dop_byte_imm(DOP_CMP,DREG(EAX),0,decode_fetchb());break;
+               case 0x3d:gen_discardflags();gen_dop_word_imm(DOP_CMP,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x3e:dyn_segprefix(ds);goto restart_prefix;
+
+               /* INC/DEC general register */
+               case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47:        
+                       gen_needcarry();gen_sop_word(SOP_INC,decode.big_op,&DynRegs[opcode&7]);
+                       break;
+               case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f:        
+                       gen_needcarry();gen_sop_word(SOP_DEC,decode.big_op,&DynRegs[opcode&7]);
+                       break;
+               /* PUSH/POP General register */
+               case 0x50:case 0x51:case 0x52:case 0x53:case 0x55:case 0x56:case 0x57:  
+                       dyn_push(&DynRegs[opcode&7]);
+                       break;
+               case 0x54:              /* PUSH SP is special */
+                       gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP));
+                       dyn_push(DREG(TMPW));
+                       gen_releasereg(DREG(TMPW));
+                       break;
+               case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f:        
+                       dyn_pop(&DynRegs[opcode&7]);
+                       break;
+               case 0x60:              /* PUSHA */
+                       gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(ESP));
+                       for (i=G_EAX;i<=G_EDI;i++) {
+                               dyn_push_unchecked((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW));
+                       }
+                       gen_releasereg(DREG(TMPW));
+                       break;
+               case 0x61:              /* POPA */
+                       for (i=G_EDI;i>=G_EAX;i--) {
+                               dyn_pop((i!=G_ESP) ? &DynRegs[i] : DREG(TMPW),false);
+                       }
+                       gen_releasereg(DREG(TMPW));
+                       break;
+               //segprefix FS,GS
+               case 0x64:dyn_segprefix(fs);goto restart_prefix;
+               case 0x65:dyn_segprefix(gs);goto restart_prefix;
+               //Push immediates
+               //Operand size          
+               case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix;
+               //Address size          
+               case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix;
+               case 0x68:              /* PUSH Iv */
+                       gen_dop_word_imm(DOP_MOV,decode.big_op,DREG(TMPW),decode.big_op ? decode_fetchd() : decode_fetchw());
+                       dyn_push(DREG(TMPW));
+                       gen_releasereg(DREG(TMPW));
+                       break;
+               /* Imul Ivx */
+               case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break;
+               case 0x6a:              /* PUSH Ibx */
+                       gen_dop_word_imm(DOP_MOV,true,DREG(TMPW),(Bit8s)decode_fetchb());
+                       dyn_push(DREG(TMPW));
+                       gen_releasereg(DREG(TMPW));
+                       break;
+               /* Imul Ibx */
+               case 0x6b:dyn_imul_gvev(1);break;
+               /* Short conditional jumps */
+               case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77:        
+               case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f:        
+                       dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb());    
+                       goto finish_block;
+               /* Group 1 */
+               case 0x80:dyn_grp1_eb_ib();break;
+               case 0x81:dyn_grp1_ev_ivx(false);break;
+               case 0x82:dyn_grp1_eb_ib();break;
+               case 0x83:dyn_grp1_ev_ivx(true);break;
+               /* TEST Gb,Eb Gv,Ev */
+               case 0x84:dyn_dop_gbeb(DOP_TEST);break;
+               case 0x85:dyn_dop_gvev(DOP_TEST);break;
+               /* XCHG Eb,Gb Ev,Gv */
+               case 0x86:dyn_dop_ebgb(DOP_XCHG);break;
+               case 0x87:dyn_dop_evgv(DOP_XCHG);break;
+               /* MOV e,g and g,e */
+               case 0x88:dyn_mov_ebgb();break;
+               case 0x89:dyn_mov_evgv();break;
+               case 0x8a:dyn_mov_gbeb();break;
+               case 0x8b:dyn_mov_gvev();break;
+               /* MOV ev,seg */
+               case 0x8c:dyn_mov_ev_seg();break;
+               /* LEA Gv */
+               case 0x8d:
+                       dyn_get_modrm();
+                       if (decode.big_op) {
+                               dyn_fill_ea(false,&DynRegs[decode.modrm.reg]);
+                       } else {
+                               dyn_fill_ea(false);
+                               gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.reg],DREG(EA));
+                               gen_releasereg(DREG(EA));
+                       }
+                       break;
+               /* Mov seg,ev */
+               case 0x8e:dyn_mov_seg_ev();break;
+               /* POP Ev */
+               case 0x8f:dyn_pop_ev();break;
+               case 0x90:      //NOP
+               case 0x9b:      //WAIT/FWAIT
+                       break;
+               //XCHG ax,reg
+               case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:  
+                       gen_dop_word(DOP_XCHG,decode.big_op,DREG(EAX),&DynRegs[opcode&07]);
+                       break;
+               /* CBW/CWDE */
+               case 0x98:
+                       gen_cbw(decode.big_op,DREG(EAX));
+                       break;
+               /* CWD/CDQ */
+               case 0x99:
+                       gen_cwd(decode.big_op,DREG(EAX),DREG(EDX));
+                       break;
+               /* CALL FAR Ip */
+               case 0x9a:dyn_call_far_imm();goto finish_block;
+               case 0x9c:              //PUSHF
+                       gen_protectflags();
+                       gen_releasereg(DREG(ESP));
+                       dyn_flags_gen_to_host();
+                       gen_call_function((void *)&CPU_PUSHF,"%Rd%Id",DREG(TMPB),decode.big_op);
+                       dyn_check_bool_exception(DREG(TMPB));
+                       gen_releasereg(DREG(TMPB));
+                       break;
+               case 0x9d:              //POPF
+                       gen_releasereg(DREG(ESP));
+                       gen_releasereg(DREG(FLAGS));
+                       gen_call_function((void *)&CPU_POPF,"%Rd%Id",DREG(TMPB),decode.big_op);
+                       dyn_check_bool_exception(DREG(TMPB));
+                       dyn_flags_host_to_gen();
+                       gen_releasereg(DREG(TMPB));
+                       dyn_check_irqrequest();
+                       break;
+               /* MOV AL,direct addresses */
+               case 0xa0:
+                       gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,
+                               decode.big_addr ? decode_fetchd() : decode_fetchw());
+                       dyn_read_byte_release(DREG(EA),DREG(EAX),false);
+                       break;
+               /* MOV AX,direct addresses */
+               case 0xa1:
+                       gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,
+                               decode.big_addr ? decode_fetchd() : decode_fetchw());
+                       dyn_read_word_release(DREG(EA),DREG(EAX),decode.big_op);
+                       break;
+               /* MOV direct address,AL */
+               case 0xa2:
+                       if (decode.big_addr) {
+                               Bitu val;
+                               if (decode_fetchd_imm(val)) {
+                                       gen_lea_imm_mem(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),(void*)val);
+                               } else {
+                                       gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,(Bits)val);
+                               }
+                               dyn_write_byte_release(DREG(EA),DREG(EAX),false);
+                       } else {
+                               gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,decode_fetchw());
+                               dyn_write_byte_release(DREG(EA),DREG(EAX),false);
+                       }
+                       break;
+               /* MOV direct addresses,AX */
+               case 0xa3:
+                       gen_lea(DREG(EA),decode.segprefix ? decode.segprefix : DREG(DS),0,0,
+                               decode.big_addr ? decode_fetchd() : decode_fetchw());
+                       dyn_write_word_release(DREG(EA),DREG(EAX),decode.big_op);
+                       break;
+               /* MOVSB/W/D*/
+               case 0xa4:dyn_string(STR_MOVSB);break;
+               case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break;
+               /* TEST AL,AX Imm */
+               case 0xa8:gen_discardflags();gen_dop_byte_imm(DOP_TEST,DREG(EAX),0,decode_fetchb());break;
+               case 0xa9:gen_discardflags();gen_dop_word_imm(DOP_TEST,decode.big_op,DREG(EAX),decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               /* STOSB/W/D*/
+               case 0xaa:dyn_string(STR_STOSB);break;
+               case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break;
+               /* LODSB/W/D*/
+               case 0xac:dyn_string(STR_LODSB);break;
+               case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break;
+               //Mov Byte reg,Imm byte
+               case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7:        
+                       gen_dop_byte_imm(DOP_MOV,&DynRegs[opcode&3],opcode&4,decode_fetchb());
+                       break;
+               //Mov word reg imm byte,word,
+               case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf:        
+                       if (decode.big_op) {
+                               dyn_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7]);break;
+                       } else {
+                               gen_dop_word_imm(DOP_MOV,decode.big_op,&DynRegs[opcode&7],decode_fetchw());break;
+                       }
+                       break;
+               //GRP2 Eb/Ev,Ib
+               case 0xc0:dyn_grp2_eb(grp2_imm);break;
+               case 0xc1:dyn_grp2_ev(grp2_imm);break;
+               //RET near Iw / Ret
+               case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block;
+               case 0xc3:dyn_ret_near(0);goto finish_block;
+               //LES
+               case 0xc4:
+                       dyn_get_modrm();
+                       if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                       dyn_load_seg_off_ea(es);
+                       break;
+               //LDS
+               case 0xc5:
+                       dyn_get_modrm();
+                       if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                       dyn_load_seg_off_ea(ds);
+                       break;
+               // MOV Eb/Ev,Ib/Iv
+               case 0xc6:dyn_mov_ebib();break;
+               case 0xc7:dyn_mov_eviv();break;
+               //ENTER and LEAVE
+               case 0xc8:dyn_enter();break;
+               case 0xc9:dyn_leave();break;
+               //RET far Iw / Ret
+               case 0xca:dyn_ret_far(decode_fetchw());goto finish_block;
+               case 0xcb:dyn_ret_far(0);goto finish_block;
+               /* Interrupt */
+//             case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block;
+               /* IRET */
+               case 0xcf:dyn_iret();goto finish_block;
+
+               //GRP2 Eb/Ev,1
+               case 0xd0:dyn_grp2_eb(grp2_1);break;
+               case 0xd1:dyn_grp2_ev(grp2_1);break;
+               //GRP2 Eb/Ev,CL
+               case 0xd2:dyn_grp2_eb(grp2_cl);break;
+               case 0xd3:dyn_grp2_ev(grp2_cl);break;
+               //FPU
+#ifdef CPU_FPU
+               case 0xd8:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc0();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc0();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc0();
+                       break;
+               case 0xd9:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc1();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc1();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc1();
+                       break;
+               case 0xda:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc2();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc2();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc2();
+                       break;
+               case 0xdb:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc3();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc3();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc3();
+                       break;
+               case 0xdc:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc4();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc4();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc4();
+                       break;
+               case 0xdd:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc5();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc5();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc5();
+                       break;
+               case 0xde:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc6();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc6();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc6();
+                       break;
+               case 0xdf:
+#ifdef X86_DYNFPU_DH_ENABLED
+                       if (dyn_dh_fpu.dh_fpu_enabled) {
+                               if (fpu_used) dh_fpu_esc7();
+                               else {
+                                       dh_fpu_startup();
+                                       dh_fpu_esc7();
+                               }
+                       } else
+#endif
+                       dyn_fpu_esc7();
+                       break;
+#endif
+               //Loops 
+               case 0xe2:dyn_loop(LOOP_NONE);goto finish_block;
+               case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block;
+               //IN AL/AX,imm
+               case 0xe4: {
+                       Bitu port=decode_fetchb();
+                       dyn_add_iocheck_var(port,1);
+                       gen_call_function((void*)&IO_ReadB,"%Id%Rl",port,DREG(EAX));
+                       } break;
+               case 0xe5: {
+                       Bitu port=decode_fetchb();
+                       dyn_add_iocheck_var(port,decode.big_op?4:2);
+                       if (decode.big_op) {
+                gen_call_function((void*)&IO_ReadD,"%Id%Rd",port,DREG(EAX));
+                       } else {
+                               gen_call_function((void*)&IO_ReadW,"%Id%Rw",port,DREG(EAX));
+                       }
+                       } break;
+               //OUT imm,AL
+               case 0xe6: {
+                       Bitu port=decode_fetchb();
+                       dyn_add_iocheck_var(port,1);
+                       gen_call_function((void*)&IO_WriteB,"%Id%Dl",port,DREG(EAX));
+                       } break;
+               case 0xe7: {
+                       Bitu port=decode_fetchb();
+                       dyn_add_iocheck_var(port,decode.big_op?4:2);
+                       if (decode.big_op) {
+                gen_call_function((void*)&IO_WriteD,"%Id%Dd",port,DREG(EAX));
+                       } else {
+                               gen_call_function((void*)&IO_WriteW,"%Id%Dw",port,DREG(EAX));
+                       }
+                       } break;
+               case 0xe8:              /* CALL Ivx */
+                       dyn_call_near_imm();
+                       goto finish_block;
+               case 0xe9:              /* Jmp Ivx */
+                       dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
+                       goto finish_block;
+               case 0xea:              /* JMP FAR Ip */
+                       dyn_jmp_far_imm();
+                       goto finish_block;
+                       /* Jmp Ibx */
+               case 0xeb:dyn_exit_link((Bit8s)decode_fetchb());goto finish_block;
+               /* IN AL/AX,DX*/
+               case 0xec:
+                       dyn_add_iocheck(1);
+                       gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),DREG(EAX));
+                       break;
+               case 0xed:
+                       dyn_add_iocheck(decode.big_op?4:2);
+                       if (decode.big_op) {
+                gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),DREG(EAX));
+                       } else {
+                               gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),DREG(EAX));
+                       }
+                       break;
+               /* OUT DX,AL/AX */
+               case 0xee:
+                       dyn_add_iocheck(1);
+                       gen_call_function((void*)&IO_WriteB,"%Dw%Dl",DREG(EDX),DREG(EAX));
+                       break;
+               case 0xef:
+                       dyn_add_iocheck(decode.big_op?4:2);
+                       if (decode.big_op) {
+                gen_call_function((void*)&IO_WriteD,"%Dw%Dd",DREG(EDX),DREG(EAX));
+                       } else {
+                               gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),DREG(EAX));
+                       }
+                       break;
+               case 0xf0:              //LOCK
+                       break;
+               case 0xf2:              //REPNE/NZ
+                       decode.rep=REP_NZ;
+                       goto restart_prefix;
+               case 0xf3:              //REPE/Z
+                       decode.rep=REP_Z;
+                       goto restart_prefix;
+               /* Change carry flag */
+               case 0xf5:              //CMC
+               case 0xf8:              //CLC
+               case 0xf9:              //STC
+                       gen_needflags();
+                       cache_addb(opcode);break;
+               /* GRP 3 Eb/EV */
+               case 0xf6:dyn_grp3_eb();break;
+               case 0xf7:dyn_grp3_ev();break;
+               /* Change interrupt flag */
+               case 0xfa:              //CLI
+                       gen_releasereg(DREG(FLAGS));
+                       gen_call_function((void *)&CPU_CLI,"%Rd",DREG(TMPB));
+                       dyn_check_bool_exception(DREG(TMPB));
+                       gen_releasereg(DREG(TMPB));
+                       break;
+               case 0xfb:              //STI
+                       gen_releasereg(DREG(FLAGS));
+                       gen_call_function((void *)&CPU_STI,"%Rd",DREG(TMPB));
+                       dyn_check_bool_exception(DREG(TMPB));
+                       gen_releasereg(DREG(TMPB));
+                       dyn_check_irqrequest();
+                       if (max_opcodes<=0) max_opcodes=1;              //Allow 1 extra opcode
+                       break;
+               case 0xfc:              //CLD
+                       gen_protectflags();
+                       gen_dop_word_imm(DOP_AND,true,DREG(FLAGS),~FLAG_DF);
+                       gen_save_host_direct(&cpu.direction,1);
+                       break;
+               case 0xfd:              //STD
+                       gen_protectflags();
+                       gen_dop_word_imm(DOP_OR,true,DREG(FLAGS),FLAG_DF);
+                       gen_save_host_direct(&cpu.direction,-1);
+                       break;
+               /* GRP 4 Eb and callback's */
+               case 0xfe:
+            dyn_get_modrm();
+                       switch (decode.modrm.reg) {
+                       case 0x0://INC Eb
+                       case 0x1://DEC Eb
+                               if (decode.modrm.mod<3) {
+                                       dyn_fill_ea();dyn_read_byte(DREG(EA),DREG(TMPB),false);
+                                       gen_needcarry();
+                                       gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,DREG(TMPB),0);
+                                       dyn_write_byte_release(DREG(EA),DREG(TMPB),false);
+                                       gen_releasereg(DREG(TMPB));
+                               } else {
+                                       gen_needcarry();
+                                       gen_sop_byte(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,
+                                               &DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
+                               }
+                               break;
+                       case 0x7:               //CALBACK Iw
+                               gen_save_host_direct(&core_dyn.callback,decode_fetchw());
+                               dyn_set_eip_end();
+                               dyn_reduce_cycles();
+                               dyn_save_critical_regs();
+                               gen_return(BR_CallBack);
+                               dyn_closeblock();
+                               goto finish_block;
+                       }
+                       break;
+
+               case 0xff: 
+                       {
+            dyn_get_modrm();DynReg * src;
+                       if (decode.modrm.mod<3) {
+                               dyn_fill_ea();
+                               dyn_read_word(DREG(EA),DREG(TMPW),decode.big_op);
+                               src=DREG(TMPW);
+                       } else src=&DynRegs[decode.modrm.rm];
+                       switch (decode.modrm.reg) {
+                       case 0x0://INC Ev
+                       case 0x1://DEC Ev
+                               gen_needcarry();
+                               gen_sop_word(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op,src);
+                               if (decode.modrm.mod<3){
+                                       dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
+                                       gen_releasereg(DREG(TMPW));
+                               }
+                               break;
+                       case 0x2:       /* CALL Ev */
+                               gen_lea(DREG(TMPB),DREG(EIP),0,0,decode.code-decode.code_start);
+                               dyn_push(DREG(TMPB));
+                               gen_releasereg(DREG(TMPB));
+                               gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src);
+                               goto core_close_block;
+                       case 0x4:       /* JMP Ev */
+                               gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),src);
+                               goto core_close_block;
+                       case 0x3:       /* CALL Ep */
+                       case 0x5:       /* JMP Ep */
+                               gen_protectflags();
+                               dyn_flags_gen_to_host();
+                               gen_lea(DREG(EA),DREG(EA),0,0,decode.big_op ? 4: 2);
+                               dyn_read_word(DREG(EA),DREG(EA),false);
+                               dyn_set_eip_last_end(DREG(TMPB));
+                               dyn_save_critical_regs();
+                               gen_call_function(
+                                       decode.modrm.reg == 3 ? (void*)&CPU_CALL : (void*)&CPU_JMP,
+                                       decode.big_op ? "%Id%Drw%Drd%Drd" : "%Id%Drw%Drw%Drd",
+                                       decode.big_op,DREG(EA),DREG(TMPW),DREG(TMPB));
+                               dyn_flags_host_to_gen();
+                               goto core_close_block;
+                       case 0x6:               /* PUSH Ev */
+                               gen_releasereg(DREG(EA));
+                               dyn_push(src);
+                               break;
+                       default:
+                               LOG(LOG_CPU,LOG_ERROR)("CPU:GRP5:Illegal opcode 0xff");
+                               goto illegalopcode;
+                       }}
+                       break;
+               default:
+#if DYN_LOG
+//                     LOG_MSG("Dynamic unhandled opcode %X",opcode);
+#endif
+                       goto illegalopcode;
+               }
+       }
+       // link to next block because the maximum number of opcodes has been reached
+       dyn_set_eip_end();
+       dyn_reduce_cycles();
+       dyn_save_critical_regs();
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start));
+       dyn_closeblock();
+       goto finish_block;
+core_close_block:
+       dyn_reduce_cycles();
+       dyn_save_critical_regs();
+       gen_return(BR_Normal);
+       dyn_closeblock();
+       goto finish_block;
+illegalopcode:
+       dyn_set_eip_last();
+       dyn_reduce_cycles();
+       dyn_save_critical_regs();
+       gen_return(BR_Opcode);
+       dyn_closeblock();
+       goto finish_block;
+#if (C_DEBUG)
+       dyn_set_eip_last();
+       dyn_reduce_cycles();
+       dyn_save_critical_regs();
+       gen_return(BR_OpcodeFull);
+       dyn_closeblock();
+       goto finish_block;
+#endif
+finish_block:
+       /* Setup the correct end-address */
+       decode.active_block->page.end=--decode.page.index;
+//     LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end);
+       return decode.block;
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/dyn_fpu.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/dyn_fpu.h
new file mode 100644 (file)
index 0000000..6534b70
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "dosbox.h"
+#if C_FPU
+
+#include <math.h>
+#include <float.h>
+#include "cross.h"
+#include "mem.h"
+#include "fpu.h"
+#include "cpu.h"
+
+
+static void FPU_FDECSTP(){
+       TOP = (TOP - 1) & 7;
+}
+
+static void FPU_FINCSTP(){
+       TOP = (TOP + 1) & 7;
+}
+
+static void FPU_FNSTCW(PhysPt addr){
+       mem_writew(addr,fpu.cw);
+}
+
+static void FPU_FFREE(Bitu st) {
+       fpu.tags[st]=TAG_Empty;
+}
+
+
+#if C_FPU_X86
+#include "../../fpu/fpu_instructions_x86.h"
+#else
+#include "../../fpu/fpu_instructions.h"
+#endif
+
+
+#define dyn_fpu_top() {                                \
+       gen_protectflags();                             \
+       gen_load_host(&TOP,DREG(EA),4); \
+       gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm);        \
+       gen_dop_word_imm(DOP_AND,true,DREG(EA),7);      \
+       gen_load_host(&TOP,DREG(TMPB),4);                       \
+}
+
+static void dyn_eatree() {
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       switch (group){
+       case 0x00:              /* FADD ST,STi */
+               gen_call_function((void*)&FPU_FADD_EA,"%Ddr",DREG(TMPB));
+               break;
+       case 0x01:              /* FMUL  ST,STi */
+               gen_call_function((void*)&FPU_FMUL_EA,"%Ddr",DREG(TMPB));
+               break;
+       case 0x02:              /* FCOM  STi */
+               gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
+               break;
+       case 0x03:              /* FCOMP STi */
+               gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
+               gen_call_function((void*)&FPU_FPOP,"");
+               break;
+       case 0x04:              /* FSUB  ST,STi */
+               gen_call_function((void*)&FPU_FSUB_EA,"%Ddr",DREG(TMPB));
+               break;  
+       case 0x05:              /* FSUBR ST,STi */
+               gen_call_function((void*)&FPU_FSUBR_EA,"%Ddr",DREG(TMPB));
+               break;
+       case 0x06:              /* FDIV  ST,STi */
+               gen_call_function((void*)&FPU_FDIV_EA,"%Ddr",DREG(TMPB));
+               break;
+       case 0x07:              /* FDIVR ST,STi */
+               gen_call_function((void*)&FPU_FDIVR_EA,"%Ddr",DREG(TMPB));
+               break;
+       default:
+               break;
+       }
+}
+
+static void dyn_fpu_esc0(){
+       dyn_get_modrm(); 
+       if (decode.modrm.val >= 0xc0) { 
+               dyn_fpu_top();
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               switch (group){
+               case 0x00:              //FADD ST,STi /
+                       gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x01:              // FMUL  ST,STi /
+                       gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x02:              // FCOM  STi /
+                       gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x03:              // FCOMP STi /
+                       gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x04:              // FSUB  ST,STi /
+                       gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;  
+               case 0x05:              // FSUBR ST,STi /
+                       gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x06:              // FDIV  ST,STi /
+                       gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x07:              // FDIVR ST,STi /
+                       gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               default:
+                       break;
+               }
+       } else { 
+               dyn_fill_ea();
+               gen_call_function((void*)&FPU_FLD_F32_EA,"%Ddr",DREG(EA)); 
+               gen_load_host(&TOP,DREG(TMPB),4);
+               dyn_eatree();
+       }
+}
+
+static void dyn_fpu_esc1(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               switch (group){
+               case 0x00: /* FLD STi */
+                       gen_protectflags(); 
+                       gen_load_host(&TOP,DREG(EA),4); 
+                       gen_dop_word_imm(DOP_ADD,true,DREG(EA),decode.modrm.rm); 
+                       gen_dop_word_imm(DOP_AND,true,DREG(EA),7); 
+                       gen_call_function((void*)&FPU_PREP_PUSH,""); 
+                       gen_load_host(&TOP,DREG(TMPB),4); 
+                       gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x01: /* FXCH STi */
+                       dyn_fpu_top();
+                       gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x02: /* FNOP */
+                       gen_call_function((void*)&FPU_FNOP,"");
+                       break;
+               case 0x03: /* FSTP STi */
+                       dyn_fpu_top();
+                       gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;   
+               case 0x04:
+                       switch(sub){
+                       case 0x00:       /* FCHS */
+                               gen_call_function((void*)&FPU_FCHS,"");
+                               break;
+                       case 0x01:       /* FABS */
+                               gen_call_function((void*)&FPU_FABS,"");
+                               break;
+                       case 0x02:       /* UNKNOWN */
+                       case 0x03:       /* ILLEGAL */
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
+                               break;
+                       case 0x04:       /* FTST */
+                               gen_call_function((void*)&FPU_FTST,"");
+                               break;
+                       case 0x05:       /* FXAM */
+                               gen_call_function((void*)&FPU_FXAM,"");
+                               break;
+                       case 0x06:       /* FTSTP (cyrix)*/
+                       case 0x07:       /* UNKNOWN */
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
+                               break;
+                       }
+                       break;
+               case 0x05:
+                       switch(sub){    
+                       case 0x00:       /* FLD1 */
+                               gen_call_function((void*)&FPU_FLD1,"");
+                               break;
+                       case 0x01:       /* FLDL2T */
+                               gen_call_function((void*)&FPU_FLDL2T,"");
+                               break;
+                       case 0x02:       /* FLDL2E */
+                               gen_call_function((void*)&FPU_FLDL2E,"");
+                               break;
+                       case 0x03:       /* FLDPI */
+                               gen_call_function((void*)&FPU_FLDPI,"");
+                               break;
+                       case 0x04:       /* FLDLG2 */
+                               gen_call_function((void*)&FPU_FLDLG2,"");
+                               break;
+                       case 0x05:       /* FLDLN2 */
+                               gen_call_function((void*)&FPU_FLDLN2,"");
+                               break;
+                       case 0x06:       /* FLDZ*/
+                               gen_call_function((void*)&FPU_FLDZ,"");
+                               break;
+                       case 0x07:       /* ILLEGAL */
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
+                               break;
+                       }
+                       break;
+               case 0x06:
+                       switch(sub){
+                       case 0x00:      /* F2XM1 */
+                               gen_call_function((void*)&FPU_F2XM1,"");
+                               break;
+                       case 0x01:      /* FYL2X */
+                               gen_call_function((void*)&FPU_FYL2X,"");
+                               break;
+                       case 0x02:      /* FPTAN  */
+                               gen_call_function((void*)&FPU_FPTAN,"");
+                               break;
+                       case 0x03:      /* FPATAN */
+                               gen_call_function((void*)&FPU_FPATAN,"");
+                               break;
+                       case 0x04:      /* FXTRACT */
+                               gen_call_function((void*)&FPU_FXTRACT,"");
+                               break;
+                       case 0x05:      /* FPREM1 */
+                               gen_call_function((void*)&FPU_FPREM1,"");
+                               break;
+                       case 0x06:      /* FDECSTP */
+                               gen_call_function((void*)&FPU_FDECSTP,"");
+                               break;
+                       case 0x07:      /* FINCSTP */
+                               gen_call_function((void*)&FPU_FINCSTP,"");
+                               break;
+                       default:
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
+                               break;
+                       }
+                       break;
+               case 0x07:
+                       switch(sub){
+                       case 0x00:              /* FPREM */
+                               gen_call_function((void*)&FPU_FPREM,"");
+                               break;
+                       case 0x01:              /* FYL2XP1 */
+                               gen_call_function((void*)&FPU_FYL2XP1,"");
+                               break;
+                       case 0x02:              /* FSQRT */
+                               gen_call_function((void*)&FPU_FSQRT,"");
+                               break;
+                       case 0x03:              /* FSINCOS */
+                               gen_call_function((void*)&FPU_FSINCOS,"");
+                               break;
+                       case 0x04:              /* FRNDINT */
+                               gen_call_function((void*)&FPU_FRNDINT,"");
+                               break;
+                       case 0x05:              /* FSCALE */
+                               gen_call_function((void*)&FPU_FSCALE,"");
+                               break;
+                       case 0x06:              /* FSIN */
+                               gen_call_function((void*)&FPU_FSIN,"");
+                               break;
+                       case 0x07:              /* FCOS */
+                               gen_call_function((void*)&FPU_FCOS,"");
+                               break;
+                       default:
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
+                               break;
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",group,sub);
+                       break;
+               }
+       } else {
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               dyn_fill_ea(); 
+               switch(group){
+               case 0x00: /* FLD float*/
+                       gen_protectflags(); 
+                       gen_call_function((void*)&FPU_PREP_PUSH,"");
+                       gen_load_host(&TOP,DREG(TMPB),4); 
+                       gen_call_function((void*)&FPU_FLD_F32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x01: /* UNKNOWN */
+                       LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02: /* FST float*/
+                       gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
+                       break;
+               case 0x03: /* FSTP float*/
+                       gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x04: /* FLDENV */
+                       gen_call_function((void*)&FPU_FLDENV,"%Ddr",DREG(EA));
+                       break;
+               case 0x05: /* FLDCW */
+                       gen_call_function((void *)&FPU_FLDCW,"%Ddr",DREG(EA));
+                       break;
+               case 0x06: /* FSTENV */
+                       gen_call_function((void *)&FPU_FSTENV,"%Ddr",DREG(EA));
+                       break;
+               case 0x07:  /* FNSTCW*/
+                       gen_call_function((void *)&FPU_FNSTCW,"%Ddr",DREG(EA));
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       }
+}
+
+static void dyn_fpu_esc2(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               switch(group){
+               case 0x05:
+                       switch(sub){
+                       case 0x01:              /* FUCOMPP */
+                               gen_protectflags(); 
+                               gen_load_host(&TOP,DREG(EA),4); 
+                               gen_dop_word_imm(DOP_ADD,true,DREG(EA),1); 
+                               gen_dop_word_imm(DOP_AND,true,DREG(EA),7); 
+                               gen_load_host(&TOP,DREG(TMPB),4); 
+                               gen_call_function((void *)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                               gen_call_function((void *)&FPU_FPOP,"");
+                               gen_call_function((void *)&FPU_FPOP,"");
+                               break;
+                       default:
+                               LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub); 
+                               break;
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       } else {
+               dyn_fill_ea(); 
+               gen_call_function((void*)&FPU_FLD_I32_EA,"%Ddr",DREG(EA)); 
+               gen_load_host(&TOP,DREG(TMPB),4); 
+               dyn_eatree();
+       }
+}
+
+static void dyn_fpu_esc3(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               switch (group) {
+               case 0x04:
+                       switch (sub) {
+                       case 0x00:                              //FNENI
+                       case 0x01:                              //FNDIS
+                               LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub);
+                               break;
+                       case 0x02:                              //FNCLEX FCLEX
+                               gen_call_function((void*)&FPU_FCLEX,"");
+                               break;
+                       case 0x03:                              //FNINIT FINIT
+                               gen_call_function((void*)&FPU_FINIT,"");
+                               break;
+                       case 0x04:                              //FNSETPM
+                       case 0x05:                              //FRSTPM
+//                             LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
+                               break;
+                       default:
+                               E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub);
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       } else {
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               dyn_fill_ea(); 
+               switch(group){
+               case 0x00:      /* FILD */
+                       gen_call_function((void*)&FPU_PREP_PUSH,"");
+                       gen_protectflags(); 
+                       gen_load_host(&TOP,DREG(TMPB),4); 
+                       gen_call_function((void*)&FPU_FLD_I32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x01:      /* FISTTP */
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02:      /* FIST */
+                       gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
+                       break;
+               case 0x03:      /* FISTP */
+                       gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x05:      /* FLD 80 Bits Real */
+                       gen_call_function((void*)&FPU_PREP_PUSH,"");
+                       gen_call_function((void*)&FPU_FLD_F80,"%Ddr",DREG(EA));
+                       break;
+               case 0x07:      /* FSTP 80 Bits Real */
+                       gen_call_function((void*)&FPU_FST_F80,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
+               }
+       }
+}
+
+static void dyn_fpu_esc4(){
+       dyn_get_modrm();  
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       Bitu sub=(decode.modrm.val & 7);
+       if (decode.modrm.val >= 0xc0) { 
+               dyn_fpu_top();
+               switch(group){
+               case 0x00:      /* FADD STi,ST*/
+                       gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x01:      /* FMUL STi,ST*/
+                       gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x02:  /* FCOM*/
+                       gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x03:  /* FCOMP*/
+                       gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x04:  /* FSUBR STi,ST*/
+                       gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x05:  /* FSUB  STi,ST*/
+                       gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x06:  /* FDIVR STi,ST*/
+                       gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x07:  /* FDIV STi,ST*/
+                       gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               default:
+                       break;
+               }
+       } else { 
+               dyn_fill_ea(); 
+               gen_call_function((void*)&FPU_FLD_F64_EA,"%Ddr",DREG(EA)); 
+               gen_load_host(&TOP,DREG(TMPB),4); 
+               dyn_eatree();
+       }
+}
+
+static void dyn_fpu_esc5(){
+       dyn_get_modrm();  
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       Bitu sub=(decode.modrm.val & 7);
+       if (decode.modrm.val >= 0xc0) { 
+               dyn_fpu_top();
+               switch(group){
+               case 0x00: /* FFREE STi */
+                       gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
+                       break;
+               case 0x01: /* FXCH STi*/
+                       gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x02: /* FST STi */
+                       gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x03:  /* FSTP STi*/
+                       gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x04:      /* FUCOM STi */
+                       gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x05:      /*FUCOMP STi */
+                       gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",group,sub);
+                       break;
+        }
+               gen_releasereg(DREG(EA));
+               gen_releasereg(DREG(TMPB));
+       } else {
+               dyn_fill_ea(); 
+               switch(group){
+               case 0x00:  /* FLD double real*/
+                       gen_call_function((void*)&FPU_PREP_PUSH,"");
+                       gen_protectflags(); 
+                       gen_load_host(&TOP,DREG(TMPB),4); 
+                       gen_call_function((void*)&FPU_FLD_F64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x01:  /* FISTTP longint*/
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02:   /* FST double real*/
+                       gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
+                       break;
+               case 0x03:      /* FSTP double real*/
+                       gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x04:      /* FRSTOR */
+                       gen_call_function((void*)&FPU_FRSTOR,"%Ddr",DREG(EA));
+                       break;
+               case 0x06:      /* FSAVE */
+                       gen_call_function((void*)&FPU_FSAVE,"%Ddr",DREG(EA));
+                       break;
+               case 0x07:   /*FNSTSW */
+                       gen_protectflags(); 
+                       gen_load_host(&TOP,DREG(TMPB),4); 
+                       gen_call_function((void*)&FPU_SET_TOP,"%Dd",DREG(TMPB));
+                       gen_load_host(&fpu.sw,DREG(TMPB),4); 
+                       gen_call_function((void*)&mem_writew,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
+               }
+       }
+}
+
+static void dyn_fpu_esc6(){
+       dyn_get_modrm();  
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       Bitu sub=(decode.modrm.val & 7);
+       if (decode.modrm.val >= 0xc0) { 
+               dyn_fpu_top();
+               switch(group){
+               case 0x00:      /*FADDP STi,ST*/
+                       gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x01:      /* FMULP STi,ST*/
+                       gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x02:  /* FCOMP5*/
+                       gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;  /* TODO IS THIS ALLRIGHT ????????? */
+               case 0x03:  /*FCOMPP*/
+                       if(sub != 1) {
+                               LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",group,sub);
+                               return;
+                       }
+                       gen_load_host(&TOP,DREG(EA),4); 
+                       gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
+                       gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
+                       gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,""); /* extra pop at the bottom*/
+                       break;
+               case 0x04:  /* FSUBRP STi,ST*/
+                       gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x05:  /* FSUBP  STi,ST*/
+                       gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x06:      /* FDIVRP STi,ST*/
+                       gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x07:  /* FDIVP STi,ST*/
+                       gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               default:
+                       break;
+               }
+               gen_call_function((void*)&FPU_FPOP,"");         
+       } else {
+               dyn_fill_ea(); 
+               gen_call_function((void*)&FPU_FLD_I16_EA,"%Ddr",DREG(EA)); 
+               gen_load_host(&TOP,DREG(TMPB),4); 
+               dyn_eatree();
+       }
+}
+
+static void dyn_fpu_esc7(){
+       dyn_get_modrm();  
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       Bitu sub=(decode.modrm.val & 7);
+       if (decode.modrm.val >= 0xc0) { 
+               switch (group){
+               case 0x00: /* FFREEP STi*/
+                       dyn_fpu_top();
+                       gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x01: /* FXCH STi*/
+                       dyn_fpu_top();
+                       gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       break;
+               case 0x02:  /* FSTP STi*/
+               case 0x03:  /* FSTP STi*/
+                       dyn_fpu_top();
+                       gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x04:
+                       switch(sub){
+                               case 0x00:     /* FNSTSW AX*/
+                                       gen_load_host(&TOP,DREG(TMPB),4);
+                                       gen_call_function((void*)&FPU_SET_TOP,"%Ddr",DREG(TMPB)); 
+                                       gen_mov_host(&fpu.sw,DREG(EAX),2);
+                                       break;
+                               default:
+                                       LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
+                                       break;
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       } else {
+               dyn_fill_ea(); 
+               switch(group){
+               case 0x00:  /* FILD Bit16s */
+                       gen_call_function((void*)&FPU_PREP_PUSH,"");
+                       gen_load_host(&TOP,DREG(TMPB),4); 
+                       gen_call_function((void*)&FPU_FLD_I16,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x01:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02:   /* FIST Bit16s */
+                       gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
+                       break;
+               case 0x03:      /* FISTP Bit16s */
+                       gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x04:   /* FBLD packed BCD */
+                       gen_call_function((void*)&FPU_PREP_PUSH,"");
+                       gen_load_host(&TOP,DREG(TMPB),4);
+                       gen_call_function((void*)&FPU_FBLD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x05:  /* FILD Bit64s */
+                       gen_call_function((void*)&FPU_PREP_PUSH,"");
+                       gen_load_host(&TOP,DREG(TMPB),4);
+                       gen_call_function((void*)&FPU_FLD_I64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
+                       break;
+               case 0x06:      /* FBSTP packed BCD */
+                       gen_call_function((void*)&FPU_FBST,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               case 0x07:  /* FISTP Bit64s */
+                       gen_call_function((void*)&FPU_FST_I64,"%Ddr",DREG(EA));
+                       gen_call_function((void*)&FPU_FPOP,"");
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       }
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/dyn_fpu_dh.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/dyn_fpu_dh.h
new file mode 100644 (file)
index 0000000..2387045
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "dosbox.h"
+#if C_FPU
+
+static void FPU_FLD_16(PhysPt addr) {
+       dyn_dh_fpu.temp.m1 = (Bit32u)mem_readw(addr);
+}
+
+static void FPU_FST_16(PhysPt addr) {
+       mem_writew(addr,(Bit16u)dyn_dh_fpu.temp.m1);
+}
+
+static void FPU_FLD_32(PhysPt addr) {
+       dyn_dh_fpu.temp.m1 = mem_readd(addr);
+}
+
+static void FPU_FST_32(PhysPt addr) {
+       mem_writed(addr,dyn_dh_fpu.temp.m1);
+}
+
+static void FPU_FLD_64(PhysPt addr) {
+       dyn_dh_fpu.temp.m1 = mem_readd(addr);
+       dyn_dh_fpu.temp.m2 = mem_readd(addr+4);
+}
+
+static void FPU_FST_64(PhysPt addr) {
+       mem_writed(addr,dyn_dh_fpu.temp.m1);
+       mem_writed(addr+4,dyn_dh_fpu.temp.m2);
+}
+
+static void FPU_FLD_80(PhysPt addr) {
+       dyn_dh_fpu.temp.m1 = mem_readd(addr);
+       dyn_dh_fpu.temp.m2 = mem_readd(addr+4);
+       dyn_dh_fpu.temp.m3 = mem_readw(addr+8);
+}
+
+static void FPU_FST_80(PhysPt addr) {
+       mem_writed(addr,dyn_dh_fpu.temp.m1);
+       mem_writed(addr+4,dyn_dh_fpu.temp.m2);
+       mem_writew(addr+8,dyn_dh_fpu.temp.m3);
+}
+
+static void FPU_FLDCW_DH(PhysPt addr){
+       dyn_dh_fpu.cw = mem_readw(addr);
+       dyn_dh_fpu.temp.m1 = (Bit32u)(dyn_dh_fpu.cw|0x3f);
+}
+
+static void FPU_FNSTCW_DH(PhysPt addr){
+       mem_writew(addr,(Bit16u)(dyn_dh_fpu.cw&0xffff));
+}
+
+static void FPU_FNINIT_DH(void){
+       dyn_dh_fpu.cw = 0x37f;
+}
+
+static void FPU_FSTENV_DH(PhysPt addr){
+       if(!cpu.code.big) {
+               mem_writew(addr+0,(Bit16u)dyn_dh_fpu.cw);
+               mem_writew(addr+2,(Bit16u)dyn_dh_fpu.temp.m2);
+               mem_writew(addr+4,dyn_dh_fpu.temp.m3);
+       } else { 
+               mem_writed(addr+0,dyn_dh_fpu.temp.m1);
+               mem_writew(addr+0,(Bit16u)dyn_dh_fpu.cw);
+               mem_writed(addr+4,dyn_dh_fpu.temp.m2);
+               mem_writed(addr+8,dyn_dh_fpu.temp.m3);
+       }
+}
+
+static void FPU_FLDENV_DH(PhysPt addr){
+       if(!cpu.code.big) {
+               dyn_dh_fpu.cw = (Bit32u)mem_readw(addr);
+               dyn_dh_fpu.temp.m1 = dyn_dh_fpu.cw|0x3f;
+               dyn_dh_fpu.temp.m2 = (Bit32u)mem_readw(addr+2);
+               dyn_dh_fpu.temp.m3 = mem_readw(addr+4);
+       } else { 
+               dyn_dh_fpu.cw = (Bit32u)mem_readw(addr);
+               dyn_dh_fpu.temp.m1 = mem_readd(addr)|0x3f;
+               dyn_dh_fpu.temp.m2 = mem_readd(addr+4);
+               dyn_dh_fpu.temp.m3 = mem_readw(addr+8);
+               dyn_dh_fpu.temp.d1 = mem_readw(addr+10);
+       }
+}
+
+static void FPU_FSAVE_DH(PhysPt addr){
+       if (!cpu.code.big) {
+               mem_writew(addr,(Bit16u)dyn_dh_fpu.cw);
+               addr+=2;
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x04]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x05]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x08]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x09]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x0c]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x0d]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x10]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x11]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x14]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x15]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x18]);
+               mem_writeb(addr++,dyn_dh_fpu.temp_state[0x19]);
+               for(Bitu i=28;i<108;i++) mem_writeb(addr++,dyn_dh_fpu.temp_state[i]);
+       } else {
+               mem_writew(addr,(Bit16u)dyn_dh_fpu.cw);
+               addr+=2;
+               for(Bitu i=2;i<108;i++) mem_writeb(addr++,dyn_dh_fpu.temp_state[i]);
+       }
+}
+
+static void FPU_FRSTOR_DH(PhysPt addr){
+       if (!cpu.code.big) {
+               dyn_dh_fpu.cw = (Bit32u)mem_readw(addr);
+               dyn_dh_fpu.temp_state[0x00] = mem_readb(addr++)|0x3f;
+               dyn_dh_fpu.temp_state[0x01] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x04] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x05] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x08] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x09] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x0c] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x0d] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x10] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x11] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x14] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x15] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x18] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0x19] = mem_readb(addr++);
+               for(Bitu i=28;i<108;i++) dyn_dh_fpu.temp_state[i] = mem_readb(addr++);
+       } else {
+               dyn_dh_fpu.cw = (Bit32u)mem_readw(addr);
+               for(Bitu i=0;i<108;i++) dyn_dh_fpu.temp_state[i] = mem_readb(addr++);
+               dyn_dh_fpu.temp_state[0]|=0x3f;
+       }
+}
+
+static void dh_fpu_esc0(){
+       dyn_get_modrm(); 
+       if (decode.modrm.val >= 0xc0) {
+               cache_addb(0xd8);
+               cache_addb(decode.modrm.val);
+       } else { 
+               dyn_fill_ea();
+               gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA)); 
+               cache_addb(0xd8);
+               cache_addb(0x05|(decode.modrm.reg<<3));
+               cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+       }
+}
+
+static void dh_fpu_esc1(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) {
+               cache_addb(0xd9);
+               cache_addb(decode.modrm.val);
+       } else {
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               dyn_fill_ea(); 
+               switch(group){
+               case 0x00: /* FLD float*/
+                       gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
+                       cache_addb(0xd9);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x01: /* UNKNOWN */
+                       LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02: /* FST float*/
+                       cache_addb(0xd9);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
+                       break;
+               case 0x03: /* FSTP float*/
+                       cache_addb(0xd9);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
+                       break;
+               case 0x04: /* FLDENV */
+                       gen_call_function((void*)&FPU_FLDENV_DH,"%Ddr",DREG(EA));
+                       cache_addb(0xd9);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x05: /* FLDCW */
+                       gen_call_function((void *)&FPU_FLDCW_DH,"%Ddr",DREG(EA));
+                       cache_addb(0xd9);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x06: /* FSTENV */
+                       cache_addb(0xd9);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FSTENV_DH,"%Ddr",DREG(EA));
+                       break;
+               case 0x07:  /* FNSTCW*/
+                       gen_call_function((void*)&FPU_FNSTCW_DH,"%Ddr",DREG(EA));
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       }
+}
+
+static void dh_fpu_esc2(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               cache_addb(0xda);
+               cache_addb(decode.modrm.val);
+       } else {
+               dyn_fill_ea(); 
+               gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA)); 
+               cache_addb(0xda);
+               cache_addb(0x05|(decode.modrm.reg<<3));
+               cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+       }
+}
+
+static void dh_fpu_esc3(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               switch (group) {
+               case 0x04:
+                       switch (sub) {
+                       case 0x00:                              //FNENI
+                       case 0x01:                              //FNDIS
+                               LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion :%d",sub);
+                               break;
+                       case 0x02:                              //FNCLEX FCLEX
+                               cache_addb(0xdb);
+                               cache_addb(decode.modrm.val);
+                               break;
+                       case 0x03:                              //FNINIT FINIT
+                               gen_call_function((void*)&FPU_FNINIT_DH,""); 
+                               cache_addb(0xdb);
+                               cache_addb(decode.modrm.val);
+                               break;
+                       case 0x04:                              //FNSETPM
+                       case 0x05:                              //FRSTPM
+//                             LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
+                               break;
+                       default:
+                               E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",group,sub);
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       } else {
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               dyn_fill_ea(); 
+               switch(group){
+               case 0x00:      /* FILD */
+                       gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
+                       cache_addb(0xdb);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x01:      /* FISTTP */
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02:      /* FIST */
+                       cache_addb(0xdb);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
+                       break;
+               case 0x03:      /* FISTP */
+                       cache_addb(0xdb);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
+                       break;
+               case 0x05:      /* FLD 80 Bits Real */
+                       gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA));
+                       cache_addb(0xdb);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x07:      /* FSTP 80 Bits Real */
+                       cache_addb(0xdb);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA));
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
+               }
+       }
+}
+
+static void dh_fpu_esc4(){
+       dyn_get_modrm();  
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       Bitu sub=(decode.modrm.val & 7);
+       if (decode.modrm.val >= 0xc0) { 
+               cache_addb(0xdc);
+               cache_addb(decode.modrm.val);
+       } else { 
+               dyn_fill_ea(); 
+               gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA)); 
+               cache_addb(0xdc);
+               cache_addb(0x05|(decode.modrm.reg<<3));
+               cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+       }
+}
+
+static void dh_fpu_esc5(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               cache_addb(0xdd);
+               cache_addb(decode.modrm.val);
+       } else {
+               dyn_fill_ea(); 
+               Bitu group=(decode.modrm.val >> 3) & 7;
+               Bitu sub=(decode.modrm.val & 7);
+               switch(group){
+               case 0x00:  /* FLD double real*/
+                       gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
+                       cache_addb(0xdd);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x01:  /* FISTTP longint*/
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02:   /* FST double real*/
+                       cache_addb(0xdd);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
+                       break;
+               case 0x03:      /* FSTP double real*/
+                       cache_addb(0xdd);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
+                       break;
+               case 0x04:      /* FRSTOR */
+                       gen_call_function((void*)&FPU_FRSTOR_DH,"%Ddr",DREG(EA));
+                       cache_addb(0xdd);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0])));
+                       break;
+               case 0x06:      /* FSAVE */
+                       cache_addb(0xdd);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0])));
+                       gen_call_function((void*)&FPU_FSAVE_DH,"%Ddr",DREG(EA));
+                       cache_addb(0xdb);
+                       cache_addb(0xe3);
+                       break;
+               case 0x07:   /* FNSTSW */
+                       cache_addb(0xdd);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
+               }
+       }
+}
+
+static void dh_fpu_esc6(){
+       dyn_get_modrm();  
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       Bitu sub=(decode.modrm.val & 7);
+       if (decode.modrm.val >= 0xc0) { 
+               cache_addb(0xde);
+               cache_addb(decode.modrm.val);
+       } else {
+               dyn_fill_ea(); 
+               gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA)); 
+               cache_addb(0xde);
+               cache_addb(0x05|(decode.modrm.reg<<3));
+               cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+       }
+}
+
+static void dh_fpu_esc7(){
+       dyn_get_modrm();  
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       Bitu sub=(decode.modrm.val & 7);
+       if (decode.modrm.val >= 0xc0) { 
+               switch (group){
+               case 0x00: /* FFREEP STi*/
+                       cache_addb(0xdf);
+                       cache_addb(decode.modrm.val);
+                       break;
+               case 0x01: /* FXCH STi*/
+                       cache_addb(0xdf);
+                       cache_addb(decode.modrm.val);
+                       break;
+               case 0x02:  /* FSTP STi*/
+               case 0x03:  /* FSTP STi*/
+                       cache_addb(0xdf);
+                       cache_addb(decode.modrm.val);
+                       break;
+               case 0x04:
+                       switch(sub){
+                               case 0x00:     /* FNSTSW AX*/
+                                       cache_addb(0xdd);
+                                       cache_addb(0x05|(0x07<<3));
+                                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                                       gen_load_host(&(dyn_dh_fpu.temp.m1),DREG(TMPB),4);
+                                       gen_dop_word(DOP_MOV,false,DREG(EAX),DREG(TMPB));
+                                       gen_releasereg(DREG(TMPB));
+                                       break;
+                               default:
+                                       LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
+                                       break;
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       } else {
+               dyn_fill_ea(); 
+               switch(group){
+               case 0x00:  /* FILD Bit16s */
+                       gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA));
+                       cache_addb(0xdf);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x01:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               case 0x02:   /* FIST Bit16s */
+                       cache_addb(0xdf);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
+                       break;
+               case 0x03:      /* FISTP Bit16s */
+                       cache_addb(0xdf);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
+                       break;
+               case 0x04:   /* FBLD packed BCD */
+                       gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA));
+                       cache_addb(0xdf);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x05:  /* FILD Bit64s */
+                       gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
+                       cache_addb(0xdf);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       break;
+               case 0x06:      /* FBSTP packed BCD */
+                       cache_addb(0xdf);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA));
+                       break;
+               case 0x07:  /* FISTP Bit64s */
+                       cache_addb(0xdf);
+                       cache_addb(0x05|(decode.modrm.reg<<3));
+                       cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
+                       gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
+                       break;
+               }
+       }
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/helpers.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/helpers.h
new file mode 100644 (file)
index 0000000..022e678
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+static bool dyn_helper_divb(Bit8u val) {
+       if (!val) return CPU_PrepareException(0,0);
+       Bitu quo=reg_ax / val;
+       Bit8u rem=(Bit8u)(reg_ax % val);
+       Bit8u quo8=(Bit8u)(quo&0xff);
+       if (quo>0xff) return CPU_PrepareException(0,0);
+       reg_ah=rem;
+       reg_al=quo8;
+       return false;
+}
+
+static bool dyn_helper_idivb(Bit8s val) {
+       if (!val) return CPU_PrepareException(0,0);
+       Bits quo=(Bit16s)reg_ax / val;
+       Bit8s rem=(Bit8s)((Bit16s)reg_ax % val);
+       Bit8s quo8s=(Bit8s)(quo&0xff);
+       if (quo!=(Bit16s)quo8s) return CPU_PrepareException(0,0);
+       reg_ah=rem;
+       reg_al=quo8s;
+       return false;
+}
+
+static bool dyn_helper_divw(Bit16u val) {
+       if (!val) return CPU_PrepareException(0,0);
+       Bitu num=(reg_dx<<16)|reg_ax;
+       Bitu quo=num/val;
+       Bit16u rem=(Bit16u)(num % val);
+       Bit16u quo16=(Bit16u)(quo&0xffff);
+       if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0);
+       reg_dx=rem;
+       reg_ax=quo16;
+       return false;
+}
+
+static bool dyn_helper_idivw(Bit16s val) {
+       if (!val) return CPU_PrepareException(0,0);
+       Bits num=(reg_dx<<16)|reg_ax;
+       Bits quo=num/val;
+       Bit16s rem=(Bit16s)(num % val);
+       Bit16s quo16s=(Bit16s)quo;
+       if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0);
+       reg_dx=rem;
+       reg_ax=quo16s;
+       return false;
+}
+
+static bool dyn_helper_divd(Bit32u val) {
+       if (!val) return CPU_PrepareException(0,0);
+       Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax;
+       Bit64u quo=num/val;
+       Bit32u rem=(Bit32u)(num % val);
+       Bit32u quo32=(Bit32u)(quo&0xffffffff);
+       if (quo!=(Bit64u)quo32) return CPU_PrepareException(0,0);
+       reg_edx=rem;
+       reg_eax=quo32;
+       return false;
+}
+
+static bool dyn_helper_idivd(Bit32s val) {
+       if (!val) return CPU_PrepareException(0,0);
+       Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax;
+       Bit64s quo=num/val;
+       Bit32s rem=(Bit32s)(num % val);
+       Bit32s quo32s=(Bit32s)(quo&0xffffffff);
+       if (quo!=(Bit64s)quo32s) return CPU_PrepareException(0,0);
+       reg_edx=rem;
+       reg_eax=quo32s;
+       return false;
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/risc_x86.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/risc_x86.h
new file mode 100644 (file)
index 0000000..74c8536
--- /dev/null
@@ -0,0 +1,1071 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+static void gen_init(void);
+
+/* End of needed */
+
+#define X86_REGS               7
+#define X86_REG_EAX            0x00
+#define X86_REG_ECX            0x01
+#define X86_REG_EDX            0x02
+#define X86_REG_EBX            0x03
+#define X86_REG_EBP            0x04
+#define X86_REG_ESI            0x05
+#define X86_REG_EDI            0x06
+
+#define X86_REG_MASK(_REG_) (1 << X86_REG_ ## _REG_)
+
+static struct {
+       bool flagsactive;
+       Bitu last_used;
+       GenReg * regs[X86_REGS];
+} x86gen;
+
+class GenReg {
+public:
+       GenReg(Bit8u _index) {
+               index=_index;
+               notusable=false;dynreg=0;
+       }
+       DynReg  * dynreg;
+       Bitu last_used;                 //Keeps track of last assigned regs 
+    Bit8u index;
+       bool notusable;
+       void Load(DynReg * _dynreg,bool stale=false) {
+               if (!_dynreg) return;
+               if (GCC_UNLIKELY((Bitu)dynreg)) Clear();
+               dynreg=_dynreg;
+               last_used=x86gen.last_used;
+               dynreg->flags&=~DYNFLG_CHANGED;
+               dynreg->genreg=this;
+               if ((!stale) && (dynreg->flags & (DYNFLG_LOAD|DYNFLG_ACTIVE))) {
+                       cache_addw(0x058b+(index << (8+3)));            //Mov reg,[data]
+                       cache_addd((Bit32u)dynreg->data);
+               }
+               dynreg->flags|=DYNFLG_ACTIVE;
+       }
+       void Save(void) {
+               if (GCC_UNLIKELY(!((Bitu)dynreg))) IllegalOption("GenReg->Save");
+               dynreg->flags&=~DYNFLG_CHANGED;
+               cache_addw(0x0589+(index << (8+3)));            //Mov [data],reg
+               cache_addd((Bit32u)dynreg->data);
+       }
+       void Release(void) {
+               if (GCC_UNLIKELY(!((Bitu)dynreg))) return;
+               if (dynreg->flags&DYNFLG_CHANGED && dynreg->flags&DYNFLG_SAVE) {
+                       Save();
+               }
+               dynreg->flags&=~(DYNFLG_CHANGED|DYNFLG_ACTIVE);
+               dynreg->genreg=0;dynreg=0;
+       }
+       void Clear(void) {
+               if (!dynreg) return;
+               if (dynreg->flags&DYNFLG_CHANGED) {
+                       Save();
+               }
+               dynreg->genreg=0;dynreg=0;
+       }
+};
+
+static BlockReturn gen_runcode(Bit8u * code) {
+       BlockReturn retval;
+#if defined (_MSC_VER)
+       __asm {
+/* Prepare the flags */
+               mov             eax,[code]
+               push    ebx
+               push    ebp
+               push    esi
+               push    edi
+               mov             ebx,[reg_flags]
+               and             ebx,FMASK_TEST
+               push    offset(return_address)
+               push    ebx
+               jmp             eax
+/* Restore the flags */
+return_address:
+               /*      return here with flags in ecx */
+               and             dword ptr [reg_flags],~FMASK_TEST
+               and             ecx,FMASK_TEST
+               or              [reg_flags],ecx
+               pop             edi
+               pop             esi
+               pop             ebp
+               pop             ebx
+               mov             [retval],eax
+       }
+#elif defined (MACOSX)
+       register Bit32u tempflags=reg_flags & FMASK_TEST;
+       __asm__ volatile (
+               "pushl %%ebx                                            \n"
+               "pushl %%ebp                                            \n"
+               "pushl $(run_return_adress)                     \n"
+               "pushl  %2                                                      \n"
+               "jmp  *%3                                                       \n"
+               "run_return_adress:                                     \n"
+               "popl %%ebp                                                     \n"
+               "popl %%ebx                                                     \n"
+               :"=a" (retval), "=c" (tempflags)
+               :"r" (tempflags),"r" (code)
+               :"%edx","%edi","%esi","cc","memory"
+       );
+       reg_flags=(reg_flags & ~FMASK_TEST) | (tempflags & FMASK_TEST);
+#else
+       register Bit32u tempflags=reg_flags & FMASK_TEST;
+       __asm__ volatile (
+               "pushl %%ebp                                            \n"
+               "pushl $(run_return_adress)                     \n"
+               "pushl  %2                                                      \n"
+               "jmp  *%3                                                       \n"
+               "run_return_adress:                                     \n"
+               "popl %%ebp                                                     \n"
+               :"=a" (retval), "=c" (tempflags)
+               :"r" (tempflags),"r" (code)
+               :"%edx","%ebx","%edi","%esi","cc","memory"
+       );
+       reg_flags=(reg_flags & ~FMASK_TEST) | (tempflags & FMASK_TEST);
+#endif
+       return retval;
+}
+
+static GenReg * FindDynReg(DynReg * dynreg,bool stale=false) {
+       x86gen.last_used++;
+       if (dynreg->genreg) {
+               dynreg->genreg->last_used=x86gen.last_used;
+               return dynreg->genreg;
+       }
+       /* Find best match for selected global reg */
+       Bits i;
+       Bits first_used,first_index;
+       first_used=-1;
+       if (dynreg->flags & DYNFLG_HAS8) {
+               /* Has to be eax,ebx,ecx,edx */
+               for (i=first_index=0;i<=X86_REG_EBX;i++) {
+                       GenReg * genreg=x86gen.regs[i];
+                       if (genreg->notusable) continue;
+                       if (!(genreg->dynreg)) {
+                               genreg->Load(dynreg,stale);
+                               return genreg;
+                       }
+                       if (genreg->last_used<(Bitu)first_used) {
+                               first_used=genreg->last_used;
+                               first_index=i;
+                       }
+               }
+       } else {
+               for (i=first_index=X86_REGS-1;i>=0;i--) {
+                       GenReg * genreg=x86gen.regs[i];
+                       if (genreg->notusable) continue;
+                       if (!(genreg->dynreg)) {
+                               genreg->Load(dynreg,stale);
+                               return genreg;
+                       }
+                       if (genreg->last_used<(Bitu)first_used) {
+                               first_used=genreg->last_used;
+                               first_index=i;
+                       }
+               }
+       }
+       /* No free register found use earliest assigned one */
+       GenReg * newreg=x86gen.regs[first_index];
+       newreg->Load(dynreg,stale);
+       return newreg;
+}
+
+static GenReg * ForceDynReg(GenReg * genreg,DynReg * dynreg) {
+       genreg->last_used=++x86gen.last_used;
+       if (dynreg->genreg==genreg) return genreg;
+       if (genreg->dynreg) genreg->Clear();
+       if (dynreg->genreg) dynreg->genreg->Clear();
+       genreg->Load(dynreg);
+       return genreg;
+}
+
+static void gen_preloadreg(DynReg * dynreg) {
+       FindDynReg(dynreg);
+}
+
+static void gen_releasereg(DynReg * dynreg) {
+       GenReg * genreg=dynreg->genreg;
+       if (genreg) genreg->Release();
+       else dynreg->flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED);
+}
+
+static void gen_setupreg(DynReg * dnew,DynReg * dsetup) {
+       dnew->flags=dsetup->flags;
+       if (dnew->genreg==dsetup->genreg) return;
+       /* Not the same genreg must be wrong */
+       if (dnew->genreg) {
+               /* Check if the genreg i'm changing is actually linked to me */
+               if (dnew->genreg->dynreg==dnew) dnew->genreg->dynreg=0;
+       }
+       dnew->genreg=dsetup->genreg;
+       if (dnew->genreg) dnew->genreg->dynreg=dnew;
+}
+
+static void gen_synchreg(DynReg * dnew,DynReg * dsynch) {
+       /* First make sure the registers match */
+       if (dnew->genreg!=dsynch->genreg) {
+               if (dnew->genreg) dnew->genreg->Clear();
+               if (dsynch->genreg) {
+                       dsynch->genreg->Load(dnew);
+               }
+       }
+       /* Always use the loadonce flag from either state */
+       dnew->flags|=(dsynch->flags & dnew->flags&DYNFLG_ACTIVE);
+       if ((dnew->flags ^ dsynch->flags) & DYNFLG_CHANGED) {
+               /* Ensure the changed value gets saved */       
+               if (dnew->flags & DYNFLG_CHANGED) {
+                       dnew->genreg->Save();
+               } else dnew->flags|=DYNFLG_CHANGED;
+       }
+}
+
+static void gen_needflags(void) {
+       if (!x86gen.flagsactive) {
+               x86gen.flagsactive=true;
+               cache_addb(0x9d);               //POPFD
+       }
+}
+
+static void gen_protectflags(void) {
+       if (x86gen.flagsactive) {
+               x86gen.flagsactive=false;
+               cache_addb(0x9c);               //PUSHFD
+       }
+}
+
+static void gen_discardflags(void) {
+       if (!x86gen.flagsactive) {
+               x86gen.flagsactive=true;
+               cache_addw(0xc483);             //ADD ESP,4
+               cache_addb(0x4);
+       }
+}
+
+static void gen_needcarry(void) {
+       if (!x86gen.flagsactive) {
+               x86gen.flagsactive=true;
+               cache_addw(0x2cd1);                     //SHR DWORD [ESP],1
+               cache_addb(0x24);
+               cache_addd(0x0424648d);         //LEA ESP,[ESP+4]
+       }
+}
+
+static void gen_setzeroflag(void) {
+       if (x86gen.flagsactive) IllegalOption("gen_setzeroflag");
+       cache_addw(0x0c83);                     //OR DWORD [ESP],0x40
+       cache_addw(0x4024);
+}
+
+static void gen_clearzeroflag(void) {
+       if (x86gen.flagsactive) IllegalOption("gen_clearzeroflag");
+       cache_addw(0x2483);                     //AND DWORD [ESP],~0x40
+       cache_addw(0xbf24);
+}
+
+static bool skip_flags=false;
+
+static void set_skipflags(bool state) {
+       if (!state) gen_discardflags();
+       skip_flags=state;
+}
+
+static void gen_reinit(void) {
+       x86gen.last_used=0;
+       x86gen.flagsactive=false;
+       for (Bitu i=0;i<X86_REGS;i++) {
+               x86gen.regs[i]->dynreg=0;
+       }
+}
+
+
+static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
+       GenReg * gr1=FindDynReg(dr1,true);
+       switch (size) {
+       case 1:cache_addw(0xb60f);break;        //movzx byte
+       case 2:cache_addw(0xb70f);break;        //movzx word
+       case 4:cache_addb(0x8b);break;  //mov
+       default:
+               IllegalOption("gen_load_host");
+       }
+       cache_addb(0x5+(gr1->index<<3));
+       cache_addd((Bit32u)data);
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) {
+       GenReg * gr1=FindDynReg(dr1,(size==4));
+       switch (size) {
+       case 1:cache_addb(0x8a);break;  //mov byte
+       case 2:cache_addb(0x66);                //mov word
+       case 4:cache_addb(0x8b);break;  //mov
+       default:
+               IllegalOption("gen_load_host");
+       }
+       cache_addb(0x5+((gr1->index+(di1?4:0))<<3));
+       cache_addd((Bit32u)data);
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+
+static void gen_dop_byte(DualOps op,DynReg * dr1,Bit8u di1,DynReg * dr2,Bit8u di2) {
+       GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2);
+       Bit8u tmp;
+       switch (op) {
+       case DOP_ADD:   tmp=0x02; break;
+       case DOP_ADC:   tmp=0x12; break;
+       case DOP_SUB:   tmp=0x2a; break;
+       case DOP_SBB:   tmp=0x1a; break;
+       case DOP_CMP:   tmp=0x3a; goto nochange;
+       case DOP_XOR:   tmp=0x32; break;
+       case DOP_AND:   tmp=0x22; if ((dr1==dr2) && (di1==di2)) goto nochange; break;
+       case DOP_OR:    tmp=0x0a; if ((dr1==dr2) && (di1==di2)) goto nochange; break;
+       case DOP_TEST:  tmp=0x84; goto nochange;
+       case DOP_MOV:   if ((dr1==dr2) && (di1==di2)) return; tmp=0x8a; break;
+       case DOP_XCHG:  tmp=0x86; dr2->flags|=DYNFLG_CHANGED; break;
+       default:
+               IllegalOption("gen_dop_byte");
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+nochange:
+       cache_addw(tmp|(0xc0+((gr1->index+di1)<<3)+gr2->index+di2)<<8);
+}
+
+static void gen_dop_byte_imm(DualOps op,DynReg * dr1,Bit8u di1,Bitu imm) {
+       GenReg * gr1=FindDynReg(dr1);
+       Bit16u tmp;
+       switch (op) {
+       case DOP_ADD:   tmp=0xc080; break;
+       case DOP_ADC:   tmp=0xd080; break;
+       case DOP_SUB:   tmp=0xe880; break;
+       case DOP_SBB:   tmp=0xd880; break;
+       case DOP_CMP:   tmp=0xf880; goto nochange;      //Doesn't change
+       case DOP_XOR:   tmp=0xf080; break;
+       case DOP_AND:   tmp=0xe080; break;
+       case DOP_OR:    tmp=0xc880; break;
+       case DOP_TEST:  tmp=0xc0f6; goto nochange;      //Doesn't change
+       case DOP_MOV:   cache_addb(0xb0+gr1->index+di1);
+                                       dr1->flags|=DYNFLG_CHANGED;
+                                       goto finish;
+       default:
+               IllegalOption("gen_dop_byte_imm");
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+nochange:
+       cache_addw(tmp+((gr1->index+di1)<<8));
+finish:
+       cache_addb(imm);
+}
+
+static void gen_dop_byte_imm_mem(DualOps op,DynReg * dr1,Bit8u di1,void* data) {
+       GenReg * gr1=FindDynReg(dr1);
+       Bit16u tmp;
+       switch (op) {
+       case DOP_ADD:   tmp=0x0502; break;
+       case DOP_ADC:   tmp=0x0512; break;
+       case DOP_SUB:   tmp=0x052a; break;
+       case DOP_SBB:   tmp=0x051a; break;
+       case DOP_CMP:   tmp=0x053a; goto nochange;      //Doesn't change
+       case DOP_XOR:   tmp=0x0532; break;
+       case DOP_AND:   tmp=0x0522; break;
+       case DOP_OR:    tmp=0x050a; break;
+       case DOP_TEST:  tmp=0x0584; goto nochange;      //Doesn't change
+       case DOP_MOV:   tmp=0x0585; break;
+       default:
+               IllegalOption("gen_dop_byte_imm_mem");
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+nochange:
+       cache_addw(tmp+((gr1->index+di1)<<11));
+       cache_addd((Bit32u)data);
+}
+
+static void gen_sop_byte(SingleOps op,DynReg * dr1,Bit8u di1) {
+       GenReg * gr1=FindDynReg(dr1);
+       Bit16u tmp;
+       switch (op) {
+       case SOP_INC: tmp=0xc0FE; break;
+       case SOP_DEC: tmp=0xc8FE; break;
+       case SOP_NOT: tmp=0xd0f6; break;
+       case SOP_NEG: tmp=0xd8f6; break;
+       default:
+               IllegalOption("gen_sop_byte");
+       }
+       cache_addw(tmp + ((gr1->index+di1)<<8));
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+
+static void gen_extend_word(bool sign,DynReg * ddr,DynReg * dsr) {
+       GenReg * gsr=FindDynReg(dsr);
+       GenReg * gdr=FindDynReg(ddr,true);
+       if (sign) cache_addw(0xbf0f);
+       else cache_addw(0xb70f);
+       cache_addb(0xc0+(gdr->index<<3)+(gsr->index));
+       ddr->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_extend_byte(bool sign,bool dword,DynReg * ddr,DynReg * dsr,Bit8u dsi) {
+       GenReg * gsr=FindDynReg(dsr);
+       GenReg * gdr=FindDynReg(ddr,dword);
+       if (!dword) cache_addb(0x66);
+       if (sign) cache_addw(0xbe0f);
+       else cache_addw(0xb60f);
+       cache_addb(0xc0+(gdr->index<<3)+(gsr->index+dsi));
+       ddr->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_lea(DynReg * ddr,DynReg * dsr1,DynReg * dsr2,Bitu scale,Bits imm) {
+       GenReg * gdr=FindDynReg(ddr);
+       Bitu imm_size;
+       Bit8u rm_base=(gdr->index << 3);
+       if (dsr1) {
+               GenReg * gsr1=FindDynReg(dsr1);
+               if (!imm && (gsr1->index!=0x5)) {
+                       imm_size=0;     rm_base+=0x0;                   //no imm
+               } else if ((imm>=-128 && imm<=127)) {
+                       imm_size=1;rm_base+=0x40;                       //Signed byte imm
+               } else {
+                       imm_size=4;rm_base+=0x80;                       //Signed dword imm
+               }
+               if (dsr2) {
+                       GenReg * gsr2=FindDynReg(dsr2);
+                       cache_addb(0x8d);               //LEA
+                       cache_addb(rm_base+0x4);                        //The sib indicator
+                       Bit8u sib=(gsr1->index)+(gsr2->index<<3)+(scale<<6);
+                       cache_addb(sib);
+               } else {
+                       if ((ddr==dsr1) && !imm_size) return;
+                       cache_addb(0x8d);               //LEA
+                       cache_addb(rm_base+gsr1->index);
+               }
+       } else {
+               if (dsr2) {
+                       GenReg * gsr2=FindDynReg(dsr2);
+                       cache_addb(0x8d);                       //LEA
+                       cache_addb(rm_base+0x4);        //The sib indicator
+                       Bit8u sib=(5+(gsr2->index<<3)+(scale<<6));
+                       cache_addb(sib);
+                       imm_size=4;
+               } else {
+                       cache_addb(0x8d);                       //LEA
+                       cache_addb(rm_base+0x05);       //dword imm
+                       imm_size=4;
+               }
+       }
+       switch (imm_size) {
+       case 0: break;
+       case 1:cache_addb(imm);break;
+       case 4:cache_addd(imm);break;
+       }
+       ddr->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_lea_imm_mem(DynReg * ddr,DynReg * dsr,void* data) {
+       GenReg * gdr=FindDynReg(ddr);
+       Bit8u rm_base=(gdr->index << 3);
+       cache_addw(0x058b+(rm_base<<8));
+       cache_addd((Bit32u)data);
+       GenReg * gsr=FindDynReg(dsr);
+       cache_addb(0x8d);               //LEA
+       cache_addb(rm_base+0x44);
+       cache_addb(rm_base+gsr->index);
+       cache_addb(0x00);
+       ddr->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_dop_word(DualOps op,bool dword,DynReg * dr1,DynReg * dr2) {
+       GenReg * gr2=FindDynReg(dr2);
+       GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV);
+       Bit8u tmp;
+       switch (op) {
+       case DOP_ADD:   tmp=0x03; break;
+       case DOP_ADC:   tmp=0x13; break;
+       case DOP_SUB:   tmp=0x2b; break;
+       case DOP_SBB:   tmp=0x1b; break;
+       case DOP_CMP:   tmp=0x3b; goto nochange;
+       case DOP_XOR:   tmp=0x33; break;
+       case DOP_AND:   tmp=0x23; if (dr1==dr2) goto nochange; break;
+       case DOP_OR:    tmp=0x0b; if (dr1==dr2) goto nochange; break;
+       case DOP_TEST:  tmp=0x85; goto nochange;
+       case DOP_MOV:   if (dr1==dr2) return; tmp=0x8b; break;
+       case DOP_XCHG:
+               dr2->flags|=DYNFLG_CHANGED;
+               if (dword && !((dr1->flags&DYNFLG_HAS8) ^ (dr2->flags&DYNFLG_HAS8))) {
+                       dr1->genreg=gr2;dr1->genreg->dynreg=dr1;
+                       dr2->genreg=gr1;dr2->genreg->dynreg=dr2;
+                       dr1->flags|=DYNFLG_CHANGED;
+                       return;
+               }
+               tmp=0x87;
+               break;
+       default:
+               IllegalOption("gen_dop_word");
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+nochange:
+       if (!dword) cache_addb(0x66);
+       cache_addw(tmp|(0xc0+(gr1->index<<3)+gr2->index)<<8);
+}
+
+static void gen_dop_word_imm(DualOps op,bool dword,DynReg * dr1,Bits imm) {
+       GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV);
+       Bit16u tmp;
+       if (!dword) cache_addb(0x66);
+       switch (op) {
+       case DOP_ADD:   tmp=0xc081; break; 
+       case DOP_ADC:   tmp=0xd081; break;
+       case DOP_SUB:   tmp=0xe881; break;
+       case DOP_SBB:   tmp=0xd881; break;
+       case DOP_CMP:   tmp=0xf881; goto nochange;      //Doesn't change
+       case DOP_XOR:   tmp=0xf081; break;
+       case DOP_AND:   tmp=0xe081; break;
+       case DOP_OR:    tmp=0xc881; break;
+       case DOP_TEST:  tmp=0xc0f7; goto nochange;      //Doesn't change
+       case DOP_MOV:   cache_addb(0xb8+(gr1->index)); dr1->flags|=DYNFLG_CHANGED; goto finish;
+       default:
+               IllegalOption("gen_dop_word_imm");
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+nochange:
+       cache_addw(tmp+(gr1->index<<8));
+finish:
+       if (dword) cache_addd(imm);
+       else cache_addw(imm);
+}
+
+static void gen_dop_word_imm_mem(DualOps op,bool dword,DynReg * dr1,void* data) {
+       GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV);
+       Bit16u tmp;
+       switch (op) {
+       case DOP_ADD:   tmp=0x0503; break; 
+       case DOP_ADC:   tmp=0x0513; break;
+       case DOP_SUB:   tmp=0x052b; break;
+       case DOP_SBB:   tmp=0x051b; break;
+       case DOP_CMP:   tmp=0x053b; goto nochange;      //Doesn't change
+       case DOP_XOR:   tmp=0x0533; break;
+       case DOP_AND:   tmp=0x0523; break;
+       case DOP_OR:    tmp=0x050b; break;
+       case DOP_TEST:  tmp=0x0585; goto nochange;      //Doesn't change
+       case DOP_MOV:
+               gen_mov_host(data,dr1,dword?4:2);
+               dr1->flags|=DYNFLG_CHANGED;
+               return;
+       default:
+               IllegalOption("gen_dop_word_imm_mem");
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+nochange:
+       if (!dword) cache_addb(0x66);
+       cache_addw(tmp+(gr1->index<<11));
+       cache_addd((Bit32u)data);
+}
+
+static void gen_dop_word_var(DualOps op,bool dword,DynReg * dr1,void* drd) {
+       GenReg * gr1=FindDynReg(dr1,dword && op==DOP_MOV);
+       Bit8u tmp;
+       switch (op) {
+       case DOP_ADD:   tmp=0x03; break;
+       case DOP_ADC:   tmp=0x13; break;
+       case DOP_SUB:   tmp=0x2b; break;
+       case DOP_SBB:   tmp=0x1b; break;
+       case DOP_CMP:   tmp=0x3b; break;
+       case DOP_XOR:   tmp=0x33; break;
+       case DOP_AND:   tmp=0x23; break;
+       case DOP_OR:    tmp=0x0b; break;
+       case DOP_TEST:  tmp=0x85; break;
+       case DOP_MOV:   tmp=0x8b; break;
+       case DOP_XCHG:  tmp=0x87; break;
+       default:
+               IllegalOption("gen_dop_word_var");
+       }
+       if (!dword) cache_addb(0x66);
+       cache_addw(tmp|(0x05+((gr1->index)<<3))<<8);
+       cache_addd((Bit32u)drd);
+}
+
+static void gen_imul_word(bool dword,DynReg * dr1,DynReg * dr2) {
+       GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2);
+       dr1->flags|=DYNFLG_CHANGED;
+       if (!dword) {
+               cache_addd(0xaf0f66|(0xc0+(gr1->index<<3)+gr2->index)<<24);
+       } else {
+               cache_addw(0xaf0f);
+               cache_addb(0xc0+(gr1->index<<3)+gr2->index);
+       }
+}
+
+static void gen_imul_word_imm(bool dword,DynReg * dr1,DynReg * dr2,Bits imm) {
+       GenReg * gr1=FindDynReg(dr1);GenReg * gr2=FindDynReg(dr2);
+       if (!dword) cache_addb(0x66);
+       if ((imm>=-128 && imm<=127)) {
+               cache_addb(0x6b);
+               cache_addb(0xc0+(gr1->index<<3)+gr2->index);
+               cache_addb(imm);
+       } else {
+               cache_addb(0x69);
+               cache_addb(0xc0+(gr1->index<<3)+gr2->index);
+               if (dword) cache_addd(imm);
+               else cache_addw(imm);
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+
+static void gen_sop_word(SingleOps op,bool dword,DynReg * dr1) {
+       GenReg * gr1=FindDynReg(dr1);
+       if (!dword) cache_addb(0x66);
+       switch (op) {
+       case SOP_INC:cache_addb(0x40+gr1->index);break;
+       case SOP_DEC:cache_addb(0x48+gr1->index);break;
+       case SOP_NOT:cache_addw(0xd0f7+(gr1->index<<8));break;
+       case SOP_NEG:cache_addw(0xd8f7+(gr1->index<<8));break;
+       default:
+               IllegalOption("gen_sop_word");
+       }
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_shift_byte_cl(Bitu op,DynReg * dr1,Bit8u di1,DynReg * drecx) {
+       ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
+       GenReg * gr1=FindDynReg(dr1);
+       cache_addw(0xc0d2+(((Bit16u)op) << 11)+ ((gr1->index+di1)<<8));
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_shift_byte_imm(Bitu op,DynReg * dr1,Bit8u di1,Bit8u imm) {
+       GenReg * gr1=FindDynReg(dr1);
+       cache_addw(0xc0c0+(((Bit16u)op) << 11) + ((gr1->index+di1)<<8));
+       cache_addb(imm);
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_shift_word_cl(Bitu op,bool dword,DynReg * dr1,DynReg * drecx) {
+       ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
+       GenReg * gr1=FindDynReg(dr1);
+       if (!dword) cache_addb(0x66);
+       cache_addw(0xc0d3+(((Bit16u)op) << 11) + ((gr1->index)<<8));
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_shift_word_imm(Bitu op,bool dword,DynReg * dr1,Bit8u imm) {
+       GenReg * gr1=FindDynReg(dr1);
+       dr1->flags|=DYNFLG_CHANGED;
+       if (!dword) {
+               cache_addd(0x66|((0xc0c1+((Bit16u)op << 11) + (gr1->index<<8))|imm<<16)<<8);
+       } else { 
+               cache_addw(0xc0c1+((Bit16u)op << 11) + (gr1->index<<8));
+               cache_addb(imm);
+       }
+}
+
+static void gen_cbw(bool dword,DynReg * dyn_ax) {
+       ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax);
+       if (!dword) cache_addb(0x66);
+       cache_addb(0x98);
+       dyn_ax->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_cwd(bool dword,DynReg * dyn_ax,DynReg * dyn_dx) {
+       ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax);
+       ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx);
+       dyn_ax->flags|=DYNFLG_CHANGED;
+       dyn_dx->flags|=DYNFLG_CHANGED;
+       if (!dword) cache_addw(0x9966);
+       else cache_addb(0x99);
+}
+
+static void gen_mul_byte(bool imul,DynReg * dyn_ax,DynReg * dr1,Bit8u di1) {
+       ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax);
+       GenReg * gr1=FindDynReg(dr1);
+       if (imul) cache_addw(0xe8f6+((gr1->index+di1)<<8));
+       else cache_addw(0xe0f6+((gr1->index+di1)<<8));
+       dyn_ax->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_mul_word(bool imul,DynReg * dyn_ax,DynReg * dyn_dx,bool dword,DynReg * dr1) {
+       ForceDynReg(x86gen.regs[X86_REG_EAX],dyn_ax);
+       ForceDynReg(x86gen.regs[X86_REG_EDX],dyn_dx);
+       GenReg * gr1=FindDynReg(dr1);
+       if (!dword) cache_addb(0x66);
+       if (imul) cache_addw(0xe8f7+(gr1->index<<8));
+       else cache_addw(0xe0f7+(gr1->index<<8));
+       dyn_ax->flags|=DYNFLG_CHANGED;
+       dyn_dx->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_dshift_imm(bool dword,bool left,DynReg * dr1,DynReg * dr2,Bitu imm) {
+       GenReg * gr1=FindDynReg(dr1);
+       GenReg * gr2=FindDynReg(dr2);
+       if (!dword) cache_addb(0x66);
+       if (left) cache_addw(0xa40f);           //SHLD IMM
+       else  cache_addw(0xac0f);                       //SHRD IMM
+       cache_addb(0xc0+gr1->index+(gr2->index<<3));
+       cache_addb(imm);
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg * drecx) {
+       ForceDynReg(x86gen.regs[X86_REG_ECX],drecx);
+       GenReg * gr1=FindDynReg(dr1);
+       GenReg * gr2=FindDynReg(dr2);
+       if (!dword) cache_addb(0x66);
+       if (left) cache_addw(0xa50f);           //SHLD CL
+       else  cache_addw(0xad0f);                       //SHRD CL
+       cache_addb(0xc0+gr1->index+(gr2->index<<3));
+       dr1->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_call_function(void * func,char const* ops,...) {
+       Bits paramcount=0;
+       bool release_flags=false;
+       struct ParamInfo {
+               const char * line;
+               Bitu value;
+       } pinfo[32];
+       ParamInfo * retparam=0;
+       /* Clear the EAX Genreg for usage */
+       x86gen.regs[X86_REG_EAX]->Clear();
+       x86gen.regs[X86_REG_EAX]->notusable=true;
+       /* Save the flags */
+       if (GCC_UNLIKELY(!skip_flags)) gen_protectflags();
+       /* Scan for the amount of params */
+       if (ops) {
+               va_list params;
+               va_start(params,ops);
+#if defined (MACOSX)
+               Bitu stack_used=0;
+               bool free_flags=false;
+#endif
+               Bits pindex=0;
+               while (*ops) {
+                       if (*ops=='%') {
+                               pinfo[pindex].line=ops+1;
+                               pinfo[pindex].value=va_arg(params,Bitu);
+#if defined (MACOSX)
+                               const char * scan=pinfo[pindex].line;
+                               if ((*scan=='I') || (*scan=='D')) stack_used+=4;
+                               else if (*scan=='F') free_flags=true;
+#endif
+                               pindex++;
+                       }
+                       ops++;
+               }
+
+#if defined (MACOSX)
+               /* align stack */
+               stack_used+=4;                  // saving esp on stack as well
+
+               cache_addw(0xc48b);             // mov eax,esp
+               cache_addb(0x2d);               // sub eax,stack_used
+               cache_addd(stack_used);
+               cache_addw(0xe083);             // and eax,0xfffffff0
+               cache_addb(0xf0);
+               cache_addb(0x05);               // sub eax,stack_used
+               cache_addd(stack_used);
+               cache_addb(0x94);               // xchg eax,esp
+               if (free_flags) {
+                       cache_addw(0xc083);     // add eax,4
+                       cache_addb(0x04);
+               }
+               cache_addb(0x50);               // push eax (==old esp)
+#endif
+
+               paramcount=0;
+               while (pindex) {
+                       pindex--;
+                       const char * scan=pinfo[pindex].line;
+                       switch (*scan++) {
+                       case 'I':                               /* immediate value */
+                               paramcount++;
+                               cache_addb(0x68);                       //Push immediate
+                               cache_addd(pinfo[pindex].value);        //Push value
+                               break;
+                       case 'D':                               /* Dynamic register */
+                               {
+                                       bool release=false;
+                                       paramcount++;
+                                       DynReg * dynreg=(DynReg *)pinfo[pindex].value;
+                                       GenReg * genreg=FindDynReg(dynreg);
+                                       scanagain:
+                                       switch (*scan++) {
+                                       case 'd':
+                                               cache_addb(0x50+genreg->index);         //Push reg
+                                               break;
+                                       case 'w':
+                                               cache_addw(0xb70f);                                     //MOVZX EAX,reg
+                                               cache_addb(0xc0+genreg->index);
+                                               cache_addb(0x50);                                       //Push EAX
+                                               break;
+                                       case 'l':
+                                               cache_addw(0xb60f);                                     //MOVZX EAX,reg[0]
+                                               cache_addb(0xc0+genreg->index);
+                                               cache_addb(0x50);                                       //Push EAX
+                                               break;
+                                       case 'h':
+                                               cache_addw(0xb60f);                                     //MOVZX EAX,reg[1]
+                                               cache_addb(0xc4+genreg->index);
+                                               cache_addb(0x50);                                       //Push EAX
+                                               break;
+                                       case 'r':                                                               /* release the reg afterwards */
+                                               release=true;
+                                               goto scanagain;
+                                       default:
+                                               IllegalOption("gen_call_function param:DREG");
+                                       }
+                                       if (release) gen_releasereg(dynreg);
+                               }
+                               break;
+                       case 'R':                               /* Dynamic register to get the return value */
+                               retparam =&pinfo[pindex];
+                               pinfo[pindex].line=scan;
+                               break;
+                       case 'F':                               /* Release flags from stack */
+                               release_flags=true;
+                               break;
+                       default:
+                               IllegalOption("gen_call_function unknown param");
+                       }
+               }
+#if defined (MACOSX)
+               if (free_flags) release_flags=false;
+       } else {
+               /* align stack */
+               Bit32u stack_used=8;    // saving esp and return address on the stack
+
+               cache_addw(0xc48b);             // mov eax,esp
+               cache_addb(0x2d);               // sub eax,stack_used
+               cache_addd(stack_used);
+               cache_addw(0xe083);             // and eax,0xfffffff0
+               cache_addb(0xf0);
+               cache_addb(0x05);               // sub eax,stack_used
+               cache_addd(stack_used);
+               cache_addb(0x94);               // xchg eax,esp
+               cache_addb(0x50);               // push esp (==old esp)
+#endif
+       }
+
+       /* Clear some unprotected registers */
+       x86gen.regs[X86_REG_ECX]->Clear();
+       x86gen.regs[X86_REG_EDX]->Clear();
+       /* Do the actual call to the procedure */
+       cache_addb(0xe8);
+       cache_addd((Bit32u)func - (Bit32u)cache.pos-4);
+       /* Restore the params of the stack */
+       if (paramcount) {
+               cache_addw(0xc483);                             //add ESP,imm byte
+               cache_addb(paramcount*4+(release_flags?4:0));
+       } else if (release_flags) {
+               cache_addw(0xc483);                             //add ESP,imm byte
+               cache_addb(4);
+       }
+       /* Save the return value in correct register */
+       if (retparam) {
+               DynReg * dynreg=(DynReg *)retparam->value;
+               GenReg * genreg=FindDynReg(dynreg);
+               if (genreg->index)              // test for (e)ax/al
+               switch (*retparam->line) {
+               case 'd':
+                       cache_addw(0xc08b+(genreg->index <<(8+3)));     //mov reg,eax
+                       break;
+               case 'w':
+                       cache_addb(0x66);                                                       
+                       cache_addw(0xc08b+(genreg->index <<(8+3)));     //mov reg,eax
+                       break;
+               case 'l':
+                       cache_addw(0xc08a+(genreg->index <<(8+3)));     //mov reg,eax
+                       break;
+               case 'h':
+                       cache_addw(0xc08a+((genreg->index+4) <<(8+3))); //mov reg,eax
+                       break;
+               }
+               dynreg->flags|=DYNFLG_CHANGED;
+       }
+       /* Restore EAX registers to be used again */
+       x86gen.regs[X86_REG_EAX]->notusable=false;
+
+#if defined (MACOSX)
+       /* restore stack */
+       cache_addb(0x5c);       // pop esp
+#endif
+}
+
+static void gen_call_write(DynReg * dr,Bit32u val,Bitu write_size) {
+       /* Clear the EAX Genreg for usage */
+       x86gen.regs[X86_REG_EAX]->Clear();
+       x86gen.regs[X86_REG_EAX]->notusable=true;
+       gen_protectflags();
+
+#if defined (MACOSX)
+       /* align stack */
+       Bitu stack_used=12;
+
+       cache_addw(0xc48b);             // mov eax,esp
+       cache_addb(0x2d);               // sub eax,stack_used
+       cache_addd(stack_used);
+       cache_addw(0xe083);             // and eax,0xfffffff0
+       cache_addb(0xf0);
+       cache_addb(0x05);               // sub eax,stack_used
+       cache_addd(stack_used);
+       cache_addb(0x94);               // xchg eax,esp
+       cache_addb(0x50);               // push eax (==old esp)
+#endif
+
+       cache_addb(0x68);       //PUSH val
+       cache_addd(val);
+       GenReg * genreg=FindDynReg(dr);
+       cache_addb(0x50+genreg->index);         //PUSH reg
+
+       /* Clear some unprotected registers */
+       x86gen.regs[X86_REG_ECX]->Clear();
+       x86gen.regs[X86_REG_EDX]->Clear();
+       /* Do the actual call to the procedure */
+       cache_addb(0xe8);
+       switch (write_size) {
+               case 1: cache_addd((Bit32u)mem_writeb_checked - (Bit32u)cache.pos-4); break;
+               case 2: cache_addd((Bit32u)mem_writew_checked - (Bit32u)cache.pos-4); break;
+               case 4: cache_addd((Bit32u)mem_writed_checked - (Bit32u)cache.pos-4); break;
+               default: IllegalOption("gen_call_write");
+       }
+
+       cache_addw(0xc483);             //ADD ESP,8
+       cache_addb(2*4);
+       x86gen.regs[X86_REG_EAX]->notusable=false;
+       gen_releasereg(dr);
+
+#if defined (MACOSX)
+       /* restore stack */
+       cache_addb(0x5c);       // pop esp
+#endif
+}
+
+static Bit8u * gen_create_branch(BranchTypes type) {
+       /* First free all registers */
+       cache_addw(0x70+type);
+       return (cache.pos-1);
+}
+
+static void gen_fill_branch(Bit8u * data,Bit8u * from=cache.pos) {
+#if C_DEBUG
+       Bits len=from-data;
+       if (len<0) len=-len;
+       if (len>126) LOG_MSG("Big jump %d",len);
+#endif
+       *data=(from-data-1);
+}
+
+static Bit8u * gen_create_branch_long(BranchTypes type) {
+       cache_addw(0x800f+(type<<8));
+       cache_addd(0);
+       return (cache.pos-4);
+}
+
+static void gen_fill_branch_long(Bit8u * data,Bit8u * from=cache.pos) {
+       *(Bit32u*)data=(from-data-4);
+}
+
+static Bit8u * gen_create_jump(Bit8u * to=0) {
+       /* First free all registers */
+       cache_addb(0xe9);
+       cache_addd(to-(cache.pos+4));
+       return (cache.pos-4);
+}
+
+static void gen_fill_jump(Bit8u * data,Bit8u * to=cache.pos) {
+       *(Bit32u*)data=(to-data-4);
+}
+
+
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       cache_addb(0xa1);
+       cache_addd((Bit32u)ptr);
+       cache_addb(0xff);               //JMP EA
+       if (!imm) {                     //NO EBP
+               cache_addb(0x20);
+    } else if ((imm>=-128 && imm<=127)) {
+               cache_addb(0x60);
+               cache_addb(imm);
+       } else {
+               cache_addb(0xa0);
+               cache_addd(imm);
+       }
+}
+
+static void gen_save_flags(DynReg * dynreg) {
+       if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_save_flags");
+       GenReg * genreg=FindDynReg(dynreg);
+       cache_addb(0x8b);                                       //MOV REG,[esp]
+       cache_addw(0x2404+(genreg->index << 3));
+       dynreg->flags|=DYNFLG_CHANGED;
+}
+
+static void gen_load_flags(DynReg * dynreg) {
+       if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_load_flags");
+       cache_addw(0xc483);                             //ADD ESP,4
+       cache_addb(0x4);
+       GenReg * genreg=FindDynReg(dynreg);
+       cache_addb(0x50+genreg->index);         //PUSH 32
+}
+
+static void gen_save_host_direct(void * data,Bits imm) {
+       cache_addw(0x05c7);             //MOV [],dword
+       cache_addd((Bit32u)data);
+       cache_addd(imm);
+}
+
+static void gen_return(BlockReturn retcode) {
+       gen_protectflags();
+       cache_addb(0x59);                       //POP ECX, the flags
+       if (retcode==0) cache_addw(0xc033);             //MOV EAX, 0
+       else {
+               cache_addb(0xb8);               //MOV EAX, retcode
+               cache_addd(retcode);
+       }
+       cache_addb(0xc3);                       //RET
+}
+
+static void gen_return_fast(BlockReturn retcode,bool ret_exception=false) {
+       if (GCC_UNLIKELY(x86gen.flagsactive)) IllegalOption("gen_return_fast");
+       cache_addw(0x0d8b);                     //MOV ECX, the flags
+       cache_addd((Bit32u)&cpu_regs.flags);
+       if (!ret_exception) {
+               cache_addw(0xc483);                     //ADD ESP,4
+               cache_addb(0x4);
+               if (retcode==0) cache_addw(0xc033);             //MOV EAX, 0
+               else {
+                       cache_addb(0xb8);               //MOV EAX, retcode
+                       cache_addd(retcode);
+               }
+       }
+       cache_addb(0xc3);                       //RET
+}
+
+static void gen_init(void) {
+       x86gen.regs[X86_REG_EAX]=new GenReg(0);
+       x86gen.regs[X86_REG_ECX]=new GenReg(1);
+       x86gen.regs[X86_REG_EDX]=new GenReg(2);
+       x86gen.regs[X86_REG_EBX]=new GenReg(3);
+       x86gen.regs[X86_REG_EBP]=new GenReg(5);
+       x86gen.regs[X86_REG_ESI]=new GenReg(6);
+       x86gen.regs[X86_REG_EDI]=new GenReg(7);
+}
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/string.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dyn_x86/string.h
new file mode 100644 (file)
index 0000000..93f69e4
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+enum STRING_OP {
+       STR_OUTSB=0,STR_OUTSW,STR_OUTSD,
+       STR_INSB=4,STR_INSW,STR_INSD,
+       STR_MOVSB=8,STR_MOVSW,STR_MOVSD,
+       STR_LODSB=12,STR_LODSW,STR_LODSD,
+       STR_STOSB=16,STR_STOSW,STR_STOSD,
+       STR_SCASB=20,STR_SCASW,STR_SCASD,
+       STR_CMPSB=24,STR_CMPSW,STR_CMPSD
+};
+
+static void dyn_string(STRING_OP op) {
+       DynReg * si_base=decode.segprefix ? decode.segprefix : DREG(DS);
+       DynReg * di_base=DREG(ES);
+       DynReg * tmp_reg;bool usesi;bool usedi;
+       gen_protectflags();
+       if (decode.rep) {
+               gen_dop_word_imm(DOP_SUB,true,DREG(CYCLES),decode.cycles);
+               gen_releasereg(DREG(CYCLES));
+               decode.cycles=0;
+       }
+       /* Check what each string operation will be using */
+       switch (op) {
+       case STR_MOVSB: case STR_MOVSW: case STR_MOVSD:
+       case STR_CMPSB: case STR_CMPSW: case STR_CMPSD:
+               tmp_reg=DREG(TMPB);usesi=true;usedi=true;break;
+       case STR_LODSB: case STR_LODSW: case STR_LODSD:
+               tmp_reg=DREG(EAX);usesi=true;usedi=false;break;
+       case STR_OUTSB: case STR_OUTSW: case STR_OUTSD:
+               tmp_reg=DREG(TMPB);usesi=true;usedi=false;break;
+       case STR_SCASB: case STR_SCASW: case STR_SCASD:
+       case STR_STOSB: case STR_STOSW: case STR_STOSD:
+               tmp_reg=DREG(EAX);usesi=false;usedi=true;break;
+       case STR_INSB:  case STR_INSW:  case STR_INSD:
+               tmp_reg=DREG(TMPB);usesi=false;usedi=true;break;
+       default:
+               IllegalOption("dyn_string op");
+       }
+       gen_load_host(&cpu.direction,DREG(TMPW),4);
+       switch (op & 3) {
+       case 0:break;
+       case 1:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),1);break;
+       case 2:gen_shift_word_imm(SHIFT_SHL,true,DREG(TMPW),2);break;
+       default:
+               IllegalOption("dyn_string shift");
+
+       }
+       if (usesi) {
+               gen_preloadreg(DREG(ESI));
+               DynRegs[G_ESI].flags|=DYNFLG_CHANGED;
+               gen_preloadreg(si_base);
+       }
+       if (usedi) {
+               gen_preloadreg(DREG(EDI));
+               DynRegs[G_EDI].flags|=DYNFLG_CHANGED;
+               gen_preloadreg(di_base);
+       }
+       if (decode.rep) {
+               gen_preloadreg(DREG(ECX));
+               DynRegs[G_ECX].flags|=DYNFLG_CHANGED;
+       }
+       DynState rep_state;
+       dyn_savestate(&rep_state);
+       Bit8u * rep_start=cache.pos;
+       Bit8u * rep_ecx_jmp;
+       /* Check if ECX!=zero */
+       if (decode.rep) {
+               gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
+               rep_ecx_jmp=gen_create_branch_long(BR_Z);
+       }
+       if (usesi) {
+               if (!decode.big_addr) {
+                       gen_extend_word(false,DREG(EA),DREG(ESI));
+                       gen_lea(DREG(EA),si_base,DREG(EA),0,0);
+               } else {
+                       gen_lea(DREG(EA),si_base,DREG(ESI),0,0);
+               }
+               switch (op&3) {
+               case 0:dyn_read_byte(DREG(EA),tmp_reg,false);break;
+               case 1:dyn_read_word(DREG(EA),tmp_reg,false);break;
+               case 2:dyn_read_word(DREG(EA),tmp_reg,true);break;
+               }
+               switch (op) {
+               case STR_OUTSB:
+                       gen_call_function((void*)&IO_WriteB,"%Id%Dl",DREG(EDX),tmp_reg);break;
+               case STR_OUTSW:
+                       gen_call_function((void*)&IO_WriteW,"%Id%Dw",DREG(EDX),tmp_reg);break;
+               case STR_OUTSD:
+                       gen_call_function((void*)&IO_WriteD,"%Id%Dd",DREG(EDX),tmp_reg);break;
+               }
+       }
+       if (usedi) {
+               if (!decode.big_addr) {
+                       gen_extend_word(false,DREG(EA),DREG(EDI));
+                       gen_lea(DREG(EA),di_base,DREG(EA),0,0);
+               } else {
+                       gen_lea(DREG(EA),di_base,DREG(EDI),0,0);
+               }
+               /* Maybe something special to be done to fill the value */
+               switch (op) {
+               case STR_INSB:
+                       gen_call_function((void*)&IO_ReadB,"%Dw%Rl",DREG(EDX),tmp_reg);
+               case STR_MOVSB:
+               case STR_STOSB:
+                       dyn_write_byte(DREG(EA),tmp_reg,false);
+                       break;
+               case STR_INSW:
+                       gen_call_function((void*)&IO_ReadW,"%Dw%Rw",DREG(EDX),tmp_reg);
+               case STR_MOVSW:
+               case STR_STOSW:
+                       dyn_write_word(DREG(EA),tmp_reg,false);
+                       break;
+               case STR_INSD:
+                       gen_call_function((void*)&IO_ReadD,"%Dw%Rd",DREG(EDX),tmp_reg);
+               case STR_MOVSD:
+               case STR_STOSD:
+                       dyn_write_word(DREG(EA),tmp_reg,true);
+                       break;
+               default:
+                       IllegalOption("dyn_string op");
+               }
+       }
+       gen_releasereg(DREG(EA));gen_releasereg(DREG(TMPB));
+
+       /* update registers */
+       if (usesi) gen_dop_word(DOP_ADD,decode.big_addr,DREG(ESI),DREG(TMPW));
+       if (usedi) gen_dop_word(DOP_ADD,decode.big_addr,DREG(EDI),DREG(TMPW));
+
+       if (decode.rep) {
+               gen_sop_word(SOP_DEC,decode.big_addr,DREG(ECX));
+               gen_sop_word(SOP_DEC,true,DREG(CYCLES));
+               gen_releasereg(DREG(CYCLES));
+               dyn_savestate(&save_info[used_save_info].state);
+               save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE);
+               save_info[used_save_info].eip_change=decode.op_start-decode.code_start;
+               save_info[used_save_info].type=normal;
+               used_save_info++;
+
+               /* Jump back to start of ECX check */
+               dyn_synchstate(&rep_state);
+               gen_create_jump(rep_start);
+
+               dyn_loadstate(&rep_state);
+               gen_fill_branch_long(rep_ecx_jmp);
+       }
+       gen_releasereg(DREG(TMPW));
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec.cpp
new file mode 100644 (file)
index 0000000..1571fb4
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include "dosbox.h"
+
+#if (C_DYNREC)
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#if defined (WIN32)
+#include <windows.h>
+#include <winbase.h>
+#endif
+
+#if (C_HAVE_MPROTECT)
+#include <sys/mman.h>
+
+#include <limits.h>
+#ifndef PAGESIZE
+#define PAGESIZE 4096
+#endif
+#endif /* C_HAVE_MPROTECT */
+
+#include "callback.h"
+#include "regs.h"
+#include "mem.h"
+#include "cpu.h"
+#include "debug.h"
+#include "paging.h"
+#include "inout.h"
+#include "lazyflags.h"
+#include "pic.h"
+
+#define CACHE_MAXSIZE  (4096*2)
+#define CACHE_TOTAL            (1024*1024*8)
+#define CACHE_PAGES            (512)
+#define CACHE_BLOCKS   (128*1024)
+#define CACHE_ALIGN            (16)
+#define DYN_HASH_SHIFT (4)
+#define DYN_PAGE_HASH  (4096>>DYN_HASH_SHIFT)
+#define DYN_LINKS              (16)
+
+
+//#define DYN_LOG 1 //Turn Logging on.
+
+
+#if C_FPU
+#define CPU_FPU 1                                               //Enable FPU escape instructions
+#endif
+
+
+// the emulated x86 registers
+#define DRC_REG_EAX 0
+#define DRC_REG_ECX 1
+#define DRC_REG_EDX 2
+#define DRC_REG_EBX 3
+#define DRC_REG_ESP 4
+#define DRC_REG_EBP 5
+#define DRC_REG_ESI 6
+#define DRC_REG_EDI 7
+
+// the emulated x86 segment registers
+#define DRC_SEG_ES 0
+#define DRC_SEG_CS 1
+#define DRC_SEG_SS 2
+#define DRC_SEG_DS 3
+#define DRC_SEG_FS 4
+#define DRC_SEG_GS 5
+
+
+// access to a general register
+#define DRCD_REG_VAL(reg) (&cpu_regs.regs[reg].dword)
+// access to a segment register
+#define DRCD_SEG_VAL(seg) (&Segs.val[seg])
+// access to the physical value of a segment register/selector
+#define DRCD_SEG_PHYS(seg) (&Segs.phys[seg])
+
+// access to an 8bit general register
+#define DRCD_REG_BYTE(reg,idx) (&cpu_regs.regs[reg].byte[idx?BH_INDEX:BL_INDEX])
+// access to  16/32bit general registers
+#define DRCD_REG_WORD(reg,dwrd) ((dwrd)?((void*)(&cpu_regs.regs[reg].dword[DW_INDEX])):((void*)(&cpu_regs.regs[reg].word[W_INDEX])))
+
+
+enum BlockReturn {
+       BR_Normal=0,
+       BR_Cycles,
+       BR_Link1,BR_Link2,
+       BR_Opcode,
+#if (C_DEBUG)
+       BR_OpcodeFull,
+#endif
+       BR_Iret,
+       BR_CallBack,
+       BR_SMCBlock
+};
+
+// identificator to signal self-modification of the currently executed block
+#define SMC_CURRENT_BLOCK      0xffff
+
+
+static void IllegalOptionDynrec(const char* msg) {
+       E_Exit("DynrecCore: illegal option in %s",msg);
+}
+
+static struct {
+       BlockReturn (*runcode)(Bit8u*);         // points to code that can start a block
+       Bitu callback;                          // the occurred callback
+       Bitu readdata;                          // spare space used when reading from memory
+       Bit32u protected_regs[8];       // space to save/restore register values
+} core_dynrec;
+
+
+#include "core_dynrec/cache.h"
+
+#define X86                    0x01
+#define X86_64         0x02
+#define MIPSEL         0x03
+#define ARMV4LE                0x04
+#define ARMV7LE                0x05
+#define POWERPC                0x04
+
+#if C_TARGETCPU == X86_64
+#include "core_dynrec/risc_x64.h"
+#elif C_TARGETCPU == X86
+#include "core_dynrec/risc_x86.h"
+#elif C_TARGETCPU == MIPSEL
+#include "core_dynrec/risc_mipsel32.h"
+#elif (C_TARGETCPU == ARMV4LE) || (C_TARGETCPU == ARMV7LE)
+#include "core_dynrec/risc_armv4le.h"
+#elif C_TARGETCPU == POWERPC
+#include "core_dynrec/risc_ppc.h"
+#endif
+
+#include "core_dynrec/decoder.h"
+
+CacheBlockDynRec * LinkBlocks(BlockReturn ret) {
+       CacheBlockDynRec * block=NULL;
+       // the last instruction was a control flow modifying instruction
+       Bitu temp_ip=SegPhys(cs)+reg_eip;
+       CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)get_tlb_readhandler(temp_ip);
+       if (temp_handler->flags & PFLAG_HASCODE) {
+               // see if the target is an already translated block
+               block=temp_handler->FindCacheBlock(temp_ip & 4095);
+               if (!block) return NULL;
+
+               // found it, link the current block to
+               cache.block.running->LinkTo(ret==BR_Link2,block);
+               return block;
+       }
+       return NULL;
+}
+
+/*
+       The core tries to find the block that should be executed next.
+       If such a block is found, it is run, otherwise the instruction
+       stream starting at ip_point is translated (see decoder.h) and
+       makes up a new code block that will be run.
+       When control is returned to CPU_Core_Dynrec_Run (which might
+       be right after the block is run, or somewhen long after that
+       due to the direct cacheblock linking) the returncode decides
+       the next action. This might be continuing the translation and
+       execution process, or returning from the core etc.
+*/
+
+Bits CPU_Core_Dynrec_Run(void) {
+       for (;;) {
+               // Determine the linear address of CS:EIP
+               PhysPt ip_point=SegPhys(cs)+reg_eip;
+               #if C_HEAVY_DEBUG
+                       if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
+               #endif
+
+               CodePageHandlerDynRec * chandler=0;
+               // see if the current page is present and contains code
+               if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) {
+                       // page not present, throw the exception
+                       CPU_Exception(cpu.exception.which,cpu.exception.error);
+                       continue;
+               }
+
+               // page doesn't contain code or is special
+               if (GCC_UNLIKELY(!chandler)) return CPU_Core_Normal_Run();
+
+               // find correct Dynamic Block to run
+               CacheBlockDynRec * block=chandler->FindCacheBlock(ip_point&4095);
+               if (!block) {
+                       // no block found, thus translate the instruction stream
+                       // unless the instruction is known to be modified
+                       if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) {
+                               // translate up to 32 instructions
+                               block=CreateCacheBlock(chandler,ip_point,32);
+                       } else {
+                               // let the normal core handle this instruction to avoid zero-sized blocks
+                               Bitu old_cycles=CPU_Cycles;
+                               CPU_Cycles=1;
+                               Bits nc_retcode=CPU_Core_Normal_Run();
+                               if (!nc_retcode) {
+                                       CPU_Cycles=old_cycles-1;
+                                       continue;
+                               }
+                               CPU_CycleLeft+=old_cycles;
+                               return nc_retcode;
+                       }
+               }
+
+run_block:
+               cache.block.running=0;
+               // now we're ready to run the dynamic code block
+//             BlockReturn ret=((BlockReturn (*)(void))(block->cache.start))();
+               BlockReturn ret=core_dynrec.runcode(block->cache.start);
+
+               switch (ret) {
+               case BR_Iret:
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+                       if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
+#endif
+#endif
+                       if (!GETFLAG(TF)) {
+                               if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
+                               break;
+                       }
+                       // trapflag is set, switch to the trap-aware decoder
+                       cpudecoder=CPU_Core_Dynrec_Trap_Run;
+                       return CBRET_NONE;
+
+               case BR_Normal:
+                       // the block was exited due to a non-predictable control flow
+                       // modifying instruction (like ret) or some nontrivial cpu state
+                       // changing instruction (for example switch to/from pmode),
+                       // or the maximum number of instructions to translate was reached
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+                       if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
+#endif
+#endif
+                       break;
+
+               case BR_Cycles:
+                       // cycles went negative, return from the core to handle
+                       // external events, schedule the pic...
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+                       if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
+#endif
+#endif
+                       return CBRET_NONE;
+
+               case BR_CallBack:
+                       // the callback code is executed in dosbox.conf, return the callback number
+                       FillFlags();
+                       return core_dynrec.callback;
+
+               case BR_SMCBlock:
+//                     LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip);
+                       cpu.exception.which=0;
+                       // fallthrough, let the normal core handle the block-modifying instruction
+               case BR_Opcode:
+                       // some instruction has been encountered that could not be translated
+                       // (thus it is not part of the code block), the normal core will
+                       // handle this instruction
+                       CPU_CycleLeft+=CPU_Cycles;
+                       CPU_Cycles=1;
+                       return CPU_Core_Normal_Run();
+
+#if (C_DEBUG)
+               case BR_OpcodeFull:
+                       CPU_CycleLeft+=CPU_Cycles;
+                       CPU_Cycles=1;
+                       return CPU_Core_Full_Run();
+#endif
+
+               case BR_Link1:
+               case BR_Link2:
+                       block=LinkBlocks(ret);
+                       if (block) goto run_block;
+                       break;
+
+               default:
+                       E_Exit("Invalid return code %d", ret);
+               }
+       }
+       return CBRET_NONE;
+}
+
+Bits CPU_Core_Dynrec_Trap_Run(void) {
+       Bits oldCycles = CPU_Cycles;
+       CPU_Cycles = 1;
+       cpu.trap_skip = false;
+
+       // let the normal core execute the next (only one!) instruction
+       Bits ret=CPU_Core_Normal_Run();
+
+       // trap to int1 unless the last instruction deferred this
+       // (allows hardware interrupts to be served without interaction)
+       if (!cpu.trap_skip) CPU_HW_Interrupt(1);
+
+       CPU_Cycles = oldCycles-1;
+       // continue (either the trapflag was clear anyways, or the int1 cleared it)
+       cpudecoder = &CPU_Core_Dynrec_Run;
+
+       return ret;
+}
+
+void CPU_Core_Dynrec_Init(void) {
+}
+
+void CPU_Core_Dynrec_Cache_Init(bool enable_cache) {
+       // Initialize code cache and dynamic blocks
+       cache_init(enable_cache);
+}
+
+void CPU_Core_Dynrec_Cache_Close(void) {
+       cache_close();
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile
new file mode 100644 (file)
index 0000000..5d16773
--- /dev/null
@@ -0,0 +1,494 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# src/cpu/core_dynrec/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/dosbox
+pkgincludedir = $(includedir)/dosbox
+pkglibdir = $(libdir)/dosbox
+pkglibexecdir = $(libexecdir)/dosbox
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-pc-linux-gnu
+host_triplet = x86_64-pc-linux-gnu
+subdir = src/cpu/core_dynrec
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = aclocal-1.16
+ALSA_CFLAGS = 
+ALSA_LIBS =  -lasound -lm -ldl -lpthread
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AUTOCONF = autoconf
+AUTOHEADER = autoheader
+AUTOMAKE = automake-1.16
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =  -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = 
+LIBOBJS = 
+LIBS = -lasound -lm -ldl -lpthread -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpng -lz -lX11 -lGL
+LTLIBOBJS = 
+MAKEINFO = makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = dosbox
+PACKAGE_BUGREPORT = 
+PACKAGE_NAME = dosbox
+PACKAGE_STRING = dosbox 0.74
+PACKAGE_TARNAME = dosbox
+PACKAGE_URL = 
+PACKAGE_VERSION = 0.74
+PATH_SEPARATOR = :
+RANLIB = ranlib
+SDL_CFLAGS = -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+SDL_CONFIG = /usr/local/bin/sdl-config
+SDL_LIBS = -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpthread
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = 
+VERSION = 0.74
+WINDRES = :
+abs_builddir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_dynrec
+abs_srcdir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_dynrec
+abs_top_builddir = /home/whatisthis/src/DOSVAXJ3
+abs_top_srcdir = /home/whatisthis/src/DOSVAXJ3
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-pc-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-pc-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/whatisthis/src/DOSVAXJ3/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+runstatedir = ${localstatedir}/run
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias = 
+top_build_prefix = ../../../
+top_builddir = ../../..
+top_srcdir = ../../..
+noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \
+                 dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h \
+                 risc_armv4le.h risc_armv4le-common.h \
+                 risc_armv4le-o3.h risc_armv4le-thumb.h \
+                 risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile.am b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile.am
new file mode 100644 (file)
index 0000000..288b915
--- /dev/null
@@ -0,0 +1,5 @@
+noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \
+                 dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h \
+                 risc_armv4le.h risc_armv4le-common.h \
+                 risc_armv4le-o3.h risc_armv4le-thumb.h \
+                 risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile.in b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/Makefile.in
new file mode 100644 (file)
index 0000000..513aafc
--- /dev/null
@@ -0,0 +1,494 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/cpu/core_dynrec
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \
+                 dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h \
+                 risc_armv4le.h risc_armv4le-common.h \
+                 risc_armv4le-o3.h risc_armv4le-thumb.h \
+                 risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/cache.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/cache.h
new file mode 100644 (file)
index 0000000..7d7a6ef
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+class CodePageHandlerDynRec;   // forward
+
+// basic cache block representation
+class CacheBlockDynRec {
+public:
+       void Clear(void);
+       // link this cache block to another block, index specifies the code
+       // path (always zero for unconditional links, 0/1 for conditional ones
+       void LinkTo(Bitu index,CacheBlockDynRec * toblock) {
+               assert(toblock);
+               link[index].to=toblock;
+               link[index].next=toblock->link[index].from;     // set target block
+               toblock->link[index].from=this;                         // remember who links me
+       }
+       struct {
+               Bit16u start,end;               // where in the page is the original code
+               CodePageHandlerDynRec * handler;                        // page containing this code
+       } page;
+       struct {
+               Bit8u * start;                  // where in the cache are we
+               Bitu size;
+               CacheBlockDynRec * next;
+               // writemap masking maskpointer/start/length
+               // to allow holes in the writemap
+               Bit8u * wmapmask;
+               Bit16u maskstart;
+               Bit16u masklen;
+       } cache;
+       struct {
+               Bitu index;
+               CacheBlockDynRec * next;
+       } hash;
+       struct {
+               CacheBlockDynRec * to;          // this block can transfer control to the to-block
+               CacheBlockDynRec * next;
+               CacheBlockDynRec * from;        // the from-block can transfer control to this block
+       } link[2];      // maximum two links (conditional jumps)
+       CacheBlockDynRec * crossblock;
+};
+
+static struct {
+       struct {
+               CacheBlockDynRec * first;               // the first cache block in the list
+               CacheBlockDynRec * active;              // the current cache block
+               CacheBlockDynRec * free;                // pointer to the free list
+               CacheBlockDynRec * running;             // the last block that was entered for execution
+       } block;
+       Bit8u * pos;            // position in the cache block
+       CodePageHandlerDynRec * free_pages;             // pointer to the free list
+       CodePageHandlerDynRec * used_pages;             // pointer to the list of used pages
+       CodePageHandlerDynRec * last_page;              // the last used page
+} cache;
+
+
+// cache memory pointers, to be malloc'd later
+static Bit8u * cache_code_start_ptr=NULL;
+static Bit8u * cache_code=NULL;
+static Bit8u * cache_code_link_blocks=NULL;
+
+static CacheBlockDynRec * cache_blocks=NULL;
+static CacheBlockDynRec link_blocks[2];                // default linking (specially marked)
+
+
+// the CodePageHandlerDynRec class provides access to the contained
+// cache blocks and intercepts writes to the code for special treatment
+class CodePageHandlerDynRec : public PageHandler {
+public:
+       CodePageHandlerDynRec() {
+               invalidation_map=NULL;
+       }
+
+       void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
+               // initialize this codepage handler
+               phys_page=_phys_page;
+               // save the old pagehandler to provide direct read access to the memory,
+               // and to be able to restore it later on
+               old_pagehandler=_old_pagehandler;
+
+               // adjust flags
+               flags=old_pagehandler->flags|PFLAG_HASCODE;
+               flags&=~PFLAG_WRITEABLE;
+
+               active_blocks=0;
+               active_count=16;
+
+               // initialize the maps with zero (no cache blocks as well as code present)
+               memset(&hash_map,0,sizeof(hash_map));
+               memset(&write_map,0,sizeof(write_map));
+               if (invalidation_map!=NULL) {
+                       free(invalidation_map);
+                       invalidation_map=NULL;
+               }
+       }
+
+       // clear out blocks that contain code which has been modified
+       bool InvalidateRange(Bitu start,Bitu end) {
+               Bits index=1+(end>>DYN_HASH_SHIFT);
+               bool is_current_block=false;    // if the current block is modified, it has to be exited as soon as possible
+
+               Bit32u ip_point=SegPhys(cs)+reg_eip;
+               ip_point=(PAGING_GetPhysicalPage(ip_point)-(phys_page<<12))+(ip_point&0xfff);
+               while (index>=0) {
+                       Bitu map=0;
+                       // see if there is still some code in the range
+                       for (Bitu count=start;count<=end;count++) map+=write_map[count];
+                       if (!map) return is_current_block;      // no more code, finished
+
+                       CacheBlockDynRec * block=hash_map[index];
+                       while (block) {
+                               CacheBlockDynRec * nextblock=block->hash.next;
+                               // test if this block is in the range
+                               if (start<=block->page.end && end>=block->page.start) {
+                                       if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true;
+                                       block->Clear();         // clear the block, decrements the write_map accordingly
+                               }
+                               block=nextblock;
+                       }
+                       index--;
+               }
+               return is_current_block;
+       }
+
+       // the following functions will clean all cache blocks that are invalid now due to the write
+       void writeb(PhysPt addr,Bitu val){
+               addr&=4095;
+               if (host_readb(hostmem+addr)==(Bit8u)val) return;
+               host_writeb(hostmem+addr,val);
+               // see if there's code where we are writing to
+               if (!host_readb(&write_map[addr])) {
+                       if (active_blocks) return;              // still some blocks in this page
+                       active_count--;
+                       if (!active_count) Release();   // delay page releasing until active_count is zero
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+               invalidation_map[addr]++;
+               InvalidateRange(addr,addr);
+       }
+       void writew(PhysPt addr,Bitu val){
+               addr&=4095;
+               if (host_readw(hostmem+addr)==(Bit16u)val) return;
+               host_writew(hostmem+addr,val);
+               // see if there's code where we are writing to
+               if (!host_readw(&write_map[addr])) {
+                       if (active_blocks) return;              // still some blocks in this page
+                       active_count--;
+                       if (!active_count) Release();   // delay page releasing until active_count is zero
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
+               host_writew(&invalidation_map[addr],
+                       host_readw(&invalidation_map[addr])+0x101);
+#else
+               (*(Bit16u*)&invalidation_map[addr])+=0x101;
+#endif
+               InvalidateRange(addr,addr+1);
+       }
+       void writed(PhysPt addr,Bitu val){
+               addr&=4095;
+               if (host_readd(hostmem+addr)==(Bit32u)val) return;
+               host_writed(hostmem+addr,val);
+               // see if there's code where we are writing to
+               if (!host_readd(&write_map[addr])) {
+                       if (active_blocks) return;              // still some blocks in this page
+                       active_count--;
+                       if (!active_count) Release();   // delay page releasing until active_count is zero
+                       return;
+               } else if (!invalidation_map) {
+                       invalidation_map=(Bit8u*)malloc(4096);
+                       memset(invalidation_map,0,4096);
+               }
+#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
+               host_writed(&invalidation_map[addr],
+                       host_readd(&invalidation_map[addr])+0x1010101);
+#else
+               (*(Bit32u*)&invalidation_map[addr])+=0x1010101;
+#endif
+               InvalidateRange(addr,addr+3);
+       }
+       bool writeb_checked(PhysPt addr,Bitu val) {
+               addr&=4095;
+               if (host_readb(hostmem+addr)==(Bit8u)val) return false;
+               // see if there's code where we are writing to
+               if (!host_readb(&write_map[addr])) {
+                       if (!active_blocks) {
+                               // no blocks left in this page, still delay the page releasing a bit
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+                       invalidation_map[addr]++;
+                       if (InvalidateRange(addr,addr)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writeb(hostmem+addr,val);
+               return false;
+       }
+       bool writew_checked(PhysPt addr,Bitu val) {
+               addr&=4095;
+               if (host_readw(hostmem+addr)==(Bit16u)val) return false;
+               // see if there's code where we are writing to
+               if (!host_readw(&write_map[addr])) {
+                       if (!active_blocks) {
+                               // no blocks left in this page, still delay the page releasing a bit
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
+                       host_writew(&invalidation_map[addr],
+                               host_readw(&invalidation_map[addr])+0x101);
+#else
+                       (*(Bit16u*)&invalidation_map[addr])+=0x101;
+#endif
+                       if (InvalidateRange(addr,addr+1)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writew(hostmem+addr,val);
+               return false;
+       }
+       bool writed_checked(PhysPt addr,Bitu val) {
+               addr&=4095;
+               if (host_readd(hostmem+addr)==(Bit32u)val) return false;
+               // see if there's code where we are writing to
+               if (!host_readd(&write_map[addr])) {
+                       if (!active_blocks) {
+                               // no blocks left in this page, still delay the page releasing a bit
+                               active_count--;
+                               if (!active_count) Release();
+                       }
+               } else {
+                       if (!invalidation_map) {
+                               invalidation_map=(Bit8u*)malloc(4096);
+                               memset(invalidation_map,0,4096);
+                       }
+#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
+                       host_writed(&invalidation_map[addr],
+                               host_readd(&invalidation_map[addr])+0x1010101);
+#else
+                       (*(Bit32u*)&invalidation_map[addr])+=0x1010101;
+#endif
+                       if (InvalidateRange(addr,addr+3)) {
+                               cpu.exception.which=SMC_CURRENT_BLOCK;
+                               return true;
+                       }
+               }
+               host_writed(hostmem+addr,val);
+               return false;
+       }
+
+    // add a cache block to this page and note it in the hash map
+       void AddCacheBlock(CacheBlockDynRec * block) {
+               Bitu index=1+(block->page.start>>DYN_HASH_SHIFT);
+               block->hash.next=hash_map[index];       // link to old block at index from the new block
+               block->hash.index=index;
+               hash_map[index]=block;                          // put new block at hash position
+               block->page.handler=this;
+               active_blocks++;
+       }
+       // there's a block whose code started in a different page
+    void AddCrossBlock(CacheBlockDynRec * block) {
+               block->hash.next=hash_map[0];
+               block->hash.index=0;
+               hash_map[0]=block;
+               block->page.handler=this;
+               active_blocks++;
+       }
+       // remove a cache block
+       void DelCacheBlock(CacheBlockDynRec * block) {
+               active_blocks--;
+               active_count=16;
+               CacheBlockDynRec * * bwhere=&hash_map[block->hash.index];
+               while (*bwhere!=block) {
+                       bwhere=&((*bwhere)->hash.next);
+                       //Will crash if a block isn't found, which should never happen.
+               }
+               *bwhere=block->hash.next;
+
+               // remove the cleared block from the write map
+               if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) {
+                       // first part is not influenced by the mask
+                       for (Bitu i=block->page.start;i<block->cache.maskstart;i++) {
+                               if (write_map[i]) write_map[i]--;
+                       }
+                       Bitu maskct=0;
+                       // last part sticks to the writemap mask
+                       for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) {
+                               if (write_map[i]) {
+                                       // only adjust writemap if it isn't masked
+                                       if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--;
+                               }
+                       }
+                       free(block->cache.wmapmask);
+                       block->cache.wmapmask=NULL;
+               } else {
+                       for (Bitu i=block->page.start;i<=block->page.end;i++) {
+                               if (write_map[i]) write_map[i]--;
+                       }
+               }
+       }
+
+       void Release(void) {
+               MEM_SetPageHandler(phys_page,1,old_pagehandler);        // revert to old handler
+               PAGING_ClearTLB();
+
+               // remove page from the lists
+               if (prev) prev->next=next;
+               else cache.used_pages=next;
+               if (next) next->prev=prev;
+               else cache.last_page=prev;
+               next=cache.free_pages;
+               cache.free_pages=this;
+               prev=0;
+       }
+       void ClearRelease(void) {
+               // clear out all cache blocks in this page
+               for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) {
+                       CacheBlockDynRec * block=hash_map[index];
+                       while (block) {
+                               CacheBlockDynRec * nextblock=block->hash.next;
+                               block->page.handler=0;                  // no need, full clear
+                               block->Clear();
+                               block=nextblock;
+                       }
+               }
+               Release();      // now can release this page
+       }
+
+       CacheBlockDynRec * FindCacheBlock(Bitu start) {
+               CacheBlockDynRec * block=hash_map[1+(start>>DYN_HASH_SHIFT)];
+               // see if there's a cache block present at the start address
+               while (block) {
+                       if (block->page.start==start) return block;     // found
+                       block=block->hash.next;
+               }
+               return 0;       // none found
+       }
+
+       HostPt GetHostReadPt(Bitu phys_page) { 
+               hostmem=old_pagehandler->GetHostReadPt(phys_page);
+               return hostmem;
+       }
+       HostPt GetHostWritePt(Bitu phys_page) { 
+               return GetHostReadPt( phys_page );
+       }
+public:
+       // the write map, there are write_map[i] cache blocks that cover the byte at address i
+       Bit8u write_map[4096];
+       Bit8u * invalidation_map;
+       CodePageHandlerDynRec * next, * prev;   // page linking
+private:
+       PageHandler * old_pagehandler;
+
+       // hash map to quickly find the cache blocks in this page
+       CacheBlockDynRec * hash_map[1+DYN_PAGE_HASH];
+
+       Bitu active_blocks;             // the number of cache blocks in this page
+       Bitu active_count;              // delaying parameter to not immediately release a page
+       HostPt hostmem; 
+       Bitu phys_page;
+};
+
+
+static INLINE void cache_addunusedblock(CacheBlockDynRec * block) {
+       // block has become unused, add it to the freelist
+       block->cache.next=cache.block.free;
+       cache.block.free=block;
+}
+
+static CacheBlockDynRec * cache_getblock(void) {
+       // get a free cache block and advance the free pointer
+       CacheBlockDynRec * ret=cache.block.free;
+       if (!ret) E_Exit("Ran out of CacheBlocks" );
+       cache.block.free=ret->cache.next;
+       ret->cache.next=0;
+       return ret;
+}
+
+void CacheBlockDynRec::Clear(void) {
+       Bitu ind;
+       // check if this is not a cross page block
+       if (hash.index) for (ind=0;ind<2;ind++) {
+               CacheBlockDynRec * fromlink=link[ind].from;
+               link[ind].from=0;
+               while (fromlink) {
+                       CacheBlockDynRec * nextlink=fromlink->link[ind].next;
+                       // clear the next-link and let the block point to the standard linkcode
+                       fromlink->link[ind].next=0;
+                       fromlink->link[ind].to=&link_blocks[ind];
+
+                       fromlink=nextlink;
+               }
+               if (link[ind].to!=&link_blocks[ind]) {
+                       // not linked to the standard linkcode, find the block that links to this block
+                       CacheBlockDynRec * * wherelink=&link[ind].to->link[ind].from;
+                       while (*wherelink != this && *wherelink) {
+                               wherelink = &(*wherelink)->link[ind].next;
+                       }
+                       // now remove the link
+                       if(*wherelink) 
+                               *wherelink = (*wherelink)->link[ind].next;
+                       else {
+                               LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate");
+                       }
+               }
+       } else 
+               cache_addunusedblock(this);
+       if (crossblock) {
+               // clear out the crossblock (in the page before) as well
+               crossblock->crossblock=0;
+               crossblock->Clear();
+               crossblock=0;
+       }
+       if (page.handler) {
+               // clear out the code page handler
+               page.handler->DelCacheBlock(this);
+               page.handler=0;
+       }
+       if (cache.wmapmask){
+               free(cache.wmapmask);
+               cache.wmapmask=NULL;
+       }
+}
+
+
+static CacheBlockDynRec * cache_openblock(void) {
+       CacheBlockDynRec * block=cache.block.active;
+       // check for enough space in this block
+       Bitu size=block->cache.size;
+       CacheBlockDynRec * nextblock=block->cache.next;
+       if (block->page.handler) 
+               block->Clear();
+       // block size must be at least CACHE_MAXSIZE
+       while (size<CACHE_MAXSIZE) {
+               if (!nextblock)
+                       goto skipresize;
+               // merge blocks
+               size+=nextblock->cache.size;
+               CacheBlockDynRec * tempblock=nextblock->cache.next;
+               if (nextblock->page.handler) 
+                       nextblock->Clear();
+               // block is free now
+               cache_addunusedblock(nextblock);
+               nextblock=tempblock;
+       }
+skipresize:
+       // adjust parameters and open this block
+       block->cache.size=size;
+       block->cache.next=nextblock;
+       cache.pos=block->cache.start;
+       return block;
+}
+
+static void cache_closeblock(void) {
+       CacheBlockDynRec * block=cache.block.active;
+       // links point to the default linking code
+       block->link[0].to=&link_blocks[0];
+       block->link[1].to=&link_blocks[1];
+       block->link[0].from=0;
+       block->link[1].from=0;
+       block->link[0].next=0;
+       block->link[1].next=0;
+       // close the block with correct alignment
+       Bitu written=(Bitu)(cache.pos-block->cache.start);
+       if (written>block->cache.size) {
+               if (!block->cache.next) {
+                       if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size);       
+               } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size);     
+       } else {
+               Bitu new_size;
+               Bitu left=block->cache.size-written;
+               // smaller than cache align then don't bother to resize
+               if (left>CACHE_ALIGN) {
+                       new_size=((written-1)|(CACHE_ALIGN-1))+1;
+                       CacheBlockDynRec * newblock=cache_getblock();
+                       // align block now to CACHE_ALIGN
+                       newblock->cache.start=block->cache.start+new_size;
+                       newblock->cache.size=block->cache.size-new_size;
+                       newblock->cache.next=block->cache.next;
+                       block->cache.next=newblock;
+                       block->cache.size=new_size;
+               }
+       }
+       // advance the active block pointer
+       if (!block->cache.next || (block->cache.next->cache.start>(cache_code_start_ptr + CACHE_TOTAL - CACHE_MAXSIZE))) {
+//             LOG_MSG("Cache full restarting");
+               cache.block.active=cache.block.first;
+       } else {
+               cache.block.active=block->cache.next;
+       }
+}
+
+
+// place an 8bit value into the cache
+static INLINE void cache_addb(Bit8u val) {
+       *cache.pos++=val;
+}
+
+// place a 16bit value into the cache
+static INLINE void cache_addw(Bit16u val) {
+       *(Bit16u*)cache.pos=val;
+       cache.pos+=2;
+}
+
+// place a 32bit value into the cache
+static INLINE void cache_addd(Bit32u val) {
+       *(Bit32u*)cache.pos=val;
+       cache.pos+=4;
+}
+
+// place a 64bit value into the cache
+static INLINE void cache_addq(Bit64u val) {
+       *(Bit64u*)cache.pos=val;
+       cache.pos+=8;
+}
+
+
+static void dyn_return(BlockReturn retcode,bool ret_exception);
+static void dyn_run_code(void);
+
+
+/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */
+#if (C_HAVE_MPROTECT)
+#define PAGESIZE_TEMP PAGESIZE
+#else 
+#define PAGESIZE_TEMP 4096
+#endif
+
+static bool cache_initialized = false;
+
+static void cache_init(bool enable) {
+       Bits i;
+       if (enable) {
+               // see if cache is already initialized
+               if (cache_initialized) return;
+               cache_initialized = true;
+               if (cache_blocks == NULL) {
+                       // allocate the cache blocks memory
+                       cache_blocks=(CacheBlockDynRec*)malloc(CACHE_BLOCKS*sizeof(CacheBlockDynRec));
+                       if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
+                       memset(cache_blocks,0,sizeof(CacheBlockDynRec)*CACHE_BLOCKS);
+                       cache.block.free=&cache_blocks[0];
+                       // initialize the cache blocks
+                       for (i=0;i<CACHE_BLOCKS-1;i++) {
+                               cache_blocks[i].link[0].to=(CacheBlockDynRec *)1;
+                               cache_blocks[i].link[1].to=(CacheBlockDynRec *)1;
+                               cache_blocks[i].cache.next=&cache_blocks[i+1];
+                       }
+               }
+               if (cache_code_start_ptr==NULL) {
+                       // allocate the code cache memory
+#if defined (WIN32)
+                       cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
+                               MEM_COMMIT,PAGE_EXECUTE_READWRITE);
+                       if (!cache_code_start_ptr)
+                               cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#else
+                       cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
+#endif
+                       if(!cache_code_start_ptr) E_Exit("Allocating dynamic cache failed");
+
+                       // align the cache at a page boundary
+                       cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1));//Bitu is same size as a pointer.
+
+                       cache_code_link_blocks=cache_code;
+                       cache_code=cache_code+PAGESIZE_TEMP;
+
+#if (C_HAVE_MPROTECT)
+                       if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
+                               LOG_MSG("Setting excute permission on the code cache has failed");
+#endif
+                       CacheBlockDynRec * block=cache_getblock();
+                       cache.block.first=block;
+                       cache.block.active=block;
+                       block->cache.start=&cache_code[0];
+                       block->cache.size=CACHE_TOTAL;
+                       block->cache.next=0;                                            // last block in the list
+               }
+               // setup the default blocks for block linkage returns
+               cache.pos=&cache_code_link_blocks[0];
+               link_blocks[0].cache.start=cache.pos;
+               // link code that returns with a special return code
+               dyn_return(BR_Link1,false);
+               cache.pos=&cache_code_link_blocks[32];
+               link_blocks[1].cache.start=cache.pos;
+               // link code that returns with a special return code
+               dyn_return(BR_Link2,false);
+
+               cache.pos=&cache_code_link_blocks[64];
+               core_dynrec.runcode=(BlockReturn (*)(Bit8u*))cache.pos;
+//             link_blocks[1].cache.start=cache.pos;
+               dyn_run_code();
+
+               cache.free_pages=0;
+               cache.last_page=0;
+               cache.used_pages=0;
+               // setup the code pages
+               for (i=0;i<CACHE_PAGES;i++) {
+                       CodePageHandlerDynRec * newpage=new CodePageHandlerDynRec();
+                       newpage->next=cache.free_pages;
+                       cache.free_pages=newpage;
+               }
+       }
+}
+
+static void cache_close(void) {
+/*     for (;;) {
+               if (cache.used_pages) {
+                       CodePageHandler * cpage=cache.used_pages;
+                       CodePageHandler * npage=cache.used_pages->next;
+                       cpage->ClearRelease();
+                       delete cpage;
+                       cache.used_pages=npage;
+               } else break;
+       }
+       if (cache_blocks != NULL) {
+               free(cache_blocks);
+               cache_blocks = NULL;
+       }
+       if (cache_code_start_ptr != NULL) {
+               ### care: under windows VirtualFree() has to be used if
+               ###       VirtualAlloc was used for memory allocation
+               free(cache_code_start_ptr);
+               cache_code_start_ptr = NULL;
+       }
+       cache_code = NULL;
+       cache_code_link_blocks = NULL;
+       cache_initialized = false; */
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder.h
new file mode 100644 (file)
index 0000000..9c1fe49
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+#include "decoder_basic.h"
+#include "operators.h"
+#include "decoder_opcodes.h"
+
+#include "dyn_fpu.h"
+
+/*
+       The function CreateCacheBlock translates the instruction stream
+       until either an unhandled instruction is found, the maximum
+       number of translated instructions is reached or some critical
+       instruction is encountered.
+*/
+
+static CacheBlockDynRec * CreateCacheBlock(CodePageHandlerDynRec * codepage,PhysPt start,Bitu max_opcodes) {
+       // initialize a load of variables
+       decode.code_start=start;
+       decode.code=start;
+       decode.page.code=codepage;
+       decode.page.index=start&4095;
+       decode.page.wmap=codepage->write_map;
+       decode.page.invmap=codepage->invalidation_map;
+       decode.page.first=start >> 12;
+       decode.active_block=decode.block=cache_openblock();
+       decode.block->page.start=(Bit16u)decode.page.index;
+       codepage->AddCacheBlock(decode.block);
+
+       InitFlagsOptimization();
+
+       // every codeblock that is run sets cache.block.running to itself
+       // so the block linking knows the last executed block
+       gen_mov_direct_ptr(&cache.block.running,(DRC_PTR_SIZE_IM)decode.block);
+
+       // start with the cycles check
+       gen_mov_word_to_reg(FC_RETOP,&CPU_Cycles,true);
+       save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_leqzero(FC_RETOP);
+       save_info_dynrec[used_save_info_dynrec].type=cycle_check;
+       used_save_info_dynrec++;
+
+       decode.cycles=0;
+       while (max_opcodes--) {
+               // Init prefixes
+               decode.big_addr=cpu.code.big;
+               decode.big_op=cpu.code.big;
+               decode.seg_prefix=0;
+               decode.seg_prefix_used=false;
+               decode.rep=REP_NONE;
+               decode.cycles++;
+               decode.op_start=decode.code;
+restart_prefix:
+               Bitu opcode;
+               if (!decode.page.invmap) opcode=decode_fetchb();
+               else {
+                       // some entries in the invalidation map, see if the next
+                       // instruction is known to be modified a lot
+                       if (decode.page.index<4096) {
+                               if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode;
+                               opcode=decode_fetchb();
+                       } else {
+                               // switch to the next page
+                               opcode=decode_fetchb();
+                               if (GCC_UNLIKELY(decode.page.invmap && 
+                                       (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode;
+                       }
+               }
+               switch (opcode) {
+               // instructions 'op reg8,reg8' and 'op [],reg8'
+               case 0x00:dyn_dop_ebgb(DOP_ADD);break;
+               case 0x08:dyn_dop_ebgb(DOP_OR);break;
+               case 0x10:dyn_dop_ebgb(DOP_ADC);break;
+               case 0x18:dyn_dop_ebgb(DOP_SBB);break;
+               case 0x20:dyn_dop_ebgb(DOP_AND);break;
+               case 0x28:dyn_dop_ebgb(DOP_SUB);break;
+               case 0x30:dyn_dop_ebgb(DOP_XOR);break;
+               case 0x38:dyn_dop_ebgb(DOP_CMP);break;
+
+               // instructions 'op reg8,reg8' and 'op reg8,[]'
+               case 0x02:dyn_dop_gbeb(DOP_ADD);break;
+               case 0x0a:dyn_dop_gbeb(DOP_OR);break;
+               case 0x12:dyn_dop_gbeb(DOP_ADC);break;
+               case 0x1a:dyn_dop_gbeb(DOP_SBB);break;
+               case 0x22:dyn_dop_gbeb(DOP_AND);break;
+               case 0x2a:dyn_dop_gbeb(DOP_SUB);break;
+               case 0x32:dyn_dop_gbeb(DOP_XOR);break;
+               case 0x3a:dyn_dop_gbeb(DOP_CMP);break;
+
+               // instructions 'op reg16/32,reg16/32' and 'op [],reg16/32'
+               case 0x01:dyn_dop_evgv(DOP_ADD);break;
+               case 0x09:dyn_dop_evgv(DOP_OR);break;
+               case 0x11:dyn_dop_evgv(DOP_ADC);break;
+               case 0x19:dyn_dop_evgv(DOP_SBB);break;
+               case 0x21:dyn_dop_evgv(DOP_AND);break;
+               case 0x29:dyn_dop_evgv(DOP_SUB);break;
+               case 0x31:dyn_dop_evgv(DOP_XOR);break;
+               case 0x39:dyn_dop_evgv(DOP_CMP);break;
+
+               // instructions 'op reg16/32,reg16/32' and 'op reg16/32,[]'
+               case 0x03:dyn_dop_gvev(DOP_ADD);break;
+               case 0x0b:dyn_dop_gvev(DOP_OR);break;
+               case 0x13:dyn_dop_gvev(DOP_ADC);break;
+               case 0x1b:dyn_dop_gvev(DOP_SBB);break;
+               case 0x23:dyn_dop_gvev(DOP_AND);break;
+               case 0x2b:dyn_dop_gvev(DOP_SUB);break;
+               case 0x33:dyn_dop_gvev(DOP_XOR);break;
+               case 0x3b:dyn_dop_gvev(DOP_CMP);break;
+
+               // instructions 'op reg8,imm8'
+               case 0x04:dyn_dop_byte_imm(DOP_ADD,DRC_REG_EAX,0);break;
+               case 0x0c:dyn_dop_byte_imm(DOP_OR,DRC_REG_EAX,0);break;
+               case 0x14:dyn_dop_byte_imm(DOP_ADC,DRC_REG_EAX,0);break;
+               case 0x1c:dyn_dop_byte_imm(DOP_SBB,DRC_REG_EAX,0);break;
+               case 0x24:dyn_dop_byte_imm(DOP_AND,DRC_REG_EAX,0);break;
+               case 0x2c:dyn_dop_byte_imm(DOP_SUB,DRC_REG_EAX,0);break;
+               case 0x34:dyn_dop_byte_imm(DOP_XOR,DRC_REG_EAX,0);break;
+               case 0x3c:dyn_dop_byte_imm(DOP_CMP,DRC_REG_EAX,0);break;
+
+               // instructions 'op reg16/32,imm16/32'
+               case 0x05:dyn_dop_word_imm(DOP_ADD,DRC_REG_EAX);break;
+               case 0x0d:dyn_dop_word_imm_old(DOP_OR,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x15:dyn_dop_word_imm_old(DOP_ADC,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x1d:dyn_dop_word_imm_old(DOP_SBB,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x25:dyn_dop_word_imm(DOP_AND,DRC_REG_EAX);break;
+               case 0x2d:dyn_dop_word_imm_old(DOP_SUB,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x35:dyn_dop_word_imm_old(DOP_XOR,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+               case 0x3d:dyn_dop_word_imm_old(DOP_CMP,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+
+               // push segment register onto stack
+               case 0x06:dyn_push_seg(DRC_SEG_ES);break;
+               case 0x0e:dyn_push_seg(DRC_SEG_CS);break;
+               case 0x16:dyn_push_seg(DRC_SEG_SS);break;
+               case 0x1e:dyn_push_seg(DRC_SEG_DS);break;
+
+               // pop segment register from stack
+               case 0x07:dyn_pop_seg(DRC_SEG_ES);break;
+               case 0x17:dyn_pop_seg(DRC_SEG_SS);break;
+               case 0x1f:dyn_pop_seg(DRC_SEG_DS);break;
+
+               // segment prefixes
+               case 0x26:dyn_segprefix(DRC_SEG_ES);goto restart_prefix;
+               case 0x2e:dyn_segprefix(DRC_SEG_CS);goto restart_prefix;
+               case 0x36:dyn_segprefix(DRC_SEG_SS);goto restart_prefix;
+               case 0x3e:dyn_segprefix(DRC_SEG_DS);goto restart_prefix;
+               case 0x64:dyn_segprefix(DRC_SEG_FS);goto restart_prefix;
+               case 0x65:dyn_segprefix(DRC_SEG_GS);goto restart_prefix;
+
+//             case 0x27: DAA missing
+//             case 0x2f: DAS missing
+//             case 0x37: AAA missing
+//             case 0x3f: AAS missing
+
+               // dual opcodes
+               case 0x0f:
+               {
+                       Bitu dual_code=decode_fetchb();
+                       switch (dual_code) {
+                               case 0x00:
+                                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
+                                       dyn_grp6();
+                                       break;
+                               case 0x01:
+                                       if (dyn_grp7()) goto finish_block;
+                                       break;
+/*                             case 0x02:
+                                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
+                                       dyn_larlsl(true);
+                                       break;
+                               case 0x03:
+                                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
+                                       dyn_larlsl(false);
+                                       break; */
+
+                               case 0x20:dyn_mov_from_crx();break;
+                               case 0x22:dyn_mov_to_crx();goto finish_block;
+
+                               // short conditional jumps
+                               case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87:        
+                               case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f:        
+                                       dyn_branched_exit((BranchTypes)(dual_code&0xf),
+                                               decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
+                                       goto finish_block;
+
+                               // conditional byte set instructions
+/*                             case 0x90:case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:        
+                               case 0x98:case 0x99:case 0x9a:case 0x9b:case 0x9c:case 0x9d:case 0x9e:case 0x9f:        
+                                       dyn_set_byte_on_condition((BranchTypes)(dual_code&0xf));
+                                       AcquireFlags(FMASK_TEST);
+                                       break; */
+
+                               // push/pop segment registers
+                               case 0xa0:dyn_push_seg(DRC_SEG_FS);break;
+                               case 0xa1:dyn_pop_seg(DRC_SEG_FS);break;
+                               case 0xa8:dyn_push_seg(DRC_SEG_GS);break;
+                               case 0xa9:dyn_pop_seg(DRC_SEG_GS);break;
+
+                               // double shift instructions
+                               case 0xa4:dyn_dshift_ev_gv(true,true);break;
+                               case 0xa5:dyn_dshift_ev_gv(true,false);break;
+                               case 0xac:dyn_dshift_ev_gv(false,true);break;
+                               case 0xad:dyn_dshift_ev_gv(false,false);break;
+
+                               case 0xaf:dyn_imul_gvev(0);break;
+
+                               // lfs
+                               case 0xb4:
+                                       dyn_get_modrm();
+                                       if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                                       dyn_load_seg_off_ea(DRC_SEG_FS);
+                                       break;
+                               // lgs
+                               case 0xb5:
+                                       dyn_get_modrm();
+                                       if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                                       dyn_load_seg_off_ea(DRC_SEG_GS);
+                                       break;
+
+                               // zero-extending moves
+                               case 0xb6:dyn_movx_ev_gb(false);break;
+                               case 0xb7:dyn_movx_ev_gw(false);break;
+
+                               // sign-extending moves
+                               case 0xbe:dyn_movx_ev_gb(true);break;
+                               case 0xbf:dyn_movx_ev_gw(true);break;
+
+                               default:
+#if DYN_LOG
+//                                     LOG_MSG("Unhandled dual opcode 0F%02X",dual_code);
+#endif
+                                       goto illegalopcode;
+                       }
+                       break;
+               }
+
+               // 'inc/dec reg16/32'
+               case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47:        
+                       dyn_sop_word(SOP_INC,opcode&7);
+                       break;
+               case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f:        
+                       dyn_sop_word(SOP_DEC,opcode&7);
+                       break;
+
+               // 'push/pop reg16/32'
+               case 0x50:case 0x51:case 0x52:case 0x53:case 0x54:case 0x55:case 0x56:case 0x57:        
+                       dyn_push_reg(opcode&7);
+                       break;
+               case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f:        
+                       dyn_pop_reg(opcode&7);
+                       break;
+
+               case 0x60:
+                       if (decode.big_op) gen_call_function_raw((void *)&dynrec_pusha_dword);
+                       else gen_call_function_raw((void *)&dynrec_pusha_word);
+                       break;
+               case 0x61:
+                       if (decode.big_op) gen_call_function_raw((void *)&dynrec_popa_dword);
+                       else gen_call_function_raw((void *)&dynrec_popa_word);
+                       break;
+
+//             case 0x62: BOUND missing
+//             case 0x61: ARPL missing
+
+               case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix;
+               case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix;
+
+               // 'push imm8/16/32'
+               case 0x68:
+                       dyn_push_word_imm(decode.big_op ? decode_fetchd() :  decode_fetchw());
+                       break;
+               case 0x6a:
+                       dyn_push_byte_imm((Bit8s)decode_fetchb());
+                       break;
+
+               // signed multiplication
+               case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break;
+               case 0x6b:dyn_imul_gvev(1);break;
+
+//             case 0x6c to 0x6f missing (ins/outs)
+
+               // short conditional jumps
+               case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77:        
+               case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f:        
+                       dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb());    
+                       goto finish_block;
+
+               // 'op []/reg8,imm8'
+               case 0x80:
+               case 0x82:dyn_grp1_eb_ib();break;
+
+               // 'op []/reg16/32,imm16/32'
+               case 0x81:dyn_grp1_ev_iv(false);break;
+               case 0x83:dyn_grp1_ev_iv(true);break;
+
+               // 'test []/reg8/16/32,reg8/16/32'
+               case 0x84:dyn_dop_gbeb(DOP_TEST);break;
+               case 0x85:dyn_dop_gvev(DOP_TEST);break;
+
+               // 'xchg reg8/16/32,[]/reg8/16/32'
+               case 0x86:dyn_dop_ebgb_xchg();break;
+               case 0x87:dyn_dop_evgv_xchg();break;
+
+               // 'mov []/reg8/16/32,reg8/16/32'
+               case 0x88:dyn_dop_ebgb_mov();break;
+               case 0x89:dyn_dop_evgv_mov();break;
+               // 'mov reg8/16/32,[]/reg8/16/32'
+               case 0x8a:dyn_dop_gbeb_mov();break;
+               case 0x8b:dyn_dop_gvev_mov();break;
+
+               // move segment register into memory or a 16bit register
+               case 0x8c:dyn_mov_ev_seg();break;
+
+               // load effective address
+               case 0x8d:dyn_lea();break;
+
+               // move a value from memory or a 16bit register into a segment register
+               case 0x8e:dyn_mov_seg_ev();break;
+
+               // 'pop []'
+               case 0x8f:dyn_pop_ev();break;
+
+               case 0x90:      // nop
+               case 0x9b:      // wait
+               case 0xf0:      // lock
+                       break;
+
+               case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97:
+                       dyn_xchg_ax(opcode&7);
+                       break;
+
+               // sign-extend al into ax/sign-extend ax into eax
+               case 0x98:dyn_cbw();break;
+               // sign-extend ax into dx:ax/sign-extend eax into edx:eax
+               case 0x99:dyn_cwd();break;
+
+               case 0x9a:dyn_call_far_imm();goto finish_block;
+
+               case 0x9c:      // pushf
+                       AcquireFlags(FMASK_TEST);
+                       gen_call_function_I((void *)&CPU_PUSHF,decode.big_op);
+                       dyn_check_exception(FC_RETOP);
+                       break;
+               case 0x9d:      // popf
+                       gen_call_function_I((void *)&CPU_POPF,decode.big_op);
+                       dyn_check_exception(FC_RETOP);
+                       InvalidateFlags();
+                       break;
+
+               case 0x9e:dyn_sahf();break;
+//             case 0x9f: LAHF missing
+
+               // 'mov al/ax,[]'
+               case 0xa0:
+                       dyn_mov_byte_al_direct(decode.big_addr ? decode_fetchd() : decode_fetchw());
+                       break;
+               case 0xa1:
+                       dyn_mov_byte_ax_direct(decode.big_addr ? decode_fetchd() : decode_fetchw());
+                       break;
+               // 'mov [],al/ax'
+               case 0xa2:
+                       dyn_mov_byte_direct_al();
+                       break;
+               case 0xa3:
+                       dyn_mov_byte_direct_ax(decode.big_addr ? decode_fetchd() : decode_fetchw());
+                       break;
+
+
+//             case 0xa6 to 0xaf string operations, some missing
+
+               // movsb/w/d
+               case 0xa4:dyn_string(STR_MOVSB);break;
+               case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break;
+
+               // stosb/w/d
+               case 0xaa:dyn_string(STR_STOSB);break;
+               case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break;
+
+               // lodsb/w/d
+               case 0xac:dyn_string(STR_LODSB);break;
+               case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break;
+
+
+               // 'test reg8/16/32,imm8/16/32'
+               case 0xa8:dyn_dop_byte_imm(DOP_TEST,DRC_REG_EAX,0);break;
+               case 0xa9:dyn_dop_word_imm_old(DOP_TEST,DRC_REG_EAX,decode.big_op ? decode_fetchd() :  decode_fetchw());break;
+
+               // 'mov reg8/16/32,imm8/16/32'
+               case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7:        
+                       dyn_mov_byte_imm(opcode&3,(opcode>>2)&1,decode_fetchb());
+                       break;
+               case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf:        
+                       dyn_mov_word_imm(opcode&7);break;
+                       break;
+
+               // 'shiftop []/reg8,imm8/1/cl'
+               case 0xc0:dyn_grp2_eb(grp2_imm);break;
+               case 0xd0:dyn_grp2_eb(grp2_1);break;
+               case 0xd2:dyn_grp2_eb(grp2_cl);break;
+
+               // 'shiftop []/reg16/32,imm8/1/cl'
+               case 0xc1:dyn_grp2_ev(grp2_imm);break;
+               case 0xd1:dyn_grp2_ev(grp2_1);break;
+               case 0xd3:dyn_grp2_ev(grp2_cl);break;
+
+               // retn [param]
+               case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block;
+               case 0xc3:dyn_ret_near(0);goto finish_block;
+
+               // les
+               case 0xc4:
+                       dyn_get_modrm();
+                       if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                       dyn_load_seg_off_ea(DRC_SEG_ES);
+                       break;
+               // lds
+               case 0xc5:
+                       dyn_get_modrm();
+                       if (GCC_UNLIKELY(decode.modrm.mod==3)) goto illegalopcode;
+                       dyn_load_seg_off_ea(DRC_SEG_DS);break;
+
+               // 'mov []/reg8/16/32,imm8/16/32'
+               case 0xc6:dyn_dop_ebib_mov();break;
+               case 0xc7:dyn_dop_eviv_mov();break;
+
+               case 0xc8:dyn_enter();break;
+               case 0xc9:dyn_leave();break;
+
+               // retf [param]
+               case 0xca:dyn_ret_far(decode_fetchw());goto finish_block;
+               case 0xcb:dyn_ret_far(0);goto finish_block;
+
+               // int/iret
+               case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block;
+               case 0xcf:dyn_iret();goto finish_block;
+
+//             case 0xd4: AAM missing
+//             case 0xd5: AAD missing
+
+//             case 0xd6: SALC missing
+//             case 0xd7: XLAT missing
+
+
+#ifdef CPU_FPU
+               // floating point instructions
+               case 0xd8:
+                       dyn_fpu_esc0();
+                       break;
+               case 0xd9:
+                       dyn_fpu_esc1();
+                       break;
+               case 0xda:
+                       dyn_fpu_esc2();
+                       break;
+               case 0xdb:
+                       dyn_fpu_esc3();
+                       break;
+               case 0xdc:
+                       dyn_fpu_esc4();
+                       break;
+               case 0xdd:
+                       dyn_fpu_esc5();
+                       break;
+               case 0xde:
+                       dyn_fpu_esc6();
+                       break;
+               case 0xdf:
+                       dyn_fpu_esc7();
+                       break;
+#endif
+
+
+               // loop instructions
+               case 0xe0:dyn_loop(LOOP_NE);goto finish_block;
+               case 0xe1:dyn_loop(LOOP_E);goto finish_block;
+               case 0xe2:dyn_loop(LOOP_NONE);goto finish_block;
+               case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block;
+
+
+               // 'in al/ax/eax,port_imm'
+               case 0xe4:dyn_read_port_byte_direct(decode_fetchb());break;
+               case 0xe5:dyn_read_port_word_direct(decode_fetchb());break;
+               // 'out port_imm,al/ax/eax'
+               case 0xe6:dyn_write_port_byte_direct(decode_fetchb());break;
+               case 0xe7:dyn_write_port_word_direct(decode_fetchb());break;
+
+               // 'in al/ax/eax,port_dx'
+               case 0xec:dyn_read_port_byte();break;
+               case 0xed:dyn_read_port_word();break;
+               // 'out port_dx,al/ax/eax'
+               case 0xee:dyn_write_port_byte();break;
+               case 0xef:dyn_write_port_word();break;
+
+
+               // 'call near imm16/32'
+               case 0xe8:
+                       dyn_call_near_imm();
+                       goto finish_block;
+               // 'jmp near imm16/32'
+               case 0xe9:
+                       dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw());
+                       goto finish_block;
+               // 'jmp far'
+               case 0xea:
+                       dyn_jmp_far_imm();
+                       goto finish_block;
+               // 'jmp short imm8'
+               case 0xeb:
+                       dyn_exit_link((Bit8s)decode_fetchb());
+                       goto finish_block;
+
+
+               // repeat prefixes
+               case 0xf2:
+                       decode.rep=REP_NZ;
+                       goto restart_prefix;
+               case 0xf3:
+                       decode.rep=REP_Z;
+                       goto restart_prefix;
+
+               case 0xf5:              //CMC
+                       gen_call_function_raw((void*)dynrec_cmc);
+                       break;
+               case 0xf8:              //CLC
+                       gen_call_function_raw((void*)dynrec_clc);
+                       break;
+               case 0xf9:              //STC
+                       gen_call_function_raw((void*)dynrec_stc);
+                       break;
+
+               case 0xf6:dyn_grp3_eb();break;
+               case 0xf7:dyn_grp3_ev();break;
+
+               case 0xfa:              //CLI
+                       gen_call_function_raw((void *)&CPU_CLI);
+                       dyn_check_exception(FC_RETOP);
+                       break;
+               case 0xfb:              //STI
+                       gen_call_function_raw((void *)&CPU_STI);
+                       dyn_check_exception(FC_RETOP);
+                       if (max_opcodes<=0) max_opcodes=1;              //Allow 1 extra opcode
+                       break;
+
+               case 0xfc:              //CLD
+                       gen_call_function_raw((void*)dynrec_cld);
+                       break;
+               case 0xfd:              //STD
+                       gen_call_function_raw((void*)dynrec_std);
+                       break;
+
+               case 0xfe:
+                       if (dyn_grp4_eb()) goto finish_block;
+                       break;
+               case 0xff:
+                       switch (dyn_grp4_ev()) {
+                       case 0:
+                               break;
+                       case 1:
+                               goto core_close_block;
+                       case 2:
+                               goto illegalopcode;
+                       default:
+                               break;
+                       }
+                       break;
+
+               default:
+#if DYN_LOG
+//                     LOG_MSG("Dynrec unhandled opcode %X",opcode);
+#endif
+                       goto illegalopcode;
+               }
+       }
+       // link to next block because the maximum number of opcodes has been reached
+       dyn_set_eip_end();
+       dyn_reduce_cycles();
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));
+       dyn_closeblock();
+    goto finish_block;
+core_close_block:
+       dyn_reduce_cycles();
+       dyn_return(BR_Normal);
+       dyn_closeblock();
+       goto finish_block;
+illegalopcode:
+       // some unhandled opcode has been encountered
+       dyn_set_eip_last();
+       dyn_reduce_cycles();
+       dyn_return(BR_Opcode);  // tell the core what happened
+       dyn_closeblock();
+       goto finish_block;
+finish_block:
+
+       // setup the correct end-address
+       decode.page.index--;
+       decode.active_block->page.end=(Bit16u)decode.page.index;
+//     LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end);
+
+       return decode.block;
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder_basic.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder_basic.h
new file mode 100644 (file)
index 0000000..61edc64
--- /dev/null
@@ -0,0 +1,1267 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/*
+       This file provides some definitions and basic level functions
+       that use code generating functions from risc_?.h
+       Important is the function call generation including parameter
+       loading, the effective address calculation and the memory
+       access functions.
+*/
+
+
+// instructions that use one operand
+enum SingleOps {
+       SOP_INC,SOP_DEC,
+       SOP_NOT,SOP_NEG
+};
+
+// instructions that use two operand
+enum DualOps {
+       DOP_ADD,DOP_ADC,
+       DOP_SUB,DOP_SBB,
+       DOP_CMP,DOP_XOR,
+       DOP_AND,DOP_OR,
+       DOP_TEST,
+       DOP_MOV,
+       DOP_XCHG
+};
+
+// shift and rotate functions
+enum ShiftOps {
+       SHIFT_ROL,SHIFT_ROR,
+       SHIFT_RCL,SHIFT_RCR,
+       SHIFT_SHL,SHIFT_SHR,
+       SHIFT_SAL,SHIFT_SAR
+};
+
+// branch conditions
+enum BranchTypes {
+       BR_O,BR_NO,BR_B,BR_NB,
+       BR_Z,BR_NZ,BR_BE,BR_NBE,
+       BR_S,BR_NS,BR_P,BR_NP,
+       BR_L,BR_NL,BR_LE,BR_NLE
+};
+
+// string instructions
+enum StringOps {
+       STR_OUTSB=0,STR_OUTSW,STR_OUTSD,
+       STR_INSB=4,STR_INSW,STR_INSD,
+       STR_MOVSB=8,STR_MOVSW,STR_MOVSD,
+       STR_LODSB=12,STR_LODSW,STR_LODSD,
+       STR_STOSB=16,STR_STOSW,STR_STOSD,
+       STR_SCASB=20,STR_SCASW,STR_SCASD,
+       STR_CMPSB=24,STR_CMPSW,STR_CMPSD
+};
+
+// repeat prefix type (for string operations)
+enum REP_Type {
+       REP_NONE=0,REP_NZ,REP_Z
+};
+
+// loop type
+enum LoopTypes {
+       LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ
+};
+
+// rotate operand type
+enum grp2_types {
+       grp2_1,grp2_imm,grp2_cl
+};
+
+// opcode mapping for group1 instructions
+static DualOps grp1_table[8]={
+       DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP
+};
+
+
+// decoding information used during translation of a code block
+static struct DynDecode {
+       PhysPt code;                    // pointer to next byte in the instruction stream
+       PhysPt code_start;              // pointer to the start of the current code block
+       PhysPt op_start;                // pointer to the start of the current instruction
+       bool big_op;                    // operand modifier
+       bool big_addr;                  // address modifier
+       REP_Type rep;                   // current repeat prefix
+       Bitu cycles;                    // number cycles used by currently translated code
+       bool seg_prefix_used;   // segment overridden
+       Bit8u seg_prefix;               // segment prefix (if seg_prefix_used==true)
+
+       // block that contains the first instruction translated
+       CacheBlockDynRec * block;
+       // block that contains the current byte of the instruction stream
+       CacheBlockDynRec * active_block;
+
+       // the active page (containing the current byte of the instruction stream)
+       struct {
+               CodePageHandlerDynRec * code;
+               Bitu index;             // index to the current byte of the instruction stream
+               Bit8u * wmap;   // write map that indicates code presence for every byte of this page
+               Bit8u * invmap; // invalidation map
+               Bitu first;             // page number 
+       } page;
+
+       // modrm state of the current instruction (if used)
+       struct {
+               Bitu val;
+               Bitu mod;
+               Bitu rm;
+               Bitu reg;
+       } modrm;
+} decode;
+
+
+static bool MakeCodePage(Bitu lin_addr,CodePageHandlerDynRec * &cph) {
+       Bit8u rdval;
+       //Ensure page contains memory:
+       if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true;
+
+       PageHandler * handler=get_tlb_readhandler(lin_addr);
+       if (handler->flags & PFLAG_HASCODE) {
+               // this is a codepage handler, and the one that we're looking for
+               cph=(CodePageHandlerDynRec *)handler;
+               return false;
+       }
+       if (handler->flags & PFLAG_NOCODE) {
+               if (PAGING_ForcePageInit(lin_addr)) {
+                       handler=get_tlb_readhandler(lin_addr);
+                       if (handler->flags & PFLAG_HASCODE) {
+                               cph=(CodePageHandlerDynRec *)handler;
+                               return false;
+                       }
+               }
+               if (handler->flags & PFLAG_NOCODE) {
+                       LOG_MSG("DYNREC:Can't run code in this page");
+                       cph=0;
+                       return false;
+               }
+       } 
+       Bitu lin_page=lin_addr>>12;
+       Bitu phys_page=lin_page;
+       // find the physical page that the linear page is mapped to
+       if (!PAGING_MakePhysPage(phys_page)) {
+               LOG_MSG("DYNREC:Can't find physpage");
+               cph=0;
+               return false;
+       }
+       // find a free CodePage
+       if (!cache.free_pages) {
+               if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease();
+               else {
+                       // try another page to avoid clearing our source-crosspage
+                       if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code))
+                               cache.used_pages->next->ClearRelease();
+                       else {
+                               LOG_MSG("DYNREC:Invalid cache links");
+                               cache.used_pages->ClearRelease();
+                       }
+               }
+       }
+       CodePageHandlerDynRec * cpagehandler=cache.free_pages;
+       cache.free_pages=cache.free_pages->next;
+
+       // adjust previous and next page pointer
+       cpagehandler->prev=cache.last_page;
+       cpagehandler->next=0;
+       if (cache.last_page) cache.last_page->next=cpagehandler;
+       cache.last_page=cpagehandler;
+       if (!cache.used_pages) cache.used_pages=cpagehandler;
+
+       // initialize the code page handler and add the handler to the memory page
+       cpagehandler->SetupAt(phys_page,handler);
+       MEM_SetPageHandler(phys_page,1,cpagehandler);
+       PAGING_UnlinkPages(lin_page,1);
+       cph=cpagehandler;
+       return false;
+}
+
+static void decode_advancepage(void) {
+       // Advance to the next page
+       decode.active_block->page.end=4095;
+       // trigger possible page fault here
+       decode.page.first++;
+       Bitu faddr=decode.page.first << 12;
+       mem_readb(faddr);
+       MakeCodePage(faddr,decode.page.code);
+       CacheBlockDynRec * newblock=cache_getblock();
+       decode.active_block->crossblock=newblock;
+       newblock->crossblock=decode.active_block;
+       decode.active_block=newblock;
+       decode.active_block->page.start=0;
+       decode.page.code->AddCrossBlock(decode.active_block);
+       decode.page.wmap=decode.page.code->write_map;
+       decode.page.invmap=decode.page.code->invalidation_map;
+       decode.page.index=0;
+}
+
+// fetch the next byte of the instruction stream
+static Bit8u decode_fetchb(void) {
+       if (GCC_UNLIKELY(decode.page.index>=4096)) {
+               decode_advancepage();
+       }
+       decode.page.wmap[decode.page.index]+=0x01;
+       decode.page.index++;
+       decode.code+=1;
+       return mem_readb(decode.code-1);
+}
+// fetch the next word of the instruction stream
+static Bit16u decode_fetchw(void) {
+       if (GCC_UNLIKELY(decode.page.index>=4095)) {
+               Bit16u val=decode_fetchb();
+               val|=decode_fetchb() << 8;
+               return val;
+       }
+       *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101;
+       decode.code+=2;decode.page.index+=2;
+       return mem_readw(decode.code-2);
+}
+// fetch the next dword of the instruction stream
+static Bit32u decode_fetchd(void) {
+       if (GCC_UNLIKELY(decode.page.index>=4093)) {
+               Bit32u val=decode_fetchb();
+               val|=decode_fetchb() << 8;
+               val|=decode_fetchb() << 16;
+               val|=decode_fetchb() << 24;
+               return val;
+        /* Advance to the next page */
+       }
+       *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101;
+       decode.code+=4;decode.page.index+=4;
+       return mem_readd(decode.code-4);
+}
+
+#define START_WMMEM 64
+
+// adjust writemap mask to care for map holes due to special
+// codefetch functions
+static void INLINE decode_increase_wmapmask(Bitu size) {
+       Bitu mapidx;
+       CacheBlockDynRec* activecb=decode.active_block; 
+       if (GCC_UNLIKELY(!activecb->cache.wmapmask)) {
+               // no mask memory yet allocated, start with a small buffer
+               activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM);
+               memset(activecb->cache.wmapmask,0,START_WMMEM);
+               activecb->cache.maskstart=decode.page.index;    // start of buffer is current code position
+               activecb->cache.masklen=START_WMMEM;
+               mapidx=0;
+       } else {
+               mapidx=decode.page.index-activecb->cache.maskstart;
+               if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) {
+                       // mask buffer too small, increase
+                       Bitu newmasklen=activecb->cache.masklen*4;
+                       if (newmasklen<mapidx+size) newmasklen=((mapidx+size)&~3)*2;
+                       Bit8u* tempmem=(Bit8u*)malloc(newmasklen);
+                       memset(tempmem,0,newmasklen);
+                       memcpy(tempmem,activecb->cache.wmapmask,activecb->cache.masklen);
+                       free(activecb->cache.wmapmask);
+                       activecb->cache.wmapmask=tempmem;
+                       activecb->cache.masklen=newmasklen;
+               }
+       }
+       // update mask entries
+       switch (size) {
+               case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break;
+               case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break;
+               case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break;
+       }
+}
+
+// fetch a byte, val points to the code location if possible,
+// otherwise val contains the current value read from the position
+static bool decode_fetchb_imm(Bitu & val) {
+       if (GCC_UNLIKELY(decode.page.index>=4096)) {
+               decode_advancepage();
+       }
+       // see if position is directly accessible
+       if (decode.page.invmap != NULL) {
+               if (decode.page.invmap[decode.page.index] == 0) {
+                       // position not yet modified
+                       val=(Bit32u)decode_fetchb();
+                       return false;
+               }
+
+               HostPt tlb_addr=get_tlb_read(decode.code);
+               if (tlb_addr) {
+                       val=(Bitu)(tlb_addr+decode.code);
+                       decode_increase_wmapmask(1);
+                       decode.code++;
+                       decode.page.index++;
+                       return true;
+               }
+       }
+       // first time decoding or not directly accessible, just fetch the value
+       val=(Bit32u)decode_fetchb();
+       return false;
+}
+
+// fetch a word, val points to the code location if possible,
+// otherwise val contains the current value read from the position
+static bool decode_fetchw_imm(Bitu & val) {
+       if (decode.page.index<4095) {
+               if (decode.page.invmap != NULL) {
+                       if ((decode.page.invmap[decode.page.index] == 0) &&
+                               (decode.page.invmap[decode.page.index + 1] == 0)) {
+                               // position not yet modified
+                               val=decode_fetchw();
+                               return false;
+                       }
+
+                       HostPt tlb_addr=get_tlb_read(decode.code);
+                       // see if position is directly accessible
+                       if (tlb_addr) {
+                               val=(Bitu)(tlb_addr+decode.code);
+                               decode_increase_wmapmask(2);
+                               decode.code+=2;
+                               decode.page.index+=2;
+                               return true;
+                       }
+               }
+       }
+       // first time decoding or not directly accessible, just fetch the value
+       val=decode_fetchw();
+       return false;
+}
+
+// fetch a dword, val points to the code location if possible,
+// otherwise val contains the current value read from the position
+static bool decode_fetchd_imm(Bitu & val) {
+       if (decode.page.index<4093) {
+               if (decode.page.invmap != NULL) {
+                       if ((decode.page.invmap[decode.page.index] == 0) &&
+                               (decode.page.invmap[decode.page.index + 1] == 0) &&
+                               (decode.page.invmap[decode.page.index + 2] == 0) &&
+                               (decode.page.invmap[decode.page.index + 3] == 0)) {
+                               // position not yet modified
+                               val=decode_fetchd();
+                               return false;
+                       }
+
+                       HostPt tlb_addr=get_tlb_read(decode.code);
+                       // see if position is directly accessible
+                       if (tlb_addr) {
+                               val=(Bitu)(tlb_addr+decode.code);
+                               decode_increase_wmapmask(4);
+                               decode.code+=4;
+                               decode.page.index+=4;
+                               return true;
+                       }
+               }
+       }
+       // first time decoding or not directly accessible, just fetch the value
+       val=decode_fetchd();
+       return false;
+}
+
+
+// modrm decoding helper
+static void INLINE dyn_get_modrm(void) {
+       decode.modrm.val=decode_fetchb();
+       decode.modrm.mod=(decode.modrm.val >> 6) & 3;
+       decode.modrm.reg=(decode.modrm.val >> 3) & 7;
+       decode.modrm.rm=(decode.modrm.val & 7);
+}
+
+
+#ifdef DRC_USE_SEGS_ADDR
+
+#define MOV_SEG_VAL_TO_HOST_REG(host_reg, seg_index) gen_mov_seg16_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_VAL(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs))
+
+#define MOV_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_mov_seg32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_PHYS(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs))
+#define ADD_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_add_seg32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_SEG_PHYS(seg_index)) - (DRC_PTR_SIZE_IM)(&Segs))
+
+#else
+
+#define MOV_SEG_VAL_TO_HOST_REG(host_reg, seg_index) gen_mov_word_to_reg(host_reg,DRCD_SEG_VAL(seg_index),false)
+
+#define MOV_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_mov_word_to_reg(host_reg,DRCD_SEG_PHYS(seg_index),true)
+#define ADD_SEG_PHYS_TO_HOST_REG(host_reg, seg_index) gen_add(host_reg,DRCD_SEG_PHYS(seg_index))
+
+#endif
+
+
+#ifdef DRC_USE_REGS_ADDR
+
+#define MOV_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_mov_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_VAL(reg_index)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+#define ADD_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_add_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_VAL(reg_index)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+
+#define MOV_REG_WORD16_TO_HOST_REG(host_reg, reg_index) gen_mov_regval16_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,false)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+#define MOV_REG_WORD32_TO_HOST_REG(host_reg, reg_index) gen_mov_regval32_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,true)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+#define MOV_REG_WORD_TO_HOST_REG(host_reg, reg_index, dword) gen_mov_regword_to_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,dword)) - (DRC_PTR_SIZE_IM)(&cpu_regs), dword)
+
+#define MOV_REG_WORD16_FROM_HOST_REG(host_reg, reg_index) gen_mov_regval16_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,false)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+#define MOV_REG_WORD32_FROM_HOST_REG(host_reg, reg_index) gen_mov_regval32_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,true)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+#define MOV_REG_WORD_FROM_HOST_REG(host_reg, reg_index, dword) gen_mov_regword_from_reg(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_WORD(reg_index,dword)) - (DRC_PTR_SIZE_IM)(&cpu_regs), dword)
+
+#define MOV_REG_BYTE_TO_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_regbyte_to_reg_low(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_regbyte_to_reg_low_canuseword(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_regbyte_from_reg_low(host_reg,(DRC_PTR_SIZE_IM)(DRCD_REG_BYTE(reg_index,high_byte)) - (DRC_PTR_SIZE_IM)(&cpu_regs))
+
+#else
+
+#define MOV_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_VAL(reg_index),true)
+#define ADD_REG_VAL_TO_HOST_REG(host_reg, reg_index) gen_add(host_reg,DRCD_REG_VAL(reg_index))
+
+#define MOV_REG_WORD16_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,false),false)
+#define MOV_REG_WORD32_TO_HOST_REG(host_reg, reg_index) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,true),true)
+#define MOV_REG_WORD_TO_HOST_REG(host_reg, reg_index, dword) gen_mov_word_to_reg(host_reg,DRCD_REG_WORD(reg_index,dword),dword)
+
+#define MOV_REG_WORD16_FROM_HOST_REG(host_reg, reg_index) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,false),false)
+#define MOV_REG_WORD32_FROM_HOST_REG(host_reg, reg_index) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,true),true)
+#define MOV_REG_WORD_FROM_HOST_REG(host_reg, reg_index, dword) gen_mov_word_from_reg(host_reg,DRCD_REG_WORD(reg_index,dword),dword)
+
+#define MOV_REG_BYTE_TO_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_byte_to_reg_low(host_reg,DRCD_REG_BYTE(reg_index,high_byte))
+#define MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(host_reg, reg_index, high_byte) gen_mov_byte_to_reg_low_canuseword(host_reg,DRCD_REG_BYTE(reg_index,high_byte))
+#define MOV_REG_BYTE_FROM_HOST_REG_LOW(host_reg, reg_index, high_byte) gen_mov_byte_from_reg_low(host_reg,DRCD_REG_BYTE(reg_index,high_byte))
+
+#endif
+
+
+#define DYN_LEA_MEM_MEM(ea_reg, op1, op2, scale, imm) dyn_lea_mem_mem(ea_reg,op1,op2,scale,imm)
+
+#if defined(DRC_USE_REGS_ADDR) && defined(DRC_USE_SEGS_ADDR)
+
+#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_segphys_regval(ea_reg,op1_index,op2_index,scale,imm)
+#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_regval_regval(ea_reg,op1_index,op2_index,scale,imm)
+#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,op1,op2_index,scale,imm)
+
+#elif defined(DRC_USE_REGS_ADDR)
+
+#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,DRCD_SEG_PHYS(op1_index),op2_index,scale,imm)
+#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_regval_regval(ea_reg,op1_index,op2_index,scale,imm)
+#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_regval(ea_reg,op1,op2_index,scale,imm)
+
+#elif defined(DRC_USE_SEGS_ADDR)
+
+#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_segphys_mem(ea_reg,op1_index,DRCD_REG_VAL(op2_index),scale,imm)
+#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_REG_VAL(op1_index),DRCD_REG_VAL(op2_index),scale,imm)
+#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,op1,DRCD_REG_VAL(op2_index),scale,imm)
+
+#else
+
+#define DYN_LEA_SEG_PHYS_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_SEG_PHYS(op1_index),DRCD_REG_VAL(op2_index),scale,imm)
+#define DYN_LEA_REG_VAL_REG_VAL(ea_reg, op1_index, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,DRCD_REG_VAL(op1_index),DRCD_REG_VAL(op2_index),scale,imm)
+#define DYN_LEA_MEM_REG_VAL(ea_reg, op1, op2_index, scale, imm) dyn_lea_mem_mem(ea_reg,op1,DRCD_REG_VAL(op2_index),scale,imm)
+
+#endif
+
+
+
+// adjust CPU_Cycles value
+static void dyn_reduce_cycles(void) {
+       if (!decode.cycles) decode.cycles++;
+       gen_sub_direct_word(&CPU_Cycles,decode.cycles,true);
+}
+
+
+// set reg to the start of the next instruction
+// set reg_eip to the start of the current instruction
+static INLINE void dyn_set_eip_last_end(HostReg reg) {
+       gen_mov_word_to_reg(reg,&reg_eip,true);
+       gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start));
+       gen_add_direct_word(&reg_eip,decode.op_start-decode.code_start,decode.big_op);
+}
+
+// set reg_eip to the start of the current instruction
+static INLINE void dyn_set_eip_last(void) {
+       gen_add_direct_word(&reg_eip,decode.op_start-decode.code_start,cpu.code.big);
+}
+
+// set reg_eip to the start of the next instruction
+static INLINE void dyn_set_eip_end(void) {
+       gen_add_direct_word(&reg_eip,decode.code-decode.code_start,cpu.code.big);
+}
+
+// set reg_eip to the start of the next instruction plus an offset (imm)
+static INLINE void dyn_set_eip_end(HostReg reg,Bit32u imm=0) {
+       gen_mov_word_to_reg(reg,&reg_eip,true); //get_extend_word will mask off the upper bits
+       //gen_mov_word_to_reg(reg,&reg_eip,decode.big_op);
+       gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start+imm));
+       if (!decode.big_op) gen_extend_word(false,reg);
+}
+
+
+
+// the following functions generate function calls
+// parameters are loaded by generating code using gen_load_param_ which
+// is architecture dependent
+// R=host register; I=32bit immediate value; A=address value; m=memory
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_R(void * func,Bitu op) {
+       gen_load_param_reg(op,0);
+       return gen_call_function_setup(func, 1);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_R3(void * func,Bitu op) {
+       gen_load_param_reg(op,2);
+       return gen_call_function_setup(func, 3, true);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_RI(void * func,Bitu op1,Bitu op2) {
+       gen_load_param_imm(op2,1);
+       gen_load_param_reg(op1,0);
+       return gen_call_function_setup(func, 2);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_RA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) {
+       gen_load_param_addr(op2,1);
+       gen_load_param_reg(op1,0);
+       return gen_call_function_setup(func, 2);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_RR(void * func,Bitu op1,Bitu op2) {
+       gen_load_param_reg(op2,1);
+       gen_load_param_reg(op1,0);
+       return gen_call_function_setup(func, 2);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_IR(void * func,Bitu op1,Bitu op2) {
+       gen_load_param_reg(op2,1);
+       gen_load_param_imm(op1,0);
+       return gen_call_function_setup(func, 2);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_I(void * func,Bitu op) {
+       gen_load_param_imm(op,0);
+       return gen_call_function_setup(func, 1);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_II(void * func,Bitu op1,Bitu op2) {
+       gen_load_param_imm(op2,1);
+       gen_load_param_imm(op1,0);
+       return gen_call_function_setup(func, 2);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_III(void * func,Bitu op1,Bitu op2,Bitu op3) {
+       gen_load_param_imm(op3,2);
+       gen_load_param_imm(op2,1);
+       gen_load_param_imm(op1,0);
+       return gen_call_function_setup(func, 3);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_IA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) {
+       gen_load_param_addr(op2,1);
+       gen_load_param_imm(op1,0);
+       return gen_call_function_setup(func, 2);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_IIR(void * func,Bitu op1,Bitu op2,Bitu op3) {
+       gen_load_param_reg(op3,2);
+       gen_load_param_imm(op2,1);
+       gen_load_param_imm(op1,0);
+       return gen_call_function_setup(func, 3);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_IIIR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) {
+       gen_load_param_reg(op4,3);
+       gen_load_param_imm(op3,2);
+       gen_load_param_imm(op2,1);
+       gen_load_param_imm(op1,0);
+       return gen_call_function_setup(func, 4);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_IRRR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) {
+       gen_load_param_reg(op4,3);
+       gen_load_param_reg(op3,2);
+       gen_load_param_reg(op2,1);
+       gen_load_param_imm(op1,0);
+       return gen_call_function_setup(func, 4);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_m(void * func,Bitu op) {
+       gen_load_param_mem(op,2);
+       return gen_call_function_setup(func, 3, true);
+}
+
+static DRC_PTR_SIZE_IM INLINE gen_call_function_mm(void * func,Bitu op1,Bitu op2) {
+       gen_load_param_mem(op2,3);
+       gen_load_param_mem(op1,2);
+       return gen_call_function_setup(func, 4, true);
+}
+
+
+
+enum save_info_type {db_exception, cycle_check, string_break};
+
+
+// function that is called on exceptions
+static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub) {
+       reg_eip+=eip_add;
+       CPU_Cycles-=cycle_sub;
+       if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock;
+       CPU_Exception(cpu.exception.which,cpu.exception.error);
+       return BR_Normal;
+}
+
+
+// array with information about code that is generated at the
+// end of a cache block because it is rarely reached (like exceptions)
+static struct {
+       save_info_type type;
+       DRC_PTR_SIZE_IM branch_pos;
+       Bit32u eip_change;
+       Bitu cycles;
+} save_info_dynrec[512];
+
+Bitu used_save_info_dynrec=0;
+
+
+// return from current block, with returncode
+static void dyn_return(BlockReturn retcode,bool ret_exception=false) {
+       if (!ret_exception) {
+               gen_mov_dword_to_reg_imm(FC_RETOP,retcode);
+       }
+       gen_return_function();
+}
+
+static void dyn_run_code(void) {
+       gen_run_code();
+       gen_return_function();
+}
+
+// fill in code at the end of the block that contains rarely-executed code
+// which is executed conditionally (like exceptions)
+static void dyn_fill_blocks(void) {
+       for (Bitu sct=0; sct<used_save_info_dynrec; sct++) {
+               gen_fill_branch_long(save_info_dynrec[sct].branch_pos);
+               switch (save_info_dynrec[sct].type) {
+                       case db_exception:
+                               // code for exception handling, load cycles and call DynRunException
+                               decode.cycles=save_info_dynrec[sct].cycles;
+                               if (cpu.code.big) gen_call_function_II((void *)&DynRunException,save_info_dynrec[sct].eip_change,save_info_dynrec[sct].cycles);
+                               else gen_call_function_II((void *)&DynRunException,save_info_dynrec[sct].eip_change&0xffff,save_info_dynrec[sct].cycles);
+                               dyn_return(BR_Normal,true);
+                               break;
+                       case cycle_check:
+                               // cycles are <=0 so exit the core
+                               dyn_return(BR_Cycles);
+                               break;
+                       case string_break:
+                               // interrupt looped string instruction, can be continued later
+                               gen_add_direct_word(&reg_eip,save_info_dynrec[sct].eip_change,decode.big_op);
+                               dyn_return(BR_Cycles);
+                               break;
+               }
+       }
+       used_save_info_dynrec=0;
+}
+
+
+static void dyn_closeblock(void) {
+       //Shouldn't create empty block normally but let's do it like this
+       dyn_fill_blocks();
+       cache_block_before_close();
+       cache_closeblock();
+       cache_block_closing(decode.block->cache.start,decode.block->cache.size);
+}
+
+
+// add a check that can branch to the exception handling
+static void dyn_check_exception(HostReg reg) {
+       save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_nonzero(reg,false);
+       if (!decode.cycles) decode.cycles++;
+       save_info_dynrec[used_save_info_dynrec].cycles=decode.cycles;
+       // in case of an exception eip will point to the start of the current instruction
+       save_info_dynrec[used_save_info_dynrec].eip_change=decode.op_start-decode.code_start;
+       if (!cpu.code.big) save_info_dynrec[used_save_info_dynrec].eip_change&=0xffff;
+       save_info_dynrec[used_save_info_dynrec].type=db_exception;
+       used_save_info_dynrec++;
+}
+
+
+
+bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) DRC_FC;
+bool DRC_CALL_CONV mem_readb_checked_drc(PhysPt address) {
+       HostPt tlb_addr=get_tlb_read(address);
+       if (tlb_addr) {
+               *((Bit8u*)(&core_dynrec.readdata))=host_readb(tlb_addr+address);
+               return false;
+       } else {
+               return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dynrec.readdata));
+       }
+}
+
+bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) DRC_FC;
+bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) {
+       HostPt tlb_addr=get_tlb_write(address);
+       if (tlb_addr) {
+               host_writeb(tlb_addr+address,val);
+               return false;
+       } else return get_tlb_writehandler(address)->writeb_checked(address,val);
+}
+
+bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) DRC_FC;
+bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) {
+       if ((address & 0xfff)<0xfff) {
+               HostPt tlb_addr=get_tlb_read(address);
+               if (tlb_addr) {
+                       *((Bit16u*)(&core_dynrec.readdata))=host_readw(tlb_addr+address);
+                       return false;
+               } else return get_tlb_readhandler(address)->readw_checked(address, (Bit16u*)(&core_dynrec.readdata));
+       } else return mem_unalignedreadw_checked(address, ((Bit16u*)(&core_dynrec.readdata)));
+}
+
+bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) DRC_FC;
+bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) {
+       if ((address & 0xfff)<0xffd) {
+               HostPt tlb_addr=get_tlb_read(address);
+               if (tlb_addr) {
+                       *((Bit32u*)(&core_dynrec.readdata))=host_readd(tlb_addr+address);
+                       return false;
+               } else return get_tlb_readhandler(address)->readd_checked(address, (Bit32u*)(&core_dynrec.readdata));
+       } else return mem_unalignedreadd_checked(address, ((Bit32u*)(&core_dynrec.readdata)));
+}
+
+bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) DRC_FC;
+bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) {
+       if ((address & 0xfff)<0xfff) {
+               HostPt tlb_addr=get_tlb_write(address);
+               if (tlb_addr) {
+                       host_writew(tlb_addr+address,val);
+                       return false;
+               } else return get_tlb_writehandler(address)->writew_checked(address,val);
+       } else return mem_unalignedwritew_checked(address,val);
+}
+
+bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) DRC_FC;
+bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) {
+       if ((address & 0xfff)<0xffd) {
+               HostPt tlb_addr=get_tlb_write(address);
+               if (tlb_addr) {
+                       host_writed(tlb_addr+address,val);
+                       return false;
+               } else return get_tlb_writehandler(address)->writed_checked(address,val);
+       } else return mem_unalignedwrited_checked(address,val);
+}
+
+
+// functions that enable access to the memory
+
+// read a byte from a given address and store it in reg_dst
+static void dyn_read_byte(HostReg reg_addr,HostReg reg_dst) {
+       gen_mov_regs(FC_OP1,reg_addr);
+       gen_call_function_raw((void *)&mem_readb_checked_drc);
+       dyn_check_exception(FC_RETOP);
+       gen_mov_byte_to_reg_low(reg_dst,&core_dynrec.readdata);
+}
+static void dyn_read_byte_canuseword(HostReg reg_addr,HostReg reg_dst) {
+       gen_mov_regs(FC_OP1,reg_addr);
+       gen_call_function_raw((void *)&mem_readb_checked_drc);
+       dyn_check_exception(FC_RETOP);
+       gen_mov_byte_to_reg_low_canuseword(reg_dst,&core_dynrec.readdata);
+}
+
+// write a byte from reg_val into the memory given by the address
+static void dyn_write_byte(HostReg reg_addr,HostReg reg_val) {
+       gen_mov_regs(FC_OP2,reg_val);
+       gen_mov_regs(FC_OP1,reg_addr);
+       gen_call_function_raw((void *)&mem_writeb_checked_drc);
+       dyn_check_exception(FC_RETOP);
+}
+
+// read a 32bit (dword=true) or 16bit (dword=false) value
+// from a given address and store it in reg_dst
+static void dyn_read_word(HostReg reg_addr,HostReg reg_dst,bool dword) {
+       gen_mov_regs(FC_OP1,reg_addr);
+       if (dword) gen_call_function_raw((void *)&mem_readd_checked_drc);
+       else gen_call_function_raw((void *)&mem_readw_checked_drc);
+       dyn_check_exception(FC_RETOP);
+       gen_mov_word_to_reg(reg_dst,&core_dynrec.readdata,dword);
+}
+
+// write a 32bit (dword=true) or 16bit (dword=false) value
+// from reg_val into the memory given by the address
+static void dyn_write_word(HostReg reg_addr,HostReg reg_val,bool dword) {
+//     if (!dword) gen_extend_word(false,reg_val);
+       gen_mov_regs(FC_OP2,reg_val);
+       gen_mov_regs(FC_OP1,reg_addr);
+       if (dword) gen_call_function_raw((void *)&mem_writed_checked_drc);
+       else gen_call_function_raw((void *)&mem_writew_checked_drc);
+       dyn_check_exception(FC_RETOP);
+}
+
+
+
+// effective address calculation helper, op2 has to be present!
+// loads op1 into ea_reg and adds the scaled op2 and the immediate to it
+static void dyn_lea_mem_mem(HostReg ea_reg,void* op1,void* op2,Bitu scale,Bits imm) {
+       if (scale || imm) {
+               if (op1!=NULL) {
+                       gen_mov_word_to_reg(ea_reg,op1,true);
+                       gen_mov_word_to_reg(TEMP_REG_DRC,op2,true);
+
+                       gen_lea(ea_reg,TEMP_REG_DRC,scale,imm);
+               } else {
+                       gen_mov_word_to_reg(ea_reg,op2,true);
+                       gen_lea(ea_reg,scale,imm);
+               }
+       } else {
+               gen_mov_word_to_reg(ea_reg,op2,true);
+               if (op1!=NULL) gen_add(ea_reg,op1);
+       }
+}
+
+#ifdef DRC_USE_REGS_ADDR
+// effective address calculation helper
+// loads op1 into ea_reg and adds the scaled op2 and the immediate to it
+// op1 is cpu_regs[op1_index], op2 is cpu_regs[op2_index] 
+static void dyn_lea_regval_regval(HostReg ea_reg,Bitu op1_index,Bitu op2_index,Bitu scale,Bits imm) {
+       if (scale || imm) {
+               MOV_REG_VAL_TO_HOST_REG(ea_reg,op1_index);
+               MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index);
+
+               gen_lea(ea_reg,TEMP_REG_DRC,scale,imm);
+       } else {
+               MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index);
+               ADD_REG_VAL_TO_HOST_REG(ea_reg,op1_index);
+       }
+}
+
+// effective address calculation helper
+// loads op1 into ea_reg and adds the scaled op2 and the immediate to it
+// op2 is cpu_regs[op2_index] 
+static void dyn_lea_mem_regval(HostReg ea_reg,void* op1,Bitu op2_index,Bitu scale,Bits imm) {
+       if (scale || imm) {
+               if (op1!=NULL) {
+                       gen_mov_word_to_reg(ea_reg,op1,true);
+                       MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index);
+
+                       gen_lea(ea_reg,TEMP_REG_DRC,scale,imm);
+               } else {
+                       MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index);
+                       gen_lea(ea_reg,scale,imm);
+               }
+       } else {
+               MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index);
+               if (op1!=NULL) gen_add(ea_reg,op1);
+       }
+}
+#endif
+
+#ifdef DRC_USE_SEGS_ADDR
+#ifdef DRC_USE_REGS_ADDR
+// effective address calculation helper
+// loads op1 into ea_reg and adds the scaled op2 and the immediate to it
+// op1 is Segs[op1_index], op2 is cpu_regs[op2_index] 
+static void dyn_lea_segphys_regval(HostReg ea_reg,Bitu op1_index,Bitu op2_index,Bitu scale,Bits imm) {
+       if (scale || imm) {
+               MOV_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index);
+               MOV_REG_VAL_TO_HOST_REG(TEMP_REG_DRC,op2_index);
+
+               gen_lea(ea_reg,TEMP_REG_DRC,scale,imm);
+       } else {
+               MOV_REG_VAL_TO_HOST_REG(ea_reg,op2_index);
+               ADD_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index);
+       }
+}
+
+#else
+
+// effective address calculation helper, op2 has to be present!
+// loads op1 into ea_reg and adds the scaled op2 and the immediate to it
+// op1 is Segs[op1_index] 
+static void dyn_lea_segphys_mem(HostReg ea_reg,Bitu op1_index,void* op2,Bitu scale,Bits imm) {
+       if (scale || imm) {
+               MOV_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index);
+               gen_mov_word_to_reg(TEMP_REG_DRC,op2,true);
+
+               gen_lea(ea_reg,TEMP_REG_DRC,scale,imm);
+       } else {
+               gen_mov_word_to_reg(ea_reg,op2,true);
+               ADD_SEG_PHYS_TO_HOST_REG(ea_reg,op1_index);
+       }
+}
+#endif
+#endif
+
+// calculate the effective address and store it in ea_reg
+static void dyn_fill_ea(HostReg ea_reg,bool addseg=true) {
+       Bit8u seg_base=DRC_SEG_DS;
+       if (!decode.big_addr) {
+               Bits imm;
+               switch (decode.modrm.mod) {
+               case 0:imm=0;break;
+               case 1:imm=(Bit8s)decode_fetchb();break;
+               case 2:imm=(Bit16s)decode_fetchw();break;
+               }
+               switch (decode.modrm.rm) {
+               case 0:// BX+SI
+                       DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBX,DRC_REG_ESI,0,imm);
+                       break;
+               case 1:// BX+DI
+                       DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBX,DRC_REG_EDI,0,imm);
+                       break;
+               case 2:// BP+SI
+                       DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBP,DRC_REG_ESI,0,imm);
+                       seg_base=DRC_SEG_SS;
+                       break;
+               case 3:// BP+DI
+                       DYN_LEA_REG_VAL_REG_VAL(ea_reg,DRC_REG_EBP,DRC_REG_EDI,0,imm);
+                       seg_base=DRC_SEG_SS;
+                       break;
+               case 4:// SI
+                       MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_ESI);
+                       if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+                       break;
+               case 5:// DI
+                       MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EDI);
+                       if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+                       break;
+               case 6:// imm/BP
+                       if (!decode.modrm.mod) {
+                               imm=decode_fetchw();
+                               gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm);
+                               goto skip_extend_word;
+                       } else {
+                               MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EBP);
+                               gen_add_imm(ea_reg,(Bit32u)imm);
+                               seg_base=DRC_SEG_SS;
+                       }
+                       break;
+               case 7: // BX
+                       MOV_REG_VAL_TO_HOST_REG(ea_reg,DRC_REG_EBX);
+                       if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+                       break;
+               }
+               // zero out the high 16bit so ea_reg can be used as full register
+               gen_extend_word(false,ea_reg);
+skip_extend_word:
+               if (addseg) {
+                       // add the physical segment value if requested
+                       ADD_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+               }
+       } else {
+               Bits imm=0;
+               Bit8u base_reg;
+               Bit8u scaled_reg;
+               Bitu scale=0;
+               switch (decode.modrm.rm) {
+               case 0:base_reg=DRC_REG_EAX;break;
+               case 1:base_reg=DRC_REG_ECX;break;
+               case 2:base_reg=DRC_REG_EDX;break;
+               case 3:base_reg=DRC_REG_EBX;break;
+               case 4: // SIB
+                       {
+                               Bitu sib=decode_fetchb();
+                               bool scaled_reg_used=false;
+                               static Bit8u scaledtable[8]={
+                                       DRC_REG_EAX,DRC_REG_ECX,DRC_REG_EDX,DRC_REG_EBX,
+                                                       0,DRC_REG_EBP,DRC_REG_ESI,DRC_REG_EDI
+                               };
+                               // see if scaling should be used and which register is to be scaled in this case
+                               if (((sib >> 3) &7)!=4) scaled_reg_used=true;
+                               scaled_reg=scaledtable[(sib >> 3) &7];
+                               scale=(sib >> 6);
+
+                               switch (sib & 7) {
+                               case 0:base_reg=DRC_REG_EAX;break;
+                               case 1:base_reg=DRC_REG_ECX;break;
+                               case 2:base_reg=DRC_REG_EDX;break;
+                               case 3:base_reg=DRC_REG_EBX;break;
+                               case 4:base_reg=DRC_REG_ESP;seg_base=DRC_SEG_SS;break;
+                               case 5:
+                                       if (decode.modrm.mod) {
+                                               base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS;
+                                       } else {
+                                               // no basereg, maybe scalereg
+                                               Bitu val;
+                                               // try to get a pointer to the next dword code position
+                                               if (decode_fetchd_imm(val)) {
+                                                       // succeeded, use the pointer to avoid code invalidation
+                                                       if (!addseg) {
+                                                               if (!scaled_reg_used) {
+                                                                       gen_mov_word_to_reg(ea_reg,(void*)val,true);
+                                                               } else {
+                                                                       DYN_LEA_MEM_REG_VAL(ea_reg,NULL,scaled_reg,scale,0);
+                                                                       gen_add(ea_reg,(void*)val);
+                                                               }
+                                                       } else {
+                                                               if (!scaled_reg_used) {
+                                                                       MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+                                                               } else {
+                                                                       DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,0);
+                                                               }
+                                                               gen_add(ea_reg,(void*)val);
+                                                       }
+                                                       return;
+                                               }
+                                               // couldn't get a pointer, use the current value
+                                               imm=(Bit32s)val;
+
+                                               if (!addseg) {
+                                                       if (!scaled_reg_used) {
+                                                               gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm);
+                                                       } else {
+                                                               DYN_LEA_MEM_REG_VAL(ea_reg,NULL,scaled_reg,scale,imm);
+                                                       }
+                                               } else {
+                                                       if (!scaled_reg_used) {
+                                                               MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+                                                               if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+                                                       } else {
+                                                               DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,imm);
+                                                       }
+                                               }
+
+                                               return;
+                                       }
+                                       break;
+                               case 6:base_reg=DRC_REG_ESI;break;
+                               case 7:base_reg=DRC_REG_EDI;break;
+                               }
+                               // basereg, maybe scalereg
+                               switch (decode.modrm.mod) {
+                               case 1:
+                                       imm=(Bit8s)decode_fetchb();
+                                       break;
+                               case 2: {
+                                       Bitu val;
+                                       // try to get a pointer to the next dword code position
+                                       if (decode_fetchd_imm(val)) {
+                                               // succeeded, use the pointer to avoid code invalidation
+                                               if (!addseg) {
+                                                       if (!scaled_reg_used) {
+                                                               MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                                                               gen_add(ea_reg,(void*)val);
+                                                       } else {
+                                                               DYN_LEA_REG_VAL_REG_VAL(ea_reg,base_reg,scaled_reg,scale,0);
+                                                               gen_add(ea_reg,(void*)val);
+                                                       }
+                                               } else {
+                                                       if (!scaled_reg_used) {
+                                                               MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+                                                       } else {
+                                                               DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,0);
+                                                       }
+                                                       ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                                                       gen_add(ea_reg,(void*)val);
+                                               }
+                                               return;
+                                       }
+                                       // couldn't get a pointer, use the current value
+                                       imm=(Bit32s)val;
+                                       break;
+                                       }
+                               }
+
+                               if (!addseg) {
+                                       if (!scaled_reg_used) {
+                                               MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                                               gen_add_imm(ea_reg,(Bit32u)imm);
+                                       } else {
+                                               DYN_LEA_REG_VAL_REG_VAL(ea_reg,base_reg,scaled_reg,scale,imm);
+                                       }
+                               } else {
+                                       if (!scaled_reg_used) {
+                                               MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+                                               ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                                               if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+                                       } else {
+                                               DYN_LEA_SEG_PHYS_REG_VAL(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base),scaled_reg,scale,imm);
+                                               ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                                       }
+                               }
+
+                               return;
+                       }       
+                       break;  // SIB Break
+               case 5:
+                       if (decode.modrm.mod) {
+                               base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS;
+                       } else {
+                               // no base, no scalereg
+
+                               imm=(Bit32s)decode_fetchd();
+                               if (!addseg) {
+                                       gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm);
+                               } else {
+                                       MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+                                       if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+                               }
+
+                               return;
+                       }
+                       break;
+               case 6:base_reg=DRC_REG_ESI;break;
+               case 7:base_reg=DRC_REG_EDI;break;
+               }
+
+               // no scalereg, but basereg
+
+               switch (decode.modrm.mod) {
+               case 1:
+                       imm=(Bit8s)decode_fetchb();
+                       break;
+               case 2: {
+                       Bitu val;
+                       // try to get a pointer to the next dword code position
+                       if (decode_fetchd_imm(val)) {
+                               // succeeded, use the pointer to avoid code invalidation
+                               if (!addseg) {
+                                       MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                                       gen_add(ea_reg,(void*)val);
+                               } else {
+                                       MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+                                       ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                                       gen_add(ea_reg,(void*)val);
+                               }
+                               return;
+                       }
+                       // couldn't get a pointer, use the current value
+                       imm=(Bit32s)val;
+                       break;
+                       }
+               }
+
+               if (!addseg) {
+                       MOV_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                       if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+               } else {
+                       MOV_SEG_PHYS_TO_HOST_REG(ea_reg,(decode.seg_prefix_used ? decode.seg_prefix : seg_base));
+                       ADD_REG_VAL_TO_HOST_REG(ea_reg,base_reg);
+                       if (imm) gen_add_imm(ea_reg,(Bit32u)imm);
+               }
+       }
+}
+
+
+
+// add code that checks if port access is allowed
+// the port is given in a register
+static void dyn_add_iocheck(HostReg reg_port,Bitu access_size) {
+       if (cpu.pmode) {
+               gen_call_function_RI((void *)&CPU_IO_Exception,reg_port,access_size);
+               dyn_check_exception(FC_RETOP);
+       }
+}
+
+// add code that checks if port access is allowed
+// the port is a constant
+static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) {
+       if (cpu.pmode) {
+               gen_call_function_II((void *)&CPU_IO_Exception,accessed_port,access_size);
+               dyn_check_exception(FC_RETOP);
+       }
+}
+
+
+
+// save back the address register
+static void gen_protect_addr_reg(void) {
+#ifdef DRC_PROTECT_ADDR_REG
+       gen_mov_word_from_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true);
+#endif
+}
+
+// restore the address register
+static void gen_restore_addr_reg(void) {
+#ifdef DRC_PROTECT_ADDR_REG
+       gen_mov_word_to_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true);
+#endif
+}
+
+// save back an arbitrary register
+static void gen_protect_reg(HostReg reg) {
+       gen_mov_word_from_reg(reg,&core_dynrec.protected_regs[reg],true);
+}
+
+// restore an arbitrary register
+static void gen_restore_reg(HostReg reg) {
+       gen_mov_word_to_reg(reg,&core_dynrec.protected_regs[reg],true);
+}
+
+// restore an arbitrary register into a different register
+static void gen_restore_reg(HostReg reg,HostReg dest_reg) {
+       gen_mov_word_to_reg(dest_reg,&core_dynrec.protected_regs[reg],true);
+}
+
+
+
+// flags optimization functions
+// they try to find out if a function can be replaced by another
+// one that does not generate any flags at all
+
+static Bitu mf_functions_num=0;
+static struct {
+       Bit8u* pos;
+       void* fct_ptr;
+       Bitu ftype;
+} mf_functions[64];
+
+static void InitFlagsOptimization(void) {
+       mf_functions_num=0;
+}
+
+// replace all queued functions with their simpler variants
+// because the current instruction destroys all condition flags and
+// the flags are not required before
+static void InvalidateFlags(void) {
+#ifdef DRC_FLAGS_INVALIDATION
+       for (Bitu ct=0; ct<mf_functions_num; ct++) {
+               gen_fill_function_ptr(mf_functions[ct].pos,mf_functions[ct].fct_ptr,mf_functions[ct].ftype);
+       }
+       mf_functions_num=0;
+#endif
+}
+
+// replace all queued functions with their simpler variants
+// because the current instruction destroys all condition flags and
+// the flags are not required before
+static void InvalidateFlags(void* current_simple_function,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION
+       for (Bitu ct=0; ct<mf_functions_num; ct++) {
+               gen_fill_function_ptr(mf_functions[ct].pos,mf_functions[ct].fct_ptr,mf_functions[ct].ftype);
+       }
+       mf_functions_num=1;
+       mf_functions[0].pos=cache.pos;
+       mf_functions[0].fct_ptr=current_simple_function;
+       mf_functions[0].ftype=flags_type;
+#endif
+}
+
+// enqueue this instruction, if later an instruction is encountered that
+// destroys all condition flags and the flags weren't needed in-between
+// this function can be replaced by a simpler one as well
+static void InvalidateFlagsPartially(void* current_simple_function,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION
+       mf_functions[mf_functions_num].pos=cache.pos;
+       mf_functions[mf_functions_num].fct_ptr=current_simple_function;
+       mf_functions[mf_functions_num].ftype=flags_type;
+       mf_functions_num++;
+#endif
+}
+
+// enqueue this instruction, if later an instruction is encountered that
+// destroys all condition flags and the flags weren't needed in-between
+// this function can be replaced by a simpler one as well
+static void InvalidateFlagsPartially(void* current_simple_function,DRC_PTR_SIZE_IM cpos,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION
+       mf_functions[mf_functions_num].pos=(Bit8u*)cpos;
+       mf_functions[mf_functions_num].fct_ptr=current_simple_function;
+       mf_functions[mf_functions_num].ftype=flags_type;
+       mf_functions_num++;
+#endif
+}
+
+// the current function needs the condition flags thus reset the queue
+static void AcquireFlags(Bitu flags_mask) {
+#ifdef DRC_FLAGS_INVALIDATION
+       mf_functions_num=0;
+#endif
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder_opcodes.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/decoder_opcodes.h
new file mode 100644 (file)
index 0000000..d08ae43
--- /dev/null
@@ -0,0 +1,1429 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/*
+       The functions in this file are called almost exclusively by     decoder.h,
+       they translate an (or a set of) instruction(s) into hostspecific code
+       and use the lower-level functions from decoder_basic.h and generating
+       functions from risc_?.h
+       Some complex instructions as well as most instructions that can modify
+       the condition flags are translated by generating a call to a C-function
+       (see operators.h). Parameter loading and result writeback is done
+       according to the instruction.
+*/
+
+static void dyn_dop_ebgb(DualOps op) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_byte_canuseword(FC_ADDR,FC_OP1);
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               dyn_dop_byte_gencall(op);
+
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) {
+                       gen_restore_addr_reg();
+                       dyn_write_byte(FC_ADDR,FC_RETOP);
+               }
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               dyn_dop_byte_gencall(op);
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+
+static void dyn_dop_ebgb_mov(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               dyn_write_byte(FC_ADDR,FC_TMP_BA1);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+
+static void dyn_dop_ebib_mov(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb());
+               dyn_write_byte(FC_ADDR,FC_TMP_BA1);
+       } else {
+               gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb());
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+
+static void dyn_dop_ebgb_xchg(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_byte(FC_ADDR,FC_TMP_BA1);
+               MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               gen_restore_addr_reg();
+               dyn_write_byte(FC_ADDR,FC_TMP_BA2);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+               MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA2,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+
+static void dyn_dop_gbeb(DualOps op) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_byte_canuseword(FC_ADDR,FC_OP2);
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               dyn_dop_byte_gencall(op);
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+               dyn_dop_byte_gencall(op);
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+       }
+}
+
+static void dyn_dop_gbeb_mov(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_byte(FC_ADDR,FC_TMP_BA1);
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.reg&3,(decode.modrm.reg>>2)&1);
+       }
+}
+
+static void dyn_dop_evgv(DualOps op) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+               gen_protect_addr_reg();
+               MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op);
+               dyn_dop_word_gencall(op,decode.big_op);
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) {
+                       gen_restore_addr_reg();
+                       dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
+               }
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+               MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op);
+               dyn_dop_word_gencall(op,decode.big_op);
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op);
+       }
+}
+
+static void dyn_dop_evgv_mov(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+               dyn_write_word(FC_ADDR,FC_OP1,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+}
+
+static void dyn_dop_eviv_mov(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd());
+               else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw());
+               dyn_write_word(FC_ADDR,FC_OP1,decode.big_op);
+       } else {
+               if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd());
+               else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw());
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+}
+
+static void dyn_dop_evgv_xchg(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+               MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op);
+
+               gen_protect_reg(FC_OP1);
+               gen_restore_addr_reg();
+               dyn_write_word(FC_ADDR,FC_OP2,decode.big_op);
+               gen_restore_reg(FC_OP1);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+               MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op);
+       }
+}
+
+static void dyn_xchg_ax(Bit8u reg) {
+       MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op);
+       MOV_REG_WORD_TO_HOST_REG(FC_OP2,reg,decode.big_op);
+       MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op);
+       MOV_REG_WORD_FROM_HOST_REG(FC_OP2,DRC_REG_EAX,decode.big_op);
+}
+
+static void dyn_dop_gvev(DualOps op) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP2,decode.big_op);
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+               dyn_dop_word_gencall(op,decode.big_op);
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) {
+                       gen_restore_addr_reg();
+                       MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op);
+               }
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.rm,decode.big_op);
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+               dyn_dop_word_gencall(op,decode.big_op);
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op);
+       }
+}
+
+static void dyn_dop_gvev_mov(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+       }
+}
+
+static void dyn_dop_byte_imm(DualOps op,Bit8u reg,Bit8u idx) {
+       MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx);
+       gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb());
+       dyn_dop_byte_gencall(op);
+       if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx);
+}
+
+static void dyn_dop_byte_imm_mem(DualOps op,Bit8u reg,Bit8u idx) {
+       MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,reg,idx);
+       Bitu val;
+       if (decode_fetchb_imm(val)) {
+               gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val);
+       } else {
+               gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,(Bit8u)val);
+       }
+       dyn_dop_byte_gencall(op);
+       if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,reg,idx);
+}
+
+static void dyn_prep_word_imm(Bit8u reg) {
+       Bitu val;
+       if (decode.big_op) {
+               if (decode_fetchd_imm(val)) {
+                       gen_mov_word_to_reg(FC_OP2,(void*)val,true);
+                       return;
+               }
+       } else {
+               if (decode_fetchw_imm(val)) {
+                       gen_mov_word_to_reg(FC_OP2,(void*)val,false);
+                       return;
+               }
+       }
+       if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)val);
+       else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)val);
+}
+
+static void dyn_dop_word_imm(DualOps op,Bit8u reg) {
+       MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op);
+       dyn_prep_word_imm(reg);
+       dyn_dop_word_gencall(op,decode.big_op);
+       if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op);
+}
+
+static void dyn_dop_word_imm_old(DualOps op,Bit8u reg,Bitu imm) {
+       MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op);
+       if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm);
+       else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm);
+       dyn_dop_word_gencall(op,decode.big_op);
+       if ((op!=DOP_CMP) && (op!=DOP_TEST)) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op);
+}
+
+static void dyn_mov_byte_imm(Bit8u reg,Bit8u idx,Bit8u imm) {
+       gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,imm);
+       MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,reg,idx);
+}
+
+static void dyn_mov_word_imm(Bit8u reg) {
+       Bitu val;
+       if (decode.big_op) {
+               if (decode_fetchd_imm(val)) {
+                       gen_mov_word_to_reg(FC_OP1,(void*)val,true);
+                       MOV_REG_WORD32_FROM_HOST_REG(FC_OP1,reg);
+                       return;
+               }
+       } else {
+               if (decode_fetchw_imm(val)) {
+                       gen_mov_word_to_reg(FC_OP1,(void*)val,false);
+                       MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,reg);
+                       return;
+               }
+       }
+       if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)val);
+       else gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)val);
+       MOV_REG_WORD_FROM_HOST_REG(FC_OP1,reg,decode.big_op);
+}
+
+
+static void dyn_sop_word(SingleOps op,Bit8u reg) {
+       MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op);
+       dyn_sop_word_gencall(op,decode.big_op);
+       MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op);
+}
+
+
+static void dyn_mov_byte_al_direct(Bitu imm) {
+       MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS));
+       gen_add_imm(FC_ADDR,imm);
+       dyn_read_byte(FC_ADDR,FC_TMP_BA1);
+       MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0);
+}
+
+static void dyn_mov_byte_ax_direct(Bitu imm) {
+       MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS));
+       gen_add_imm(FC_ADDR,imm);
+       dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+       MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op);
+}
+
+static void dyn_mov_byte_direct_al() {
+       MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS));
+       if (decode.big_addr) {
+               Bitu val;
+               if (decode_fetchd_imm(val)) {
+                       gen_add(FC_ADDR,(void*)val);
+               } else {
+                       gen_add_imm(FC_ADDR,(Bit32u)val);
+               }
+       } else {
+               gen_add_imm(FC_ADDR,decode_fetchw());
+       }
+       MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,DRC_REG_EAX,0);
+       dyn_write_byte(FC_ADDR,FC_TMP_BA1);
+}
+
+static void dyn_mov_byte_direct_ax(Bitu imm) {
+       MOV_SEG_PHYS_TO_HOST_REG(FC_ADDR,(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS));
+       gen_add_imm(FC_ADDR,imm);
+       MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op);
+       dyn_write_word(FC_ADDR,FC_OP1,decode.big_op);
+}
+
+
+static void dyn_movx_ev_gb(bool sign) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_byte(FC_ADDR,FC_TMP_BA1);
+               gen_extend_byte(sign,FC_TMP_BA1);
+               MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW(FC_TMP_BA1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+               gen_extend_byte(sign,FC_TMP_BA1);
+               MOV_REG_WORD_FROM_HOST_REG(FC_TMP_BA1,decode.modrm.reg,decode.big_op);
+       }
+}
+
+static void dyn_movx_ev_gw(bool sign) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_word(FC_ADDR,FC_OP1,false);
+               gen_extend_word(sign,FC_OP1);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+       } else {
+               MOV_REG_WORD16_TO_HOST_REG(FC_OP1,decode.modrm.rm);
+               gen_extend_word(sign,FC_OP1);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+       }
+}
+
+
+static void dyn_mov_ev_seg(void) {
+       dyn_get_modrm();
+       MOV_SEG_VAL_TO_HOST_REG(FC_OP1,decode.modrm.reg);
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_write_word(FC_ADDR,FC_OP1,false);
+       } else {
+               if (decode.big_op) gen_extend_word(false,FC_OP1);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+}
+
+
+static void dyn_lea(void) {
+       dyn_get_modrm();
+       dyn_fill_ea(FC_ADDR,false);
+       MOV_REG_WORD_FROM_HOST_REG(FC_ADDR,decode.modrm.reg,decode.big_op);
+}
+
+
+static void dyn_push_seg(Bit8u seg) {
+       MOV_SEG_VAL_TO_HOST_REG(FC_OP1,seg);
+       if (decode.big_op) {
+               gen_extend_word(false,FC_OP1);
+               gen_call_function_raw((void*)&dynrec_push_dword);
+       } else {
+               gen_call_function_raw((void*)&dynrec_push_word);
+       }
+}
+
+static void dyn_pop_seg(Bit8u seg) {
+       gen_call_function_II((void *)&CPU_PopSeg,seg,decode.big_op);
+       dyn_check_exception(FC_RETOP);
+}
+
+static void dyn_push_reg(Bit8u reg) {
+       MOV_REG_WORD_TO_HOST_REG(FC_OP1,reg,decode.big_op);
+       if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword);
+       else gen_call_function_raw((void*)&dynrec_push_word);
+}
+
+static void dyn_pop_reg(Bit8u reg) {
+       if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword);
+       else gen_call_function_raw((void*)&dynrec_pop_word);
+       MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,reg,decode.big_op);
+}
+
+static void dyn_push_byte_imm(Bit8s imm) {
+       gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm);
+       if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword);
+       else gen_call_function_raw((void*)&dynrec_push_word);
+}
+
+static void dyn_push_word_imm(Bitu imm) {
+       if (decode.big_op) {
+               gen_mov_dword_to_reg_imm(FC_OP1,imm);
+               gen_call_function_raw((void*)&dynrec_push_dword);
+       } else {
+               gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)imm);
+               gen_call_function_raw((void*)&dynrec_push_word);
+       }
+}
+
+static void dyn_pop_ev(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+/*             dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);    // dummy read to trigger possible page faults */
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword);
+               else gen_call_function_raw((void*)&dynrec_pop_word);
+               dyn_fill_ea(FC_ADDR);
+//             gen_restore_addr_reg();
+               dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
+       } else {
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword);
+               else gen_call_function_raw((void*)&dynrec_pop_word);
+               MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op);
+       }
+}
+
+
+static void dyn_segprefix(Bit8u seg) {
+//     if (GCC_UNLIKELY(decode.seg_prefix_used)) IllegalOptionDynrec("dyn_segprefix");
+       decode.seg_prefix=seg;
+       decode.seg_prefix_used=true;
+}
+
+ static void dyn_mov_seg_ev(void) {
+       dyn_get_modrm();
+       if (GCC_UNLIKELY(decode.modrm.reg==DRC_SEG_CS)) IllegalOptionDynrec("dyn_mov_seg_ev");
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_word(FC_ADDR,FC_RETOP,false);
+       } else {
+               MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm);
+       }
+       gen_call_function_IR((void *)&CPU_SetSegGeneral,decode.modrm.reg,FC_RETOP);
+       dyn_check_exception(FC_RETOP);
+}
+
+static void dyn_load_seg_off_ea(Bit8u seg) {
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+               gen_protect_reg(FC_OP1);
+
+               gen_restore_addr_reg();
+               gen_add_imm(FC_ADDR,decode.big_op ? 4:2);
+               dyn_read_word(FC_ADDR,FC_RETOP,false);
+
+               gen_call_function_IR((void *)&CPU_SetSegGeneral,seg,FC_RETOP);
+               dyn_check_exception(FC_RETOP);
+
+               gen_restore_reg(FC_OP1);
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,decode.modrm.reg,decode.big_op);
+       } else {
+               IllegalOptionDynrec("dyn_load_seg_off_ea");
+       }
+}
+
+
+
+static void dyn_imul_gvev(Bitu immsize) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+
+       switch (immsize) {
+               case 0:
+                       MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op);
+                       break;
+               case 1:
+                       if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb());
+                       else  gen_mov_word_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb());
+                       break;
+               case 2:
+                       if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw());
+                       else gen_mov_word_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw());
+                       break;
+               case 4:
+                       if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32s)decode_fetchd());
+                       else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)((Bit32s)decode_fetchd()));
+                       break;
+       }
+
+       if (decode.big_op) gen_call_function_raw((void*)dynrec_dimul_dword);
+       else gen_call_function_raw((void*)dynrec_dimul_word);
+
+       MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.reg,decode.big_op);
+}
+
+static void dyn_dshift_ev_gv(bool left,bool immediate) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+       MOV_REG_WORD_TO_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op);
+       if (immediate) gen_mov_byte_to_reg_low_imm(FC_OP3,decode_fetchb());
+       else MOV_REG_BYTE_TO_HOST_REG_LOW(FC_OP3,DRC_REG_ECX,0);
+       if (decode.big_op) dyn_dpshift_dword_gencall(left);
+       else dyn_dpshift_word_gencall(left);
+
+       if (decode.modrm.mod<3) {
+               gen_restore_addr_reg();
+               dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
+       } else {
+               MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op);
+       }
+}
+
+
+static void dyn_grp1_eb_ib(void) {
+       dyn_get_modrm();
+       DualOps op=grp1_table[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_byte_canuseword(FC_ADDR,FC_OP1);
+               gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb());
+               dyn_dop_byte_gencall(op);
+
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) {
+                       gen_restore_addr_reg();
+                       dyn_write_byte(FC_ADDR,FC_RETOP);
+               }
+       } else {
+               dyn_dop_byte_imm_mem(op,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+
+static void dyn_grp1_ev_iv(bool withbyte) {
+       dyn_get_modrm();
+       DualOps op=grp1_table[decode.modrm.reg];
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+
+               if (!withbyte) {
+                       dyn_prep_word_imm(FC_OP2);
+               } else {
+                       Bits imm=(Bit8s)decode_fetchb(); 
+                       if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm);
+                       else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm);
+               }
+
+               dyn_dop_word_gencall(op,decode.big_op);
+
+               if ((op!=DOP_CMP) && (op!=DOP_TEST)) {
+                       gen_restore_addr_reg();
+                       dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
+               }
+       } else {
+               if (!withbyte) {
+                       dyn_dop_word_imm(op,decode.modrm.rm);
+               } else {
+                       Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); 
+                       dyn_dop_word_imm_old(op,decode.modrm.rm,imm);
+               }
+       }
+}
+
+
+static void dyn_grp2_eb(grp2_types type) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_byte_canuseword(FC_ADDR,FC_OP1);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+       switch (type) {
+       case grp2_1:
+               gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1);
+               dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg);
+               break;
+       case grp2_imm: {
+               Bit8u imm=decode_fetchb();
+               if (imm) {
+                       gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f);
+                       dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg);
+               } else return;
+               }
+               break;
+       case grp2_cl:
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0);
+               gen_and_imm(FC_OP2,0x1f);
+               dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg);
+               break;
+       }
+       if (decode.modrm.mod<3) {
+               gen_restore_addr_reg();
+               dyn_write_byte(FC_ADDR,FC_RETOP);
+       } else {
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+
+static void dyn_grp2_ev(grp2_types type) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+       switch (type) {
+       case grp2_1:
+               gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1);
+               dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op);
+               break;
+       case grp2_imm: {
+               Bitu val;
+               if (decode_fetchb_imm(val)) {
+                       gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val);
+                       gen_and_imm(FC_OP2,0x1f);
+                       dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op);
+                       break;
+               }
+               Bit8u imm=(Bit8u)val;
+               if (imm) {
+                       gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f);
+                       dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op);
+               } else return;
+               }
+               break;
+       case grp2_cl:
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP2,DRC_REG_ECX,0);
+               gen_and_imm(FC_OP2,0x1f);
+               dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op);
+               break;
+       }
+       if (decode.modrm.mod<3) {
+               gen_restore_addr_reg();
+               dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
+       } else {
+               MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op);
+       }
+}
+
+
+static void dyn_grp3_eb(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg();
+               dyn_read_byte_canuseword(FC_ADDR,FC_OP1);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+       switch (decode.modrm.reg) {
+       case 0x0:       // test eb,ib
+               gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb());
+               dyn_dop_byte_gencall(DOP_TEST);
+               return;
+       case 0x2:       // NOT Eb
+               dyn_sop_byte_gencall(SOP_NOT);
+               break;
+       case 0x3:       // NEG Eb
+               dyn_sop_byte_gencall(SOP_NEG);
+               break;
+       case 0x4:       // mul Eb
+               gen_call_function_raw((void*)&dynrec_mul_byte);
+               return;
+       case 0x5:       // imul Eb
+               gen_call_function_raw((void*)&dynrec_imul_byte);
+               return;
+       case 0x6:       // div Eb
+               gen_call_function_raw((void*)&dynrec_div_byte);
+               dyn_check_exception(FC_RETOP);
+               return;
+       case 0x7:       // idiv Eb
+               gen_call_function_raw((void*)&dynrec_idiv_byte);
+               dyn_check_exception(FC_RETOP);
+               return;
+       }
+       // Save the result if memory op
+       if (decode.modrm.mod<3) {
+               gen_restore_addr_reg();
+               dyn_write_byte(FC_ADDR,FC_RETOP);
+       } else {
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+
+static void dyn_grp3_ev(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+       switch (decode.modrm.reg) {
+       case 0x0:       // test ev,iv
+               if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,decode_fetchd());
+               else gen_mov_word_to_reg_imm(FC_OP2,decode_fetchw());
+               dyn_dop_word_gencall(DOP_TEST,decode.big_op);
+               return;
+       case 0x2:       // NOT Ev
+               dyn_sop_word_gencall(SOP_NOT,decode.big_op);
+               break;
+       case 0x3:       // NEG Eb
+               dyn_sop_word_gencall(SOP_NEG,decode.big_op);
+               break;
+       case 0x4:       // mul Eb
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_mul_dword);
+               else gen_call_function_raw((void*)&dynrec_mul_word);
+               return;
+       case 0x5:       // imul Eb
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_imul_dword);
+               else gen_call_function_raw((void*)&dynrec_imul_word);
+               return;
+       case 0x6:       // div Eb
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_div_dword);
+               else gen_call_function_raw((void*)&dynrec_div_word);
+               dyn_check_exception(FC_RETOP);
+               return;
+       case 0x7:       // idiv Eb
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_idiv_dword);
+               else gen_call_function_raw((void*)&dynrec_idiv_word);
+               dyn_check_exception(FC_RETOP);
+               return;
+       }
+       // Save the result if memory op
+       if (decode.modrm.mod<3) {
+               gen_restore_addr_reg();
+               dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
+       } else {
+               MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op);
+       }
+}
+
+
+static bool dyn_grp4_eb(void) {
+       dyn_get_modrm();
+       switch (decode.modrm.reg) {
+       case 0x0://INC Eb
+       case 0x1://DEC Eb
+               if (decode.modrm.mod<3) {
+                       dyn_fill_ea(FC_ADDR);
+                       gen_protect_addr_reg();
+                       dyn_read_byte_canuseword(FC_ADDR,FC_OP1);
+                       dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC);
+                       gen_restore_addr_reg();
+                       dyn_write_byte(FC_ADDR,FC_RETOP);
+               } else {
+                       MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+                       dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC);
+                       MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+               }
+               break;
+       case 0x7:               //CALBACK Iw
+               gen_mov_direct_dword(&core_dynrec.callback,decode_fetchw());
+               dyn_set_eip_end();
+               dyn_reduce_cycles();
+               dyn_return(BR_CallBack);
+               dyn_closeblock();
+               return true;
+       default:
+               IllegalOptionDynrec("dyn_grp4_eb");
+               break;
+       }
+       return false;
+}
+
+static Bitu dyn_grp4_ev(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               if ((decode.modrm.reg<2) || (decode.modrm.reg==3) || (decode.modrm.reg==5))  gen_protect_addr_reg();
+               dyn_read_word(FC_ADDR,FC_OP1,decode.big_op);
+       } else {
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,decode.modrm.rm,decode.big_op);
+       }
+       switch (decode.modrm.reg) {
+       case 0x0://INC Ev
+       case 0x1://DEC Ev
+               dyn_sop_word_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op);
+               if (decode.modrm.mod<3) {
+                       gen_restore_addr_reg();
+                       dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
+               } else {
+                       MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,decode.modrm.rm,decode.big_op);
+               }
+               break;
+       case 0x2:       // CALL Ev
+               gen_mov_regs(FC_ADDR,FC_OP1);
+               gen_protect_addr_reg();
+               gen_mov_word_to_reg(FC_OP1,decode.big_op?(void*)(&reg_eip):(void*)(&reg_ip),decode.big_op);
+               gen_add_imm(FC_OP1,(Bit32u)(decode.code-decode.code_start));
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword);
+               else gen_call_function_raw((void*)&dynrec_push_word);
+
+               gen_restore_addr_reg();
+               gen_mov_word_from_reg(FC_ADDR,decode.big_op?(void*)(&reg_eip):(void*)(&reg_ip),decode.big_op);
+               return 1;
+       case 0x4:       // JMP Ev
+               gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(&reg_eip):(void*)(&reg_ip),decode.big_op);
+               return 1;
+       case 0x3:       // CALL Ep
+       case 0x5:       // JMP Ep
+               if (!decode.big_op) gen_extend_word(false,FC_OP1);
+               if (decode.modrm.mod<3) gen_restore_addr_reg();
+               gen_protect_reg(FC_OP1);
+               gen_add_imm(FC_ADDR,decode.big_op?4:2);
+               dyn_read_word(FC_ADDR,FC_OP2,decode.big_op);
+               gen_extend_word(false,FC_OP2);
+
+               dyn_set_eip_last_end(FC_RETOP);
+               gen_restore_reg(FC_OP1,FC_ADDR);
+               gen_call_function_IRRR(decode.modrm.reg == 3 ? (void*)(&CPU_CALL) : (void*)(&CPU_JMP),
+                       decode.big_op,FC_OP2,FC_ADDR,FC_RETOP);
+               return 1;
+       case 0x6:               // PUSH Ev
+               if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword);
+               else gen_call_function_raw((void*)&dynrec_push_word);
+               break;
+       default:
+//             IllegalOptionDynrec("dyn_grp4_ev");
+               return 2;
+       }
+       return 0;
+}
+
+
+static bool dyn_grp6(void) {
+       dyn_get_modrm();
+       switch (decode.modrm.reg) {
+               case 0x00:      // SLDT
+               case 0x01:      // STR
+                       if (decode.modrm.reg==0) gen_call_function_raw((void*)CPU_SLDT);
+                       else gen_call_function_raw((void*)CPU_STR);
+                       if (decode.modrm.mod<3) {
+                               dyn_fill_ea(FC_ADDR);
+                               dyn_write_word(FC_ADDR,FC_RETOP,false);
+                       } else {
+                               MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm);
+                       }
+                       break;
+               case 0x02:      // LLDT
+               case 0x03:      // LTR
+               case 0x04:      // VERR
+               case 0x05:      // VERW
+                       if (decode.modrm.mod<3) {
+                               dyn_fill_ea(FC_ADDR);
+                               dyn_read_word(FC_ADDR,FC_RETOP,false);
+                       } else {
+                               MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm);
+                       }
+                       gen_extend_word(false,FC_RETOP);
+                       switch (decode.modrm.reg) {
+                               case 0x02:      // LLDT
+//                                     if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0);
+                                       if (cpu.cpl) E_Exit("lldt cpl>0");
+                                       gen_call_function_R((void*)CPU_LLDT,FC_RETOP);
+                                       dyn_check_exception(FC_RETOP);
+                                       break;
+                               case 0x03:      // LTR
+//                                     if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0);
+                                       if (cpu.cpl) E_Exit("ltr cpl>0");
+                                       gen_call_function_R((void*)CPU_LTR,FC_RETOP);
+                                       dyn_check_exception(FC_RETOP);
+                                       break;
+                               case 0x04:      // VERR
+                                       gen_call_function_R((void*)CPU_VERR,FC_RETOP);
+                                       break;
+                               case 0x05:      // VERW
+                                       gen_call_function_R((void*)CPU_VERW,FC_RETOP);
+                                       break;
+                       }
+                       break;
+               default: IllegalOptionDynrec("dyn_grp6");
+       }
+       return false;
+}
+
+static bool dyn_grp7(void) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               switch (decode.modrm.reg) {
+                       case 0x00:      // SGDT
+                               gen_call_function_raw((void*)CPU_SGDT_limit);
+                               dyn_fill_ea(FC_ADDR);
+                               gen_protect_addr_reg();
+                               dyn_write_word(FC_ADDR,FC_RETOP,false);
+                               gen_call_function_raw((void*)CPU_SGDT_base);
+                               gen_restore_addr_reg();
+                               gen_add_imm(FC_ADDR,2);
+                               dyn_write_word(FC_ADDR,FC_RETOP,true);
+                               break;
+                       case 0x01:      // SIDT
+                               gen_call_function_raw((void*)CPU_SIDT_limit);
+                               dyn_fill_ea(FC_ADDR);
+                               gen_protect_addr_reg();
+                               dyn_write_word(FC_ADDR,FC_RETOP,false);
+                               gen_call_function_raw((void*)CPU_SIDT_base);
+                               gen_restore_addr_reg();
+                               gen_add_imm(FC_ADDR,2);
+                               dyn_write_word(FC_ADDR,FC_RETOP,true);
+                               break;
+                       case 0x02:      // LGDT
+                       case 0x03:      // LIDT
+//                             if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                               if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("lgdt nonpriviledged");
+                               dyn_fill_ea(FC_ADDR);
+                               gen_protect_addr_reg();
+                               dyn_read_word(FC_ADDR,FC_OP1,false);
+                               gen_extend_word(false,FC_OP1);
+                               gen_protect_reg(FC_OP1);
+
+                               gen_restore_addr_reg();
+                               gen_add_imm(FC_ADDR,2);
+                               dyn_read_word(FC_ADDR,FC_OP2,true);
+                               if (!decode.big_op) gen_and_imm(FC_OP2,0xffffff);
+
+                               gen_restore_reg(FC_OP1);
+                               if (decode.modrm.reg==2) gen_call_function_RR((void*)CPU_LGDT,FC_OP1,FC_OP2);
+                               else gen_call_function_RR((void*)CPU_LIDT,FC_OP1,FC_OP2);
+                               break;
+                       case 0x04:      // SMSW
+                               gen_call_function_raw((void*)CPU_SMSW);
+                               dyn_fill_ea(FC_ADDR);
+                               dyn_write_word(FC_ADDR,FC_RETOP,false);
+                               break;
+                       case 0x06:      // LMSW
+                               dyn_fill_ea(FC_ADDR);
+                               dyn_read_word(FC_ADDR,FC_RETOP,false);
+                               gen_call_function_R((void*)CPU_LMSW,FC_RETOP);
+                               dyn_check_exception(FC_RETOP);
+                               dyn_set_eip_end();
+                               dyn_reduce_cycles();
+                               dyn_return(BR_Normal);
+                               dyn_closeblock();
+                               return true;
+                       case 0x07:      // INVLPG
+//                             if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                               if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("invlpg nonpriviledged");
+                               gen_call_function_raw((void*)PAGING_ClearTLB);
+                               break;
+                       default: IllegalOptionDynrec("dyn_grp7_1");
+               }
+       } else {
+               switch (decode.modrm.reg) {
+                       case 0x04:      // SMSW
+                               gen_call_function_raw((void*)CPU_SMSW);
+                               MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,decode.modrm.rm);
+                               break;
+                       case 0x06:      // LMSW
+                               MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm);
+                               gen_call_function_R((void*)CPU_LMSW,FC_RETOP);
+                               dyn_check_exception(FC_RETOP);
+                               dyn_set_eip_end();
+                               dyn_reduce_cycles();
+                               dyn_return(BR_Normal);
+                               dyn_closeblock();
+                               return true;
+                       default: IllegalOptionDynrec("dyn_grp7_2");
+               }
+       }
+       return false;
+}
+
+
+/*
+static void dyn_larlsl(bool is_lar) {
+       dyn_get_modrm();
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_read_word(FC_ADDR,FC_RETOP,false);
+       } else {
+               MOV_REG_WORD16_TO_HOST_REG(FC_RETOP,decode.modrm.rm);
+       }
+       gen_extend_word(false,FC_RETOP);
+       if (is_lar) gen_call_function((void*)CPU_LAR,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata);
+       else gen_call_function((void*)CPU_LSL,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata);
+       DRC_PTR_SIZE_IM brnz=gen_create_branch_on_nonzero(FC_RETOP,true);
+       gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true);
+       MOV_REG_WORD_FROM_HOST_REG(FC_OP2,decode.modrm.reg,decode.big_op);
+       gen_fill_branch(brnz);
+}
+*/
+
+
+static void dyn_mov_from_crx(void) {
+       dyn_get_modrm();
+       gen_call_function_IA((void*)CPU_READ_CRX,decode.modrm.reg,(DRC_PTR_SIZE_IM)&core_dynrec.readdata);
+       dyn_check_exception(FC_RETOP);
+       gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true);
+       MOV_REG_WORD32_FROM_HOST_REG(FC_OP2,decode.modrm.rm);
+}
+
+static void dyn_mov_to_crx(void) {
+       dyn_get_modrm();
+       MOV_REG_WORD32_TO_HOST_REG(FC_RETOP,decode.modrm.rm);
+       gen_call_function_IR((void*)CPU_WRITE_CRX,decode.modrm.reg,FC_RETOP);
+       dyn_check_exception(FC_RETOP);
+       dyn_set_eip_end();
+       dyn_reduce_cycles();
+       dyn_return(BR_Normal);
+       dyn_closeblock();
+}
+
+
+static void dyn_cbw(void) {
+       if (decode.big_op) {
+               MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX);
+               gen_call_function_raw((void *)&dynrec_cwde);
+               MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX);
+       } else {
+               MOV_REG_BYTE_TO_HOST_REG_LOW_CANUSEWORD(FC_OP1,DRC_REG_EAX,0);
+               gen_call_function_raw((void *)&dynrec_cbw);
+               MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX);
+       }
+}
+
+static void dyn_cwd(void) {
+       MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_EAX,decode.big_op);
+       if (decode.big_op) {
+               gen_call_function_raw((void *)&dynrec_cdq);
+               MOV_REG_WORD32_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX);
+       } else {
+               gen_call_function_raw((void *)&dynrec_cwd);
+               MOV_REG_WORD16_FROM_HOST_REG(FC_RETOP,DRC_REG_EDX);
+       }
+}
+
+static void dyn_sahf(void) {
+       MOV_REG_WORD16_TO_HOST_REG(FC_OP1,DRC_REG_EAX);
+       gen_call_function_raw((void *)&dynrec_sahf);
+       InvalidateFlags();
+}
+
+
+static void dyn_exit_link(Bits eip_change) {
+       gen_add_direct_word(&reg_eip,(decode.code-decode.code_start)+eip_change,decode.big_op);
+       dyn_reduce_cycles();
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));
+       dyn_closeblock();
+}
+
+
+static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) {
+       Bitu eip_base=decode.code-decode.code_start;
+       dyn_reduce_cycles();
+
+       dyn_branchflag_to_reg(btype);
+       DRC_PTR_SIZE_IM data=gen_create_branch_on_nonzero(FC_RETOP,true);
+
+       // Branch not taken
+       gen_add_direct_word(&reg_eip,eip_base,decode.big_op);
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));
+       gen_fill_branch(data);
+
+       // Branch taken
+       gen_add_direct_word(&reg_eip,eip_base+eip_add,decode.big_op);
+       gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start));
+       dyn_closeblock();
+}
+
+/*
+static void dyn_set_byte_on_condition(BranchTypes btype) {
+       dyn_get_modrm();
+       dyn_branchflag_to_reg(btype);
+       gen_and_imm(FC_RETOP,1);
+       if (decode.modrm.mod<3) {
+               dyn_fill_ea(FC_ADDR);
+               dyn_write_byte(FC_ADDR,FC_RETOP);
+       } else {
+               MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,decode.modrm.rm&3,(decode.modrm.rm>>2)&1);
+       }
+}
+*/
+
+static void dyn_loop(LoopTypes type) {
+       dyn_reduce_cycles();
+       Bits eip_add=(Bit8s)decode_fetchb();
+       Bitu eip_base=decode.code-decode.code_start;
+       DRC_PTR_SIZE_IM branch1=0;
+       DRC_PTR_SIZE_IM branch2=0;
+       switch (type) {
+       case LOOP_E:
+               dyn_branchflag_to_reg(BR_NZ);
+               branch1=gen_create_branch_on_nonzero(FC_RETOP,true);
+               break;
+       case LOOP_NE:
+               dyn_branchflag_to_reg(BR_Z);
+               branch1=gen_create_branch_on_nonzero(FC_RETOP,true);
+               break;
+       }
+       switch (type) {
+       case LOOP_E:
+       case LOOP_NE:
+       case LOOP_NONE:
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr);
+               gen_add_imm(FC_OP1,(Bit32u)(-1));
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr);
+               branch2=gen_create_branch_on_zero(FC_OP1,decode.big_addr);
+               break;
+       case LOOP_JCXZ:
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr);
+               branch2=gen_create_branch_on_nonzero(FC_OP1,decode.big_addr);
+               break;
+       }
+       gen_add_direct_word(&reg_eip,eip_base+eip_add,true);
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));
+       if (branch1) {
+               gen_fill_branch(branch1);
+               MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr);
+               gen_add_imm(FC_OP1,(Bit32u)(-1));
+               MOV_REG_WORD_FROM_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr);
+       }
+       // Branch taken
+       gen_fill_branch(branch2);
+       gen_add_direct_word(&reg_eip,eip_base,decode.big_op);
+       gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start));
+       dyn_closeblock();
+}
+
+
+static void dyn_ret_near(Bitu bytes) {
+       dyn_reduce_cycles();
+
+       if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword);
+       else {
+               gen_call_function_raw((void*)&dynrec_pop_word);
+               gen_extend_word(false,FC_RETOP);
+       }
+       gen_mov_word_from_reg(FC_RETOP,decode.big_op?(void*)(&reg_eip):(void*)(&reg_ip),true);
+
+       if (bytes) gen_add_direct_word(&reg_esp,bytes,true);
+       dyn_return(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_call_near_imm(void) {
+       Bits imm;
+       if (decode.big_op) imm=(Bit32s)decode_fetchd();
+       else imm=(Bit16s)decode_fetchw();
+       dyn_set_eip_end(FC_OP1);
+       if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword);
+       else gen_call_function_raw((void*)&dynrec_push_word);
+
+       dyn_set_eip_end(FC_OP1,imm);
+       gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(&reg_eip):(void*)(&reg_ip),decode.big_op);
+
+       dyn_reduce_cycles();
+       gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start));
+       dyn_closeblock();
+}
+
+static void dyn_ret_far(Bitu bytes) {
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(FC_RETOP);
+       gen_call_function_IIR((void*)&CPU_RET,decode.big_op,bytes,FC_RETOP);
+       dyn_return(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_call_far_imm(void) {
+       Bitu sel,off;
+       off=decode.big_op ? decode_fetchd() : decode_fetchw();
+       sel=decode_fetchw();
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(FC_RETOP);
+       gen_call_function_IIIR((void*)&CPU_CALL,decode.big_op,sel,off,FC_RETOP);
+       dyn_return(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_jmp_far_imm(void) {
+       Bitu sel,off;
+       off=decode.big_op ? decode_fetchd() : decode_fetchw();
+       sel=decode_fetchw();
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(FC_RETOP);
+       gen_call_function_IIIR((void*)&CPU_JMP,decode.big_op,sel,off,FC_RETOP);
+       dyn_return(BR_Normal);
+       dyn_closeblock();
+}
+
+static void dyn_iret(void) {
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(FC_RETOP);
+       gen_call_function_IR((void*)&CPU_IRET,decode.big_op,FC_RETOP);
+       dyn_return(BR_Iret);
+       dyn_closeblock();
+}
+
+static void dyn_interrupt(Bit8u num) {
+       dyn_reduce_cycles();
+       dyn_set_eip_last_end(FC_RETOP);
+       gen_call_function_IIR((void*)&CPU_Interrupt,num,CPU_INT_SOFTWARE,FC_RETOP);
+       dyn_return(BR_Normal);
+       dyn_closeblock();
+}
+
+
+
+static void dyn_string(StringOps op) {
+       if (decode.rep) MOV_REG_WORD_TO_HOST_REG(FC_OP1,DRC_REG_ECX,decode.big_addr);
+       else gen_mov_dword_to_reg_imm(FC_OP1,1);
+       gen_mov_word_to_reg(FC_OP2,&cpu.direction,true);
+       Bit8u di_base_addr=decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS;
+       switch (op) {
+               case STR_MOVSB:
+                       if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       else gen_call_function_mm((void*)&dynrec_movsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       break;
+               case STR_MOVSW:
+                       if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       else gen_call_function_mm((void*)&dynrec_movsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       break;
+               case STR_MOVSD:
+                       if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       else gen_call_function_mm((void*)&dynrec_movsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       break;
+
+               case STR_LODSB:
+                       if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr));
+                       else gen_call_function_m((void*)&dynrec_lodsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr));
+                       break;
+               case STR_LODSW:
+                       if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr));
+                       else gen_call_function_m((void*)&dynrec_lodsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr));
+                       break;
+               case STR_LODSD:
+                       if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr));
+                       else gen_call_function_m((void*)&dynrec_lodsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr));
+                       break;
+
+               case STR_STOSB:
+                       if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosb_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       else gen_call_function_m((void*)&dynrec_stosb_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       break;
+               case STR_STOSW:
+                       if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosw_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       else gen_call_function_m((void*)&dynrec_stosw_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       break;
+               case STR_STOSD:
+                       if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosd_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       else gen_call_function_m((void*)&dynrec_stosd_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES));
+                       break;
+               default: IllegalOptionDynrec("dyn_string");
+       }
+       if (decode.rep) MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_ECX,decode.big_addr);
+
+       if (op<STR_SCASB) {
+               // those string operations are allowed for premature termination
+               // when not enough cycles left
+               if (!decode.big_addr) gen_extend_word(false,FC_RETOP);
+               save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_nonzero(FC_RETOP,true);
+               save_info_dynrec[used_save_info_dynrec].eip_change=decode.op_start-decode.code_start;
+               save_info_dynrec[used_save_info_dynrec].type=string_break;
+               used_save_info_dynrec++;
+       }
+}
+
+
+static void dyn_read_port_byte_direct(Bit8u port) {
+       dyn_add_iocheck_var(port,1);
+       gen_call_function_I((void*)&IO_ReadB,port);
+       MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0);
+}
+
+static void dyn_read_port_word_direct(Bit8u port) {
+       dyn_add_iocheck_var(port,decode.big_op?4:2);
+       gen_call_function_I(decode.big_op?((void*)&IO_ReadD):((void*)&IO_ReadW),port);
+       MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op);
+}
+
+static void dyn_write_port_byte_direct(Bit8u port) {
+       dyn_add_iocheck_var(port,1);
+       MOV_REG_BYTE_TO_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0);
+       gen_extend_byte(false,FC_RETOP);
+       gen_call_function_IR((void*)&IO_WriteB,port,FC_RETOP);
+}
+
+static void dyn_write_port_word_direct(Bit8u port) {
+       dyn_add_iocheck_var(port,decode.big_op?4:2);
+       MOV_REG_WORD_TO_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op);
+       if (!decode.big_op) gen_extend_word(false,FC_RETOP);
+       gen_call_function_IR(decode.big_op?((void*)&IO_WriteD):((void*)&IO_WriteW),port,FC_RETOP);
+}
+
+
+static void dyn_read_port_byte(void) {
+       MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX);
+       gen_extend_word(false,FC_ADDR);
+       gen_protect_addr_reg();
+       dyn_add_iocheck(FC_ADDR,1);
+       gen_restore_addr_reg();
+       gen_call_function_R((void*)&IO_ReadB,FC_ADDR);
+       MOV_REG_BYTE_FROM_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0);
+}
+
+static void dyn_read_port_word(void) {
+       MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX);
+       gen_extend_word(false,FC_ADDR);
+       gen_protect_addr_reg();
+       dyn_add_iocheck(FC_ADDR,decode.big_op?4:2);
+       gen_restore_addr_reg();
+       gen_call_function_R(decode.big_op?((void*)&IO_ReadD):((void*)&IO_ReadW),FC_ADDR);
+       MOV_REG_WORD_FROM_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op);
+}
+
+static void dyn_write_port_byte(void) {
+       MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX);
+       gen_extend_word(false,FC_ADDR);
+       gen_protect_addr_reg();
+       dyn_add_iocheck(FC_ADDR,1);
+       MOV_REG_BYTE_TO_HOST_REG_LOW(FC_RETOP,DRC_REG_EAX,0);
+       gen_extend_byte(false,FC_RETOP);
+       gen_restore_addr_reg();
+       gen_call_function_RR((void*)&IO_WriteB,FC_ADDR,FC_RETOP);
+}
+
+static void dyn_write_port_word(void) {
+       MOV_REG_WORD16_TO_HOST_REG(FC_ADDR,DRC_REG_EDX);
+       gen_extend_word(false,FC_ADDR);
+       gen_protect_addr_reg();
+       dyn_add_iocheck(FC_ADDR,decode.big_op?4:2);
+       MOV_REG_WORD_TO_HOST_REG(FC_RETOP,DRC_REG_EAX,decode.big_op);
+       if (!decode.big_op) gen_extend_word(false,FC_RETOP);
+       gen_restore_addr_reg();
+       gen_call_function_RR(decode.big_op?((void*)&IO_WriteD):((void*)&IO_WriteW),FC_ADDR,FC_RETOP);
+}
+
+
+static void dyn_enter(void) {
+       Bitu bytes=decode_fetchw();
+       Bitu level=decode_fetchb();
+       gen_call_function_III((void *)&CPU_ENTER,decode.big_op,bytes,level);
+}
+
+static void dynrec_leave_word(void) {
+       reg_esp&=cpu.stack.notmask;
+       reg_esp|=(reg_ebp&cpu.stack.mask);
+       reg_bp=(Bit16u)CPU_Pop16();
+}
+
+static void dynrec_leave_dword(void) {
+       reg_esp&=cpu.stack.notmask;
+       reg_esp|=(reg_ebp&cpu.stack.mask);
+       reg_ebp=CPU_Pop32();
+}
+
+static void dyn_leave(void) {
+       if (decode.big_op) gen_call_function_raw((void *)dynrec_leave_dword);
+       else gen_call_function_raw((void *)dynrec_leave_word);
+}
+
+
+static void dynrec_pusha_word(void) {
+       Bit16u old_sp=reg_sp;
+       CPU_Push16(reg_ax);CPU_Push16(reg_cx);CPU_Push16(reg_dx);CPU_Push16(reg_bx);
+       CPU_Push16(old_sp);CPU_Push16(reg_bp);CPU_Push16(reg_si);CPU_Push16(reg_di);
+}
+
+static void dynrec_pusha_dword(void) {
+       Bitu tmpesp = reg_esp;
+       CPU_Push32(reg_eax);CPU_Push32(reg_ecx);CPU_Push32(reg_edx);CPU_Push32(reg_ebx);
+       CPU_Push32(tmpesp);CPU_Push32(reg_ebp);CPU_Push32(reg_esi);CPU_Push32(reg_edi);
+}
+
+static void dynrec_popa_word(void) {
+       reg_di=(Bit16u)CPU_Pop16();reg_si=(Bit16u)CPU_Pop16();
+       reg_bp=(Bit16u)CPU_Pop16();CPU_Pop16();         //Don't save SP
+       reg_bx=(Bit16u)CPU_Pop16();reg_dx=(Bit16u)CPU_Pop16();
+       reg_cx=(Bit16u)CPU_Pop16();reg_ax=(Bit16u)CPU_Pop16();
+}
+
+static void dynrec_popa_dword(void) {
+       reg_edi=CPU_Pop32();reg_esi=CPU_Pop32();reg_ebp=CPU_Pop32();CPU_Pop32();        //Don't save ESP
+       reg_ebx=CPU_Pop32();reg_edx=CPU_Pop32();reg_ecx=CPU_Pop32();reg_eax=CPU_Pop32();
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/dyn_fpu.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/dyn_fpu.h
new file mode 100644 (file)
index 0000000..c410ebd
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+#include "dosbox.h"
+#if C_FPU
+
+#include <math.h>
+#include <float.h>
+#include "cross.h"
+#include "mem.h"
+#include "fpu.h"
+#include "cpu.h"
+
+
+static void FPU_FDECSTP(){
+       TOP = (TOP - 1) & 7;
+}
+
+static void FPU_FINCSTP(){
+       TOP = (TOP + 1) & 7;
+}
+
+static void FPU_FNSTCW(PhysPt addr){
+       mem_writew(addr,fpu.cw);
+}
+
+static void FPU_FFREE(Bitu st) {
+       fpu.tags[st]=TAG_Empty;
+}
+
+
+#if C_FPU_X86
+#include "../../fpu/fpu_instructions_x86.h"
+#else
+#include "../../fpu/fpu_instructions.h"
+#endif
+
+
+static INLINE void dyn_fpu_top() {
+       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+       gen_add_imm(FC_OP2,decode.modrm.rm);
+       gen_and_imm(FC_OP2,7);
+       gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+}
+
+static INLINE void dyn_fpu_top_swapped() {
+       gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+       gen_add_imm(FC_OP1,decode.modrm.rm);
+       gen_and_imm(FC_OP1,7);
+       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+}
+
+static void dyn_eatree() {
+       Bitu group=(decode.modrm.val >> 3) & 7;
+       switch (group){
+       case 0x00:              // FADD ST,STi
+               gen_call_function_R((void*)&FPU_FADD_EA,FC_OP1);
+               break;
+       case 0x01:              // FMUL  ST,STi
+               gen_call_function_R((void*)&FPU_FMUL_EA,FC_OP1);
+               break;
+       case 0x02:              // FCOM  STi
+               gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1);
+               break;
+       case 0x03:              // FCOMP STi
+               gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1);
+               gen_call_function_raw((void*)&FPU_FPOP);
+               break;
+       case 0x04:              // FSUB  ST,STi
+               gen_call_function_R((void*)&FPU_FSUB_EA,FC_OP1);
+               break;  
+       case 0x05:              // FSUBR ST,STi
+               gen_call_function_R((void*)&FPU_FSUBR_EA,FC_OP1);
+               break;
+       case 0x06:              // FDIV  ST,STi
+               gen_call_function_R((void*)&FPU_FDIV_EA,FC_OP1);
+               break;
+       case 0x07:              // FDIVR ST,STi
+               gen_call_function_R((void*)&FPU_FDIVR_EA,FC_OP1);
+               break;
+       default:
+               break;
+       }
+}
+
+static void dyn_fpu_esc0(){
+       dyn_get_modrm(); 
+       if (decode.modrm.val >= 0xc0) { 
+               dyn_fpu_top();
+               switch (decode.modrm.reg){
+               case 0x00:              //FADD ST,STi
+                       gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2);
+                       break;
+               case 0x01:              // FMUL  ST,STi
+                       gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2);
+                       break;
+               case 0x02:              // FCOM  STi
+                       gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
+                       break;
+               case 0x03:              // FCOMP STi
+                       gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x04:              // FSUB  ST,STi
+                       gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2);
+                       break;  
+               case 0x05:              // FSUBR ST,STi
+                       gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2);
+                       break;
+               case 0x06:              // FDIV  ST,STi
+                       gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2);
+                       break;
+               case 0x07:              // FDIVR ST,STi
+                       gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2);
+                       break;
+               default:
+                       break;
+               }
+       } else { 
+               dyn_fill_ea(FC_ADDR);
+               gen_call_function_R((void*)&FPU_FLD_F32_EA,FC_ADDR); 
+               gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+               dyn_eatree();
+       }
+}
+
+
+static void dyn_fpu_esc1(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               switch (decode.modrm.reg){
+               case 0x00: /* FLD STi */
+                       gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+                       gen_add_imm(FC_OP1,decode.modrm.rm);
+                       gen_and_imm(FC_OP1,7);
+                       gen_protect_reg(FC_OP1);
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH); 
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_restore_reg(FC_OP1);
+                       gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
+                       break;
+               case 0x01: /* FXCH STi */
+                       dyn_fpu_top();
+                       gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2);
+                       break;
+               case 0x02: /* FNOP */
+                       gen_call_function_raw((void*)&FPU_FNOP);
+                       break;
+               case 0x03: /* FSTP STi */
+                       dyn_fpu_top();
+                       gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;   
+               case 0x04:
+                       switch(decode.modrm.rm){
+                       case 0x00:       /* FCHS */
+                               gen_call_function_raw((void*)&FPU_FCHS);
+                               break;
+                       case 0x01:       /* FABS */
+                               gen_call_function_raw((void*)&FPU_FABS);
+                               break;
+                       case 0x02:       /* UNKNOWN */
+                       case 0x03:       /* ILLEGAL */
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
+                               break;
+                       case 0x04:       /* FTST */
+                               gen_call_function_raw((void*)&FPU_FTST);
+                               break;
+                       case 0x05:       /* FXAM */
+                               gen_call_function_raw((void*)&FPU_FXAM);
+                               break;
+                       case 0x06:       /* FTSTP (cyrix)*/
+                       case 0x07:       /* UNKNOWN */
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
+                               break;
+                       }
+                       break;
+               case 0x05:
+                       switch(decode.modrm.rm){        
+                       case 0x00:       /* FLD1 */
+                               gen_call_function_raw((void*)&FPU_FLD1);
+                               break;
+                       case 0x01:       /* FLDL2T */
+                               gen_call_function_raw((void*)&FPU_FLDL2T);
+                               break;
+                       case 0x02:       /* FLDL2E */
+                               gen_call_function_raw((void*)&FPU_FLDL2E);
+                               break;
+                       case 0x03:       /* FLDPI */
+                               gen_call_function_raw((void*)&FPU_FLDPI);
+                               break;
+                       case 0x04:       /* FLDLG2 */
+                               gen_call_function_raw((void*)&FPU_FLDLG2);
+                               break;
+                       case 0x05:       /* FLDLN2 */
+                               gen_call_function_raw((void*)&FPU_FLDLN2);
+                               break;
+                       case 0x06:       /* FLDZ*/
+                               gen_call_function_raw((void*)&FPU_FLDZ);
+                               break;
+                       case 0x07:       /* ILLEGAL */
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
+                               break;
+                       }
+                       break;
+               case 0x06:
+                       switch(decode.modrm.rm){
+                       case 0x00:      /* F2XM1 */
+                               gen_call_function_raw((void*)&FPU_F2XM1);
+                               break;
+                       case 0x01:      /* FYL2X */
+                               gen_call_function_raw((void*)&FPU_FYL2X);
+                               break;
+                       case 0x02:      /* FPTAN  */
+                               gen_call_function_raw((void*)&FPU_FPTAN);
+                               break;
+                       case 0x03:      /* FPATAN */
+                               gen_call_function_raw((void*)&FPU_FPATAN);
+                               break;
+                       case 0x04:      /* FXTRACT */
+                               gen_call_function_raw((void*)&FPU_FXTRACT);
+                               break;
+                       case 0x05:      /* FPREM1 */
+                               gen_call_function_raw((void*)&FPU_FPREM1);
+                               break;
+                       case 0x06:      /* FDECSTP */
+                               gen_call_function_raw((void*)&FPU_FDECSTP);
+                               break;
+                       case 0x07:      /* FINCSTP */
+                               gen_call_function_raw((void*)&FPU_FINCSTP);
+                               break;
+                       default:
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
+                               break;
+                       }
+                       break;
+               case 0x07:
+                       switch(decode.modrm.rm){
+                       case 0x00:              /* FPREM */
+                               gen_call_function_raw((void*)&FPU_FPREM);
+                               break;
+                       case 0x01:              /* FYL2XP1 */
+                               gen_call_function_raw((void*)&FPU_FYL2XP1);
+                               break;
+                       case 0x02:              /* FSQRT */
+                               gen_call_function_raw((void*)&FPU_FSQRT);
+                               break;
+                       case 0x03:              /* FSINCOS */
+                               gen_call_function_raw((void*)&FPU_FSINCOS);
+                               break;
+                       case 0x04:              /* FRNDINT */
+                               gen_call_function_raw((void*)&FPU_FRNDINT);
+                               break;
+                       case 0x05:              /* FSCALE */
+                               gen_call_function_raw((void*)&FPU_FSCALE);
+                               break;
+                       case 0x06:              /* FSIN */
+                               gen_call_function_raw((void*)&FPU_FSIN);
+                               break;
+                       case 0x07:              /* FCOS */
+                               gen_call_function_raw((void*)&FPU_FCOS);
+                               break;
+                       default:
+                               LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
+                               break;
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               }
+       } else {
+               switch(decode.modrm.reg){
+               case 0x00: /* FLD float*/
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH);
+                       dyn_fill_ea(FC_OP1);
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_call_function_RR((void*)&FPU_FLD_F32,FC_OP1,FC_OP2);
+                       break;
+               case 0x01: /* UNKNOWN */
+                       LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               case 0x02: /* FST float*/
+                       dyn_fill_ea(FC_ADDR);
+                       gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR);
+                       break;
+               case 0x03: /* FSTP float*/
+                       dyn_fill_ea(FC_ADDR);
+                       gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x04: /* FLDENV */
+                       dyn_fill_ea(FC_ADDR);
+                       gen_call_function_R((void*)&FPU_FLDENV,FC_ADDR);
+                       break;
+               case 0x05: /* FLDCW */
+                       dyn_fill_ea(FC_ADDR);
+                       gen_call_function_R((void *)&FPU_FLDCW,FC_ADDR);
+                       break;
+               case 0x06: /* FSTENV */
+                       dyn_fill_ea(FC_ADDR);
+                       gen_call_function_R((void *)&FPU_FSTENV,FC_ADDR);
+                       break;
+               case 0x07:  /* FNSTCW*/
+                       dyn_fill_ea(FC_ADDR);
+                       gen_call_function_R((void *)&FPU_FNSTCW,FC_ADDR);
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               }
+       }
+}
+
+static void dyn_fpu_esc2(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               switch(decode.modrm.reg){
+               case 0x05:
+                       switch(decode.modrm.rm){
+                       case 0x01:              /* FUCOMPP */
+                               gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                               gen_add_imm(FC_OP2,1);
+                               gen_and_imm(FC_OP2,7);
+                               gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+                               gen_call_function_RR((void *)&FPU_FUCOM,FC_OP1,FC_OP2);
+                               gen_call_function_raw((void *)&FPU_FPOP);
+                               gen_call_function_raw((void *)&FPU_FPOP);
+                               break;
+                       default:
+                               LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); 
+                               break;
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               }
+       } else {
+               dyn_fill_ea(FC_ADDR);
+               gen_call_function_R((void*)&FPU_FLD_I32_EA,FC_ADDR); 
+               gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+               dyn_eatree();
+       }
+}
+
+static void dyn_fpu_esc3(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               switch (decode.modrm.reg) {
+               case 0x04:
+                       switch (decode.modrm.rm) {
+                       case 0x00:                              //FNENI
+                       case 0x01:                              //FNDIS
+                               LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion: %d",decode.modrm.rm);
+                               break;
+                       case 0x02:                              //FNCLEX FCLEX
+                               gen_call_function_raw((void*)&FPU_FCLEX);
+                               break;
+                       case 0x03:                              //FNINIT FINIT
+                               gen_call_function_raw((void*)&FPU_FINIT);
+                               break;
+                       case 0x04:                              //FNSETPM
+                       case 0x05:                              //FRSTPM
+//                             LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done");
+                               break;
+                       default:
+                               E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               }
+       } else {
+               switch(decode.modrm.reg){
+               case 0x00:      /* FILD */
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH);
+                       dyn_fill_ea(FC_OP1); 
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_call_function_RR((void*)&FPU_FLD_I32,FC_OP1,FC_OP2);
+                       break;
+               case 0x01:      /* FISTTP */
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               case 0x02:      /* FIST */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR);
+                       break;
+               case 0x03:      /* FISTP */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x05:      /* FLD 80 Bits Real */
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH);
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FLD_F80,FC_ADDR);
+                       break;
+               case 0x07:      /* FSTP 80 Bits Real */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_F80,FC_ADDR);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+               }
+       }
+}
+
+static void dyn_fpu_esc4(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               switch(decode.modrm.reg){
+               case 0x00:      /* FADD STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2);
+                       break;
+               case 0x01:      /* FMUL STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2);
+                       break;
+               case 0x02:  /* FCOM*/
+                       dyn_fpu_top();
+                       gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
+                       break;
+               case 0x03:  /* FCOMP*/
+                       dyn_fpu_top();
+                       gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x04:  /* FSUBR STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2);
+                       break;
+               case 0x05:  /* FSUB  STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2);
+                       break;
+               case 0x06:  /* FDIVR STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2);
+                       break;
+               case 0x07:  /* FDIV STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2);
+                       break;
+               default:
+                       break;
+               }
+       } else { 
+               dyn_fill_ea(FC_ADDR);
+               gen_call_function_R((void*)&FPU_FLD_F64_EA,FC_ADDR); 
+               gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+               dyn_eatree();
+       }
+}
+
+static void dyn_fpu_esc5(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               dyn_fpu_top();
+               switch(decode.modrm.reg){
+               case 0x00: /* FFREE STi */
+                       gen_call_function_R((void*)&FPU_FFREE,FC_OP2);
+                       break;
+               case 0x01: /* FXCH STi*/
+                       gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2);
+                       break;
+               case 0x02: /* FST STi */
+                       gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
+                       break;
+               case 0x03:  /* FSTP STi*/
+                       gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x04:      /* FUCOM STi */
+                       gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2);
+                       break;
+               case 0x05:      /*FUCOMP STi */
+                       gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+        }
+       } else {
+               switch(decode.modrm.reg){
+               case 0x00:  /* FLD double real*/
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH);
+                       dyn_fill_ea(FC_OP1); 
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_call_function_RR((void*)&FPU_FLD_F64,FC_OP1,FC_OP2);
+                       break;
+               case 0x01:  /* FISTTP longint*/
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               case 0x02:   /* FST double real*/
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR);
+                       break;
+               case 0x03:      /* FSTP double real*/
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x04:      /* FRSTOR */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FRSTOR,FC_ADDR);
+                       break;
+               case 0x06:      /* FSAVE */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FSAVE,FC_ADDR);
+                       break;
+               case 0x07:   /*FNSTSW */
+                       gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+                       gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1);
+                       dyn_fill_ea(FC_OP1); 
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),false);
+                       gen_call_function_RR((void*)&mem_writew,FC_OP1,FC_OP2);
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+               }
+       }
+}
+
+static void dyn_fpu_esc6(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               switch(decode.modrm.reg){
+               case 0x00:      /*FADDP STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2);
+                       break;
+               case 0x01:      /* FMULP STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2);
+                       break;
+               case 0x02:  /* FCOMP5*/
+                       dyn_fpu_top();
+                       gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
+                       break;  /* TODO IS THIS ALLRIGHT ????????? */
+               case 0x03:  /*FCOMPP*/
+                       if(decode.modrm.rm != 1) {
+                               LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                               return;
+                       }
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_add_imm(FC_OP2,1);
+                       gen_and_imm(FC_OP2,7);
+                       gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+                       gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP); /* extra pop at the bottom*/
+                       break;
+               case 0x04:  /* FSUBRP STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2);
+                       break;
+               case 0x05:  /* FSUBP  STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2);
+                       break;
+               case 0x06:      /* FDIVRP STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2);
+                       break;
+               case 0x07:  /* FDIVP STi,ST*/
+                       dyn_fpu_top_swapped();
+                       gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2);
+                       break;
+               default:
+                       break;
+               }
+               gen_call_function_raw((void*)&FPU_FPOP);                
+       } else {
+               dyn_fill_ea(FC_ADDR);
+               gen_call_function_R((void*)&FPU_FLD_I16_EA,FC_ADDR); 
+               gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+               dyn_eatree();
+       }
+}
+
+static void dyn_fpu_esc7(){
+       dyn_get_modrm();  
+       if (decode.modrm.val >= 0xc0) { 
+               switch (decode.modrm.reg){
+               case 0x00: /* FFREEP STi */
+                       dyn_fpu_top();
+                       gen_call_function_R((void*)&FPU_FFREE,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x01: /* FXCH STi*/
+                       dyn_fpu_top();
+                       gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2);
+                       break;
+               case 0x02:  /* FSTP STi*/
+               case 0x03:  /* FSTP STi*/
+                       dyn_fpu_top();
+                       gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x04:
+                       switch(decode.modrm.rm){
+                               case 0x00:     /* FNSTSW AX*/
+                                       gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
+                                       gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); 
+                                       gen_mov_word_to_reg(FC_OP1,(void*)(&fpu.sw),false);
+                                       MOV_REG_WORD16_FROM_HOST_REG(FC_OP1,DRC_REG_EAX);
+                                       break;
+                               default:
+                                       LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                                       break;
+                       }
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               }
+       } else {
+               switch(decode.modrm.reg){
+               case 0x00:  /* FILD Bit16s */
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH);
+                       dyn_fill_ea(FC_OP1); 
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_call_function_RR((void*)&FPU_FLD_I16,FC_OP1,FC_OP2);
+                       break;
+               case 0x01:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               case 0x02:   /* FIST Bit16s */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR);
+                       break;
+               case 0x03:      /* FISTP Bit16s */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x04:   /* FBLD packed BCD */
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH);
+                       dyn_fill_ea(FC_OP1);
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_call_function_RR((void*)&FPU_FBLD,FC_OP1,FC_OP2);
+                       break;
+               case 0x05:  /* FILD Bit64s */
+                       gen_call_function_raw((void*)&FPU_PREP_PUSH);
+                       dyn_fill_ea(FC_OP1);
+                       gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true);
+                       gen_call_function_RR((void*)&FPU_FLD_I64,FC_OP1,FC_OP2);
+                       break;
+               case 0x06:      /* FBSTP packed BCD */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FBST,FC_ADDR);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               case 0x07:  /* FISTP Bit64s */
+                       dyn_fill_ea(FC_ADDR); 
+                       gen_call_function_R((void*)&FPU_FST_I64,FC_ADDR);
+                       gen_call_function_raw((void*)&FPU_FPOP);
+                       break;
+               default:
+                       LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm);
+                       break;
+               }
+       }
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/operators.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/operators.h
new file mode 100644 (file)
index 0000000..18d1743
--- /dev/null
@@ -0,0 +1,1996 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) {
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=(Bit8u)(lf_var1b+lf_var2b);
+       lflags.type=t_ADDb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) {
+       return op1+op2;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) {
+       lflags.oldcf=get_CF()!=0;
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=(Bit8u)(lf_var1b+lf_var2b+lflags.oldcf);
+       lflags.type=t_ADCb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) {
+       return (Bit8u)(op1+op2+(Bitu)(get_CF()!=0));
+}
+
+static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) {
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=(Bit8u)(lf_var1b-lf_var2b);
+       lflags.type=t_SUBb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) {
+       return op1-op2;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) {
+       lflags.oldcf=get_CF()!=0;
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=(Bit8u)(lf_var1b-(lf_var2b+lflags.oldcf));
+       lflags.type=t_SBBb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) {
+       return (Bit8u)(op1-(op2+(Bitu)(get_CF()!=0)));
+}
+
+static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) {
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=(Bit8u)(lf_var1b-lf_var2b);
+       lflags.type=t_CMPb;
+}
+
+static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) {
+}
+
+static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) {
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=lf_var1b ^ lf_var2b;
+       lflags.type=t_XORb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) {
+       return op1 ^ op2;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) {
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=lf_var1b & lf_var2b;
+       lflags.type=t_ANDb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) {
+       return op1 & op2;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) {
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=lf_var1b | lf_var2b;
+       lflags.type=t_ORb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) {
+       return op1 | op2;
+}
+
+static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) {
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=lf_var1b & lf_var2b;
+       lflags.type=t_TESTb;
+}
+
+static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) {
+}
+
+static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) {
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=(Bit16u)(lf_var1w+lf_var2w);
+       lflags.type=t_ADDw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) {
+       return op1+op2;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) {
+       lflags.oldcf=get_CF()!=0;
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=(Bit16u)(lf_var1w+lf_var2w+lflags.oldcf);
+       lflags.type=t_ADCw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) {
+       return (Bit16u)(op1+op2+(Bitu)(get_CF()!=0));
+}
+
+static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) {
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=(Bit16u)(lf_var1w-lf_var2w);
+       lflags.type=t_SUBw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) {
+       return op1-op2;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) {
+       lflags.oldcf=get_CF()!=0;
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=(Bit16u)(lf_var1w-(lf_var2w+lflags.oldcf));
+       lflags.type=t_SBBw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) {
+       return (Bit16u)(op1-(op2+(Bitu)(get_CF()!=0)));
+}
+
+static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) {
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=(Bit16u)(lf_var1w-lf_var2w);
+       lflags.type=t_CMPw;
+}
+
+static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) {
+}
+
+static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) {
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=lf_var1w ^ lf_var2w;
+       lflags.type=t_XORw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) {
+       return op1 ^ op2;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) {
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=lf_var1w & lf_var2w;
+       lflags.type=t_ANDw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) {
+       return op1 & op2;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) {
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=lf_var1w | lf_var2w;
+       lflags.type=t_ORw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) {
+       return op1 | op2;
+}
+
+static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) {
+       lf_var1w=op1;
+       lf_var2w=op2;
+       lf_resw=lf_var1w & lf_var2w;
+       lflags.type=t_TESTw;
+}
+
+static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) {
+}
+
+static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) {
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d+lf_var2d;
+       lflags.type=t_ADDd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) {
+       return op1 + op2;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) {
+       lflags.oldcf=get_CF()!=0;
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d+lf_var2d+lflags.oldcf;
+       lflags.type=t_ADCd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) {
+       return op1+op2+(Bitu)(get_CF()!=0);
+}
+
+static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) {
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d-lf_var2d;
+       lflags.type=t_SUBd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) {
+       return op1-op2;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) {
+       lflags.oldcf=get_CF()!=0;
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d-(lf_var2d+lflags.oldcf);
+       lflags.type=t_SBBd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) {
+       return op1-(op2+(Bitu)(get_CF()!=0));
+}
+
+static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) {
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d-lf_var2d;
+       lflags.type=t_CMPd;
+}
+
+static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) {
+}
+
+static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) {
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d ^ lf_var2d;
+       lflags.type=t_XORd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) {
+       return op1 ^ op2;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) {
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d & lf_var2d;
+       lflags.type=t_ANDd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) {
+       return op1 & op2;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) {
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d | lf_var2d;
+       lflags.type=t_ORd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) {
+       return op1 | op2;
+}
+
+static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) {
+       lf_var1d=op1;
+       lf_var2d=op2;
+       lf_resd=lf_var1d & lf_var2d;
+       lflags.type=t_TESTd;
+}
+
+static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) DRC_FC;
+static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) {
+}
+
+
+static void dyn_dop_byte_gencall(DualOps op) {
+       switch (op) {
+               case DOP_ADD:
+                       InvalidateFlags((void*)&dynrec_add_byte_simple,t_ADDb);
+                       gen_call_function_raw((void*)&dynrec_add_byte);
+                       break;
+               case DOP_ADC:
+                       AcquireFlags(FLAG_CF);
+                       InvalidateFlagsPartially((void*)&dynrec_adc_byte_simple,t_ADCb);
+                       gen_call_function_raw((void*)&dynrec_adc_byte);
+                       break;
+               case DOP_SUB:
+                       InvalidateFlags((void*)&dynrec_sub_byte_simple,t_SUBb);
+                       gen_call_function_raw((void*)&dynrec_sub_byte);
+                       break;
+               case DOP_SBB:
+                       AcquireFlags(FLAG_CF);
+                       InvalidateFlagsPartially((void*)&dynrec_sbb_byte_simple,t_SBBb);
+                       gen_call_function_raw((void*)&dynrec_sbb_byte);
+                       break;
+               case DOP_CMP:
+                       InvalidateFlags((void*)&dynrec_cmp_byte_simple,t_CMPb);
+                       gen_call_function_raw((void*)&dynrec_cmp_byte);
+                       break;
+               case DOP_XOR:
+                       InvalidateFlags((void*)&dynrec_xor_byte_simple,t_XORb);
+                       gen_call_function_raw((void*)&dynrec_xor_byte);
+                       break;
+               case DOP_AND:
+                       InvalidateFlags((void*)&dynrec_and_byte_simple,t_ANDb);
+                       gen_call_function_raw((void*)&dynrec_and_byte);
+                       break;
+               case DOP_OR:
+                       InvalidateFlags((void*)&dynrec_or_byte_simple,t_ORb);
+                       gen_call_function_raw((void*)&dynrec_or_byte);
+                       break;
+               case DOP_TEST:
+                       InvalidateFlags((void*)&dynrec_test_byte_simple,t_TESTb);
+                       gen_call_function_raw((void*)&dynrec_test_byte);
+                       break;
+               default: IllegalOptionDynrec("dyn_dop_byte_gencall");
+       }
+}
+
+static void dyn_dop_word_gencall(DualOps op,bool dword) {
+       if (dword) {
+               switch (op) {
+                       case DOP_ADD:
+                               InvalidateFlags((void*)&dynrec_add_dword_simple,t_ADDd);
+                               gen_call_function_raw((void*)&dynrec_add_dword);
+                               break;
+                       case DOP_ADC:
+                               AcquireFlags(FLAG_CF);
+                               InvalidateFlagsPartially((void*)&dynrec_adc_dword_simple,t_ADCd);
+                               gen_call_function_raw((void*)&dynrec_adc_dword);
+                               break;
+                       case DOP_SUB:
+                               InvalidateFlags((void*)&dynrec_sub_dword_simple,t_SUBd);
+                               gen_call_function_raw((void*)&dynrec_sub_dword);
+                               break;
+                       case DOP_SBB:
+                               AcquireFlags(FLAG_CF);
+                               InvalidateFlagsPartially((void*)&dynrec_sbb_dword_simple,t_SBBd);
+                               gen_call_function_raw((void*)&dynrec_sbb_dword);
+                               break;
+                       case DOP_CMP:
+                               InvalidateFlags((void*)&dynrec_cmp_dword_simple,t_CMPd);
+                               gen_call_function_raw((void*)&dynrec_cmp_dword);
+                               break;
+                       case DOP_XOR:
+                               InvalidateFlags((void*)&dynrec_xor_dword_simple,t_XORd);
+                               gen_call_function_raw((void*)&dynrec_xor_dword);
+                               break;
+                       case DOP_AND:
+                               InvalidateFlags((void*)&dynrec_and_dword_simple,t_ANDd);
+                               gen_call_function_raw((void*)&dynrec_and_dword);
+                               break;
+                       case DOP_OR:
+                               InvalidateFlags((void*)&dynrec_or_dword_simple,t_ORd);
+                               gen_call_function_raw((void*)&dynrec_or_dword);
+                               break;
+                       case DOP_TEST:
+                               InvalidateFlags((void*)&dynrec_test_dword_simple,t_TESTd);
+                               gen_call_function_raw((void*)&dynrec_test_dword);
+                               break;
+                       default: IllegalOptionDynrec("dyn_dop_dword_gencall");
+               }
+       } else {
+               switch (op) {
+                       case DOP_ADD:
+                               InvalidateFlags((void*)&dynrec_add_word_simple,t_ADDw);
+                               gen_call_function_raw((void*)&dynrec_add_word);
+                               break;
+                       case DOP_ADC:
+                               AcquireFlags(FLAG_CF);
+                               InvalidateFlagsPartially((void*)&dynrec_adc_word_simple,t_ADCw);
+                               gen_call_function_raw((void*)&dynrec_adc_word);
+                               break;
+                       case DOP_SUB:
+                               InvalidateFlags((void*)&dynrec_sub_word_simple,t_SUBw);
+                               gen_call_function_raw((void*)&dynrec_sub_word);
+                               break;
+                       case DOP_SBB:
+                               AcquireFlags(FLAG_CF);
+                               InvalidateFlagsPartially((void*)&dynrec_sbb_word_simple,t_SBBw);
+                               gen_call_function_raw((void*)&dynrec_sbb_word);
+                               break;
+                       case DOP_CMP:
+                               InvalidateFlags((void*)&dynrec_cmp_word_simple,t_CMPw);
+                               gen_call_function_raw((void*)&dynrec_cmp_word);
+                               break;
+                       case DOP_XOR:
+                               InvalidateFlags((void*)&dynrec_xor_word_simple,t_XORw);
+                               gen_call_function_raw((void*)&dynrec_xor_word);
+                               break;
+                       case DOP_AND:
+                               InvalidateFlags((void*)&dynrec_and_word_simple,t_ANDw);
+                               gen_call_function_raw((void*)&dynrec_and_word);
+                               break;
+                       case DOP_OR:
+                               InvalidateFlags((void*)&dynrec_or_word_simple,t_ORw);
+                               gen_call_function_raw((void*)&dynrec_or_word);
+                               break;
+                       case DOP_TEST:
+                               InvalidateFlags((void*)&dynrec_test_word_simple,t_TESTw);
+                               gen_call_function_raw((void*)&dynrec_test_word);
+                               break;
+                       default: IllegalOptionDynrec("dyn_dop_word_gencall");
+               }
+       }
+}
+
+
+static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) {
+       LoadCF;
+       lf_var1b=op;
+       lf_resb=lf_var1b+1;
+       lflags.type=t_INCb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) {
+       return op+1;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) {
+       LoadCF;
+       lf_var1b=op;
+       lf_resb=lf_var1b-1;
+       lflags.type=t_DECb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) {
+       return op-1;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) {
+       return ~op;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) {
+       lf_var1b=op;
+       lf_resb=0-lf_var1b;
+       lflags.type=t_NEGb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) {
+       return 0-op;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) {
+       LoadCF;
+       lf_var1w=op;
+       lf_resw=lf_var1w+1;
+       lflags.type=t_INCw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) {
+       return op+1;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) {
+       LoadCF;
+       lf_var1w=op;
+       lf_resw=lf_var1w-1;
+       lflags.type=t_DECw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) {
+       return op-1;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) {
+       return ~op;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) {
+       lf_var1w=op;
+       lf_resw=0-lf_var1w;
+       lflags.type=t_NEGw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) {
+       return 0-op;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) {
+       LoadCF;
+       lf_var1d=op;
+       lf_resd=lf_var1d+1;
+       lflags.type=t_INCd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) {
+       return op+1;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) {
+       LoadCF;
+       lf_var1d=op;
+       lf_resd=lf_var1d-1;
+       lflags.type=t_DECd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) {
+       return op-1;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) {
+       return ~op;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) {
+       lf_var1d=op;
+       lf_resd=0-lf_var1d;
+       lflags.type=t_NEGd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) {
+       return 0-op;
+}
+
+
+static void dyn_sop_byte_gencall(SingleOps op) {
+       switch (op) {
+               case SOP_INC:
+                       InvalidateFlagsPartially((void*)&dynrec_inc_byte_simple,t_INCb);
+                       gen_call_function_raw((void*)&dynrec_inc_byte);
+                       break;
+               case SOP_DEC:
+                       InvalidateFlagsPartially((void*)&dynrec_dec_byte_simple,t_DECb);
+                       gen_call_function_raw((void*)&dynrec_dec_byte);
+                       break;
+               case SOP_NOT:
+                       gen_call_function_raw((void*)&dynrec_not_byte);
+                       break;
+               case SOP_NEG:
+                       InvalidateFlags((void*)&dynrec_neg_byte_simple,t_NEGb);
+                       gen_call_function_raw((void*)&dynrec_neg_byte);
+                       break;
+               default: IllegalOptionDynrec("dyn_sop_byte_gencall");
+       }
+}
+
+static void dyn_sop_word_gencall(SingleOps op,bool dword) {
+       if (dword) {
+               switch (op) {
+                       case SOP_INC:
+                               InvalidateFlagsPartially((void*)&dynrec_inc_dword_simple,t_INCd);
+                               gen_call_function_raw((void*)&dynrec_inc_dword);
+                               break;
+                       case SOP_DEC:
+                               InvalidateFlagsPartially((void*)&dynrec_dec_dword_simple,t_DECd);
+                               gen_call_function_raw((void*)&dynrec_dec_dword);
+                               break;
+                       case SOP_NOT:
+                               gen_call_function_raw((void*)&dynrec_not_dword);
+                               break;
+                       case SOP_NEG:
+                               InvalidateFlags((void*)&dynrec_neg_dword_simple,t_NEGd);
+                               gen_call_function_raw((void*)&dynrec_neg_dword);
+                               break;
+                       default: IllegalOptionDynrec("dyn_sop_dword_gencall");
+               }
+       } else {
+               switch (op) {
+                       case SOP_INC:
+                               InvalidateFlagsPartially((void*)&dynrec_inc_word_simple,t_INCw);
+                               gen_call_function_raw((void*)&dynrec_inc_word);
+                               break;
+                       case SOP_DEC:
+                               InvalidateFlagsPartially((void*)&dynrec_dec_word_simple,t_DECw);
+                               gen_call_function_raw((void*)&dynrec_dec_word);
+                               break;
+                       case SOP_NOT:
+                               gen_call_function_raw((void*)&dynrec_not_word);
+                               break;
+                       case SOP_NEG:
+                               InvalidateFlags((void*)&dynrec_neg_word_simple,t_NEGw);
+                               gen_call_function_raw((void*)&dynrec_neg_word);
+                               break;
+                       default: IllegalOptionDynrec("dyn_sop_word_gencall");
+               }
+       }
+}
+
+
+static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) {
+       if (!(op2&0x7)) {
+               if (op2&0x18) {
+                       FillFlagsNoCFOF();
+                       SETFLAGBIT(CF,op1 & 1);
+                       SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7));
+               }
+               return op1;
+       }
+       FillFlagsNoCFOF();
+       lf_var1b=op1;
+       lf_var2b=op2&0x07;
+       lf_resb=(lf_var1b << lf_var2b) | (lf_var1b >> (8-lf_var2b));
+       SETFLAGBIT(CF,lf_resb & 1);
+       SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7));
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) {
+       if (!(op2&0x7)) return op1;
+       return (op1 << (op2&0x07)) | (op1 >> (8-(op2&0x07)));
+}
+
+static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) {
+       if (!(op2&0x7)) {
+               if (op2&0x18) {
+                       FillFlagsNoCFOF();
+                       SETFLAGBIT(CF,op1>>7);
+                       SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1));
+               }
+               return op1;
+       }
+       FillFlagsNoCFOF();
+       lf_var1b=op1;
+       lf_var2b=op2&0x07;
+       lf_resb=(lf_var1b >> lf_var2b) | (lf_var1b << (8-lf_var2b));
+       SETFLAGBIT(CF,lf_resb & 0x80);
+       SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80);
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) {
+       if (!(op2&0x7)) return op1;
+       return (op1 >> (op2&0x07)) | (op1 << (8-(op2&0x07)));
+}
+
+static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) {
+       if (op2%9) {
+               Bit8u cf=(Bit8u)FillFlags()&0x1;
+               lf_var1b=op1;
+               lf_var2b=op2%9;
+               lf_resb=(lf_var1b << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1b >> (9-lf_var2b));
+               SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1));
+               SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7));
+               return lf_resb;
+       } else return op1;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) {
+       if (op2%9) {
+               Bit8u cf=(Bit8u)FillFlags()&0x1;
+               lf_var1b=op1;
+               lf_var2b=op2%9;
+               lf_resb=(lf_var1b >> lf_var2b) | (cf << (8-lf_var2b)) | (lf_var1b << (9-lf_var2b));                                     \
+               SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1);
+               SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80);
+               return lf_resb;
+       } else return op1;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=lf_var1b << lf_var2b;
+       lflags.type=t_SHLb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return op1 << op2;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1b=op1;
+       lf_var2b=op2;
+       lf_resb=lf_var1b >> lf_var2b;
+       lflags.type=t_SHRb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return op1 >> op2;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1b=op1;
+       lf_var2b=op2;
+       if (lf_var2b>8) lf_var2b=8;
+    if (lf_var1b & 0x80) {
+               lf_resb=(lf_var1b >> lf_var2b)| (0xff << (8 - lf_var2b));
+       } else {
+               lf_resb=lf_var1b >> lf_var2b;
+    }
+       lflags.type=t_SARb;
+       return lf_resb;
+}
+
+static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) DRC_FC;
+static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) {
+       if (!op2) return op1;
+       if (op2>8) op2=8;
+    if (op1 & 0x80) return (op1 >> op2) | (0xff << (8 - op2));
+       else return op1 >> op2;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) {
+       if (!(op2&0xf)) {
+               if (op2&0x10) {
+                       FillFlagsNoCFOF();
+                       SETFLAGBIT(CF,op1 & 1);
+                       SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15));
+               }
+               return op1;
+       }
+       FillFlagsNoCFOF();
+       lf_var1w=op1;
+       lf_var2b=op2&0xf;
+       lf_resw=(lf_var1w << lf_var2b) | (lf_var1w >> (16-lf_var2b));
+       SETFLAGBIT(CF,lf_resw & 1);
+       SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15));
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) {
+       if (!(op2&0xf)) return op1;
+       return (op1 << (op2&0xf)) | (op1 >> (16-(op2&0xf)));
+}
+
+static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) {
+       if (!(op2&0xf)) {
+               if (op2&0x10) {
+                       FillFlagsNoCFOF();
+                       SETFLAGBIT(CF,op1>>15);
+                       SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1));
+               }
+               return op1;
+       }
+       FillFlagsNoCFOF();
+       lf_var1w=op1;
+       lf_var2b=op2&0xf;
+       lf_resw=(lf_var1w >> lf_var2b) | (lf_var1w << (16-lf_var2b));
+       SETFLAGBIT(CF,lf_resw & 0x8000);
+       SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000);
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) {
+       if (!(op2&0xf)) return op1;
+       return (op1 >> (op2&0xf)) | (op1 << (16-(op2&0xf)));
+}
+
+static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) {
+       if (op2%17) {
+               Bit16u cf=(Bit16u)FillFlags()&0x1;
+               lf_var1w=op1;
+               lf_var2b=op2%17;
+               lf_resw=(lf_var1w << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1w >> (17-lf_var2b));
+               SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1));
+               SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15));
+               return lf_resw;
+       } else return op1;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) {
+       if (op2%17) {
+               Bit16u cf=(Bit16u)FillFlags()&0x1;
+               lf_var1w=op1;
+               lf_var2b=op2%17;
+               lf_resw=(lf_var1w >> lf_var2b) | (cf << (16-lf_var2b)) | (lf_var1w << (17-lf_var2b));
+               SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1);
+               SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000);
+               return lf_resw;
+       } else return op1;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1w=op1;
+       lf_var2b=op2;
+       lf_resw=lf_var1w << lf_var2b;
+       lflags.type=t_SHLw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return op1 << op2;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1w=op1;
+       lf_var2b=op2;
+       lf_resw=lf_var1w >> lf_var2b;
+       lflags.type=t_SHRw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return op1 >> op2;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1w=op1;
+       lf_var2b=op2;
+       if (lf_var2b>16) lf_var2b=16;
+       if (lf_var1w & 0x8000) {
+               lf_resw=(lf_var1w >> lf_var2b) | (0xffff << (16 - lf_var2b));
+       } else {
+               lf_resw=lf_var1w >> lf_var2b;
+    }
+       lflags.type=t_SARw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) {
+       if (!op2) return op1;
+       if (op2>16) op2=16;
+       if (op1 & 0x8000) return (op1 >> op2) | (0xffff << (16 - op2));
+       else return op1 >> op2;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       FillFlagsNoCFOF();
+       lf_var1d=op1;
+       lf_var2b=op2;
+       lf_resd=(lf_var1d << lf_var2b) | (lf_var1d >> (32-lf_var2b));
+       SETFLAGBIT(CF,lf_resd & 1);
+       SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31));
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return (op1 << op2) | (op1 >> (32-op2));
+}
+
+static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       FillFlagsNoCFOF();
+       lf_var1d=op1;
+       lf_var2b=op2;
+       lf_resd=(lf_var1d >> lf_var2b) | (lf_var1d << (32-lf_var2b));
+       SETFLAGBIT(CF,lf_resd & 0x80000000);
+       SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000);
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return (op1 >> op2) | (op1 << (32-op2));
+}
+
+static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       Bit32u cf=(Bit32u)FillFlags()&0x1;
+       lf_var1d=op1;
+       lf_var2b=op2;
+       if (lf_var2b==1) {
+               lf_resd=(lf_var1d << 1) | cf;
+       } else  {
+               lf_resd=(lf_var1d << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1d >> (33-lf_var2b));
+       }
+       SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1));
+       SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resd >> 31));
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) {
+       if (op2) {
+               Bit32u cf=(Bit32u)FillFlags()&0x1;
+               lf_var1d=op1;
+               lf_var2b=op2;
+               if (lf_var2b==1) {
+                       lf_resd=lf_var1d >> 1 | cf << 31;
+               } else {
+                       lf_resd=(lf_var1d >> lf_var2b) | (cf << (32-lf_var2b)) | (lf_var1d << (33-lf_var2b));
+               }
+               SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
+               SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000);
+               return lf_resd;
+       } else return op1;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1d=op1;
+       lf_var2b=op2;
+       lf_resd=lf_var1d << lf_var2b;
+       lflags.type=t_SHLd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return op1 << op2;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var1d=op1;
+       lf_var2b=op2;
+       lf_resd=lf_var1d >> lf_var2b;
+       lflags.type=t_SHRd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       return op1 >> op2;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       lf_var2b=op2;
+       lf_var1d=op1;
+       if (lf_var1d & 0x80000000) {
+               lf_resd=(lf_var1d >> lf_var2b) | (0xffffffff << (32 - lf_var2b));
+       } else {
+               lf_resd=lf_var1d >> lf_var2b;
+    }
+       lflags.type=t_SARd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) {
+       if (!op2) return op1;
+       if (op1 & 0x80000000) return (op1 >> op2) | (0xffffffff << (32 - op2));
+       else return op1 >> op2;
+}
+
+static void dyn_shift_byte_gencall(ShiftOps op) {
+       switch (op) {
+               case SHIFT_ROL:
+                       InvalidateFlagsPartially((void*)&dynrec_rol_byte_simple,t_ROLb);
+                       gen_call_function_raw((void*)&dynrec_rol_byte);
+                       break;
+               case SHIFT_ROR:
+                       InvalidateFlagsPartially((void*)&dynrec_ror_byte_simple,t_RORb);
+                       gen_call_function_raw((void*)&dynrec_ror_byte);
+                       break;
+               case SHIFT_RCL:
+                       AcquireFlags(FLAG_CF);
+                       gen_call_function_raw((void*)&dynrec_rcl_byte);
+                       break;
+               case SHIFT_RCR:
+                       AcquireFlags(FLAG_CF);
+                       gen_call_function_raw((void*)&dynrec_rcr_byte);
+                       break;
+               case SHIFT_SHL:
+               case SHIFT_SAL:
+                       InvalidateFlagsPartially((void*)&dynrec_shl_byte_simple,t_SHLb);
+                       gen_call_function_raw((void*)&dynrec_shl_byte);
+                       break;
+               case SHIFT_SHR:
+                       InvalidateFlagsPartially((void*)&dynrec_shr_byte_simple,t_SHRb);
+                       gen_call_function_raw((void*)&dynrec_shr_byte);
+                       break;
+               case SHIFT_SAR:
+                       InvalidateFlagsPartially((void*)&dynrec_sar_byte_simple,t_SARb);
+                       gen_call_function_raw((void*)&dynrec_sar_byte);
+                       break;
+               default: IllegalOptionDynrec("dyn_shift_byte_gencall");
+       }
+}
+
+static void dyn_shift_word_gencall(ShiftOps op,bool dword) {
+       if (dword) {
+               switch (op) {
+                       case SHIFT_ROL:
+                               InvalidateFlagsPartially((void*)&dynrec_rol_dword_simple,t_ROLd);
+                               gen_call_function_raw((void*)&dynrec_rol_dword);
+                               break;
+                       case SHIFT_ROR:
+                               InvalidateFlagsPartially((void*)&dynrec_ror_dword_simple,t_RORd);
+                               gen_call_function_raw((void*)&dynrec_ror_dword);
+                               break;
+                       case SHIFT_RCL:
+                               AcquireFlags(FLAG_CF);
+                               gen_call_function_raw((void*)&dynrec_rcl_dword);
+                               break;
+                       case SHIFT_RCR:
+                               AcquireFlags(FLAG_CF);
+                               gen_call_function_raw((void*)&dynrec_rcr_dword);
+                               break;
+                       case SHIFT_SHL:
+                       case SHIFT_SAL:
+                               InvalidateFlagsPartially((void*)&dynrec_shl_dword_simple,t_SHLd);
+                               gen_call_function_raw((void*)&dynrec_shl_dword);
+                               break;
+                       case SHIFT_SHR:
+                               InvalidateFlagsPartially((void*)&dynrec_shr_dword_simple,t_SHRd);
+                               gen_call_function_raw((void*)&dynrec_shr_dword);
+                               break;
+                       case SHIFT_SAR:
+                               InvalidateFlagsPartially((void*)&dynrec_sar_dword_simple,t_SARd);
+                               gen_call_function_raw((void*)&dynrec_sar_dword);
+                               break;
+                       default: IllegalOptionDynrec("dyn_shift_dword_gencall");
+               }
+       } else {
+               switch (op) {
+                       case SHIFT_ROL:
+                               InvalidateFlagsPartially((void*)&dynrec_rol_word_simple,t_ROLw);
+                               gen_call_function_raw((void*)&dynrec_rol_word);
+                               break;
+                       case SHIFT_ROR:
+                               InvalidateFlagsPartially((void*)&dynrec_ror_word_simple,t_RORw);
+                               gen_call_function_raw((void*)&dynrec_ror_word);
+                               break;
+                       case SHIFT_RCL:
+                               AcquireFlags(FLAG_CF);
+                               gen_call_function_raw((void*)&dynrec_rcl_word);
+                               break;
+                       case SHIFT_RCR:
+                               AcquireFlags(FLAG_CF);
+                               gen_call_function_raw((void*)&dynrec_rcr_word);
+                               break;
+                       case SHIFT_SHL:
+                       case SHIFT_SAL:
+                               InvalidateFlagsPartially((void*)&dynrec_shl_word_simple,t_SHLw);
+                               gen_call_function_raw((void*)&dynrec_shl_word);
+                               break;
+                       case SHIFT_SHR:
+                               InvalidateFlagsPartially((void*)&dynrec_shr_word_simple,t_SHRw);
+                               gen_call_function_raw((void*)&dynrec_shr_word);
+                               break;
+                       case SHIFT_SAR:
+                               InvalidateFlagsPartially((void*)&dynrec_sar_word_simple,t_SARw);
+                               gen_call_function_raw((void*)&dynrec_sar_word);
+                               break;
+                       default: IllegalOptionDynrec("dyn_shift_word_gencall");
+               }
+       }
+}
+
+static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       lf_var2b=val;
+       lf_var1d=(op1<<16)|op2;
+       Bit32u tempd=lf_var1d << lf_var2b;
+       if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16));
+       lf_resw=(Bit16u)(tempd >> 16);
+       lflags.type=t_DSHLw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       Bit32u tempd=(Bit32u)((((Bit32u)op1)<<16)|op2) << val;
+       if (val>16) tempd |= (op2 << (val - 16));
+       return (Bit16u)(tempd >> 16);
+}
+
+static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       lf_var2b=val;
+       lf_var1d=op1;
+       lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b));
+       lflags.type=t_DSHLd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       return (op1 << val) | (op2 >> (32-val));
+}
+
+static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       lf_var2b=val;
+       lf_var1d=(op2<<16)|op1;
+       Bit32u tempd=lf_var1d >> lf_var2b;
+       if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b ));
+       lf_resw=(Bit16u)(tempd);
+       lflags.type=t_DSHRw;
+       return lf_resw;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       Bit32u tempd=(Bit32u)((((Bit32u)op2)<<16)|op1) >> val;
+       if (val>16) tempd |= (op2 << (32-val));
+       return (Bit16u)(tempd);
+}
+
+static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       lf_var2b=val;
+       lf_var1d=op1;
+       lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b));
+       lflags.type=t_DSHRd;
+       return lf_resd;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) {
+       Bit8u val=op3 & 0x1f;
+       if (!val) return op1;
+       return (op1 >> val) | (op2 << (32-val));
+}
+
+static void dyn_dpshift_word_gencall(bool left) {
+       if (left) {
+               DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_word,FC_OP3);
+               InvalidateFlagsPartially((void*)&dynrec_dshl_word_simple,proc_addr,t_DSHLw);
+       } else {
+               DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_word,FC_OP3);
+               InvalidateFlagsPartially((void*)&dynrec_dshr_word_simple,proc_addr,t_DSHRw);
+       }
+}
+
+static void dyn_dpshift_dword_gencall(bool left) {
+       if (left) {
+               DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_dword,FC_OP3);
+               InvalidateFlagsPartially((void*)&dynrec_dshl_dword_simple,proc_addr,t_DSHLd);
+       } else {
+               DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_dword,FC_OP3);
+               InvalidateFlagsPartially((void*)&dynrec_dshr_dword_simple,proc_addr,t_DSHRd);
+       }
+}
+
+
+
+static Bit32u DRC_CALL_CONV dynrec_get_of(void)                DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_of(void)                { return TFLG_O; }
+static Bit32u DRC_CALL_CONV dynrec_get_nof(void)       DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_nof(void)       { return TFLG_NO; }
+static Bit32u DRC_CALL_CONV dynrec_get_cf(void)                DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_cf(void)                { return TFLG_B; }
+static Bit32u DRC_CALL_CONV dynrec_get_ncf(void)       DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_ncf(void)       { return TFLG_NB; }
+static Bit32u DRC_CALL_CONV dynrec_get_zf(void)                DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_zf(void)                { return TFLG_Z; }
+static Bit32u DRC_CALL_CONV dynrec_get_nzf(void)       DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_nzf(void)       { return TFLG_NZ; }
+static Bit32u DRC_CALL_CONV dynrec_get_sf(void)                DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_sf(void)                { return TFLG_S; }
+static Bit32u DRC_CALL_CONV dynrec_get_nsf(void)       DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_nsf(void)       { return TFLG_NS; }
+static Bit32u DRC_CALL_CONV dynrec_get_pf(void)                DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_pf(void)                { return TFLG_P; }
+static Bit32u DRC_CALL_CONV dynrec_get_npf(void)       DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_npf(void)       { return TFLG_NP; }
+
+static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void)                  DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void)                  { return TFLG_BE; }
+static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void)               DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void)               { return TFLG_NBE; }
+static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void)                 DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void)                 { return TFLG_L; }
+static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void)                  DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void)                  { return TFLG_NL; }
+static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void)   DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void)   { return TFLG_LE; }
+static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void)  DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void)  { return TFLG_NLE; }
+
+
+static void dyn_branchflag_to_reg(BranchTypes btype) {
+       switch (btype) {
+               case BR_O:gen_call_function_raw((void*)&dynrec_get_of);break;
+               case BR_NO:gen_call_function_raw((void*)&dynrec_get_nof);break;
+               case BR_B:gen_call_function_raw((void*)&dynrec_get_cf);break;
+               case BR_NB:gen_call_function_raw((void*)&dynrec_get_ncf);break;
+               case BR_Z:gen_call_function_raw((void*)&dynrec_get_zf);break;
+               case BR_NZ:gen_call_function_raw((void*)&dynrec_get_nzf);break;
+               case BR_BE:gen_call_function_raw((void*)&dynrec_get_cf_or_zf);break;
+               case BR_NBE:gen_call_function_raw((void*)&dynrec_get_ncf_and_nzf);break;
+
+               case BR_S:gen_call_function_raw((void*)&dynrec_get_sf);break;
+               case BR_NS:gen_call_function_raw((void*)&dynrec_get_nsf);break;
+               case BR_P:gen_call_function_raw((void*)&dynrec_get_pf);break;
+               case BR_NP:gen_call_function_raw((void*)&dynrec_get_npf);break;
+               case BR_L:gen_call_function_raw((void*)&dynrec_get_sf_neq_of);break;
+               case BR_NL:gen_call_function_raw((void*)&dynrec_get_sf_eq_of);break;
+               case BR_LE:gen_call_function_raw((void*)&dynrec_get_zf_or_sf_neq_of);break;
+               case BR_NLE:gen_call_function_raw((void*)&dynrec_get_nzf_and_sf_eq_of);break;
+       }
+}
+
+
+static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) DRC_FC;
+static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) {
+       FillFlagsNoCFOF();
+       reg_ax=reg_al*op;
+       SETFLAGBIT(ZF,reg_al == 0);
+       if (reg_ax & 0xff00) {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       } else {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       }
+}
+
+static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) DRC_FC;
+static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) {
+       FillFlagsNoCFOF();
+       reg_ax=((Bit8s)reg_al) * ((Bit8s)op);
+       if ((reg_ax & 0xff80)==0xff80 || (reg_ax & 0xff80)==0x0000) {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       } else {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       }
+}
+
+static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) DRC_FC;
+static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) {
+       FillFlagsNoCFOF();
+       Bitu tempu=(Bitu)reg_ax*(Bitu)op;
+       reg_ax=(Bit16u)(tempu);
+       reg_dx=(Bit16u)(tempu >> 16);
+       SETFLAGBIT(ZF,reg_ax == 0);
+       if (reg_dx) {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       } else {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       }
+}
+
+static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) DRC_FC;
+static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) {
+       FillFlagsNoCFOF();
+       Bits temps=((Bit16s)reg_ax)*((Bit16s)op);
+       reg_ax=(Bit16s)(temps);
+       reg_dx=(Bit16s)(temps >> 16);
+       if (((temps & 0xffff8000)==0xffff8000 || (temps & 0xffff8000)==0x0000)) {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       } else {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       }
+}
+
+static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) DRC_FC;
+static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) {
+       FillFlagsNoCFOF();
+       Bit64u tempu=(Bit64u)reg_eax*(Bit64u)op;
+       reg_eax=(Bit32u)(tempu);
+       reg_edx=(Bit32u)(tempu >> 32);
+       SETFLAGBIT(ZF,reg_eax == 0);
+       if (reg_edx) {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       } else {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       }
+}
+
+static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) DRC_FC;
+static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) {
+       FillFlagsNoCFOF();
+       Bit64s temps=((Bit64s)((Bit32s)reg_eax))*((Bit64s)((Bit32s)op));
+       reg_eax=(Bit32u)(temps);
+       reg_edx=(Bit32u)(temps >> 32);
+       if ((reg_edx==0xffffffff) && (reg_eax & 0x80000000) ) {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       } else if ( (reg_edx==0x00000000) && (reg_eax< 0x80000000) ) {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       } else {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       }
+}
+
+
+static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) DRC_FC;
+static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) {
+       Bitu val=op;
+       if (val==0) return CPU_PrepareException(0,0);
+       Bitu quo=reg_ax / val;
+       Bit8u rem=(Bit8u)(reg_ax % val);
+       Bit8u quo8=(Bit8u)(quo&0xff);
+       if (quo>0xff) return CPU_PrepareException(0,0);
+       reg_ah=rem;
+       reg_al=quo8;
+       return false;
+}
+
+static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) DRC_FC;
+static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) {
+       Bits val=(Bit8s)op;
+       if (val==0) return CPU_PrepareException(0,0);
+       Bits quo=((Bit16s)reg_ax) / val;
+       Bit8s rem=(Bit8s)((Bit16s)reg_ax % val);
+       Bit8s quo8s=(Bit8s)(quo&0xff);
+       if (quo!=(Bit16s)quo8s) return CPU_PrepareException(0,0);
+       reg_ah=rem;
+       reg_al=quo8s;
+       return false;
+}
+
+static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) DRC_FC;
+static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) {
+       Bitu val=op;
+       if (val==0)     return CPU_PrepareException(0,0);
+       Bitu num=((Bit32u)reg_dx<<16)|reg_ax;
+       Bitu quo=num/val;
+       Bit16u rem=(Bit16u)(num % val);
+       Bit16u quo16=(Bit16u)(quo&0xffff);
+       if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0);
+       reg_dx=rem;
+       reg_ax=quo16;
+       return false;
+}
+
+static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) DRC_FC;
+static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) {
+       Bits val=(Bit16s)op;
+       if (val==0) return CPU_PrepareException(0,0);
+       Bits num=(Bit32s)((reg_dx<<16)|reg_ax);
+       Bits quo=num/val;
+       Bit16s rem=(Bit16s)(num % val);
+       Bit16s quo16s=(Bit16s)quo;
+       if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0);
+       reg_dx=rem;
+       reg_ax=quo16s;
+       return false;
+}
+
+static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) DRC_FC;
+static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) {
+       Bitu val=op;
+       if (val==0) return CPU_PrepareException(0,0);
+       Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax;
+       Bit64u quo=num/val;
+       Bit32u rem=(Bit32u)(num % val);
+       Bit32u quo32=(Bit32u)(quo&0xffffffff);
+       if (quo!=(Bit64u)quo32) return CPU_PrepareException(0,0);
+       reg_edx=rem;
+       reg_eax=quo32;
+       return false;
+}
+
+static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) DRC_FC;
+static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) {
+       Bits val=(Bit32s)op;
+       if (val==0) return CPU_PrepareException(0,0);
+       Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax;     
+       Bit64s quo=num/val;
+       Bit32s rem=(Bit32s)(num % val);
+       Bit32s quo32s=(Bit32s)(quo&0xffffffff);
+       if (quo!=(Bit64s)quo32s) return CPU_PrepareException(0,0);
+       reg_edx=rem;
+       reg_eax=quo32s;
+       return false;
+}
+
+
+static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) {
+       FillFlagsNoCFOF();
+       Bits res=((Bit16s)op1) * ((Bit16s)op2);
+       if ((res>-32768)  && (res<32767)) {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       } else {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       }
+       return (Bit16u)(res & 0xffff);
+}
+
+static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) {
+       FillFlagsNoCFOF();
+       Bit64s res=((Bit64s)((Bit32s)op1))*((Bit64s)((Bit32s)op2));
+       if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) {
+               SETFLAGBIT(CF,false);
+               SETFLAGBIT(OF,false);
+       } else {
+               SETFLAGBIT(CF,true);
+               SETFLAGBIT(OF,true);
+       }
+       return (Bit32s)res;
+}
+
+
+
+static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) {
+       return (Bit8s)op;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) {
+       return (Bit16s)op;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) {
+       if (op & 0x8000) return 0xffff;
+       else return 0;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) {
+       if (op & 0x80000000) return 0xffffffff;
+       else return 0;
+}
+
+
+static void DRC_CALL_CONV dynrec_sahf(Bit16u op) DRC_FC;
+static void DRC_CALL_CONV dynrec_sahf(Bit16u op) {
+       SETFLAGBIT(OF,get_OF());
+       lflags.type=t_UNKNOWN;
+       CPU_SetFlags(op>>8,FMASK_NORMAL & 0xff);
+}
+
+
+static void DRC_CALL_CONV dynrec_cmc(void) DRC_FC;
+static void DRC_CALL_CONV dynrec_cmc(void) {
+       FillFlags();
+       SETFLAGBIT(CF,!(reg_flags & FLAG_CF));
+}
+static void DRC_CALL_CONV dynrec_clc(void) DRC_FC;
+static void DRC_CALL_CONV dynrec_clc(void) {
+       FillFlags();
+       SETFLAGBIT(CF,false);
+}
+static void DRC_CALL_CONV dynrec_stc(void) DRC_FC;
+static void DRC_CALL_CONV dynrec_stc(void) {
+       FillFlags();
+       SETFLAGBIT(CF,true);
+}
+static void DRC_CALL_CONV dynrec_cld(void) DRC_FC;
+static void DRC_CALL_CONV dynrec_cld(void) {
+       SETFLAGBIT(DF,false);
+       cpu.direction=1;
+}
+static void DRC_CALL_CONV dynrec_std(void) DRC_FC;
+static void DRC_CALL_CONV dynrec_std(void) {
+       SETFLAGBIT(DF,true);
+       cpu.direction=-1;
+}
+
+
+static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       for (;count>0;count--) {
+               mem_writeb(di_base+reg_di,mem_readb(si_base+reg_si));
+               reg_si+=add_index;
+               reg_di+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       for (;count>0;count--) {
+               mem_writeb(di_base+reg_edi,mem_readb(si_base+reg_esi));
+               reg_esi+=add_index;
+               reg_edi+=add_index;
+       }
+       return count_left;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=1;
+       for (;count>0;count--) {
+               mem_writew(di_base+reg_di,mem_readw(si_base+reg_si));
+               reg_si+=add_index;
+               reg_di+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=1;
+       for (;count>0;count--) {
+               mem_writew(di_base+reg_edi,mem_readw(si_base+reg_esi));
+               reg_esi+=add_index;
+               reg_edi+=add_index;
+       }
+       return count_left;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=2;
+       for (;count>0;count--) {
+               mem_writed(di_base+reg_di,mem_readd(si_base+reg_si));
+               reg_si+=add_index;
+               reg_di+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=2;
+       for (;count>0;count--) {
+               mem_writed(di_base+reg_edi,mem_readd(si_base+reg_esi));
+               reg_esi+=add_index;
+               reg_edi+=add_index;
+       }
+       return count_left;
+}
+
+
+static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       for (;count>0;count--) {
+               reg_al=mem_readb(si_base+reg_si);
+               reg_si+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       for (;count>0;count--) {
+               reg_al=mem_readb(si_base+reg_esi);
+               reg_esi+=add_index;
+       }
+       return count_left;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=1;
+       for (;count>0;count--) {
+               reg_ax=mem_readw(si_base+reg_si);
+               reg_si+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=1;
+       for (;count>0;count--) {
+               reg_ax=mem_readw(si_base+reg_esi);
+               reg_esi+=add_index;
+       }
+       return count_left;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=2;
+       for (;count>0;count--) {
+               reg_eax=mem_readd(si_base+reg_si);
+               reg_si+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=2;
+       for (;count>0;count--) {
+               reg_eax=mem_readd(si_base+reg_esi);
+               reg_esi+=add_index;
+       }
+       return count_left;
+}
+
+
+static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       for (;count>0;count--) {
+               mem_writeb(di_base+reg_di,reg_al);
+               reg_di+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       for (;count>0;count--) {
+               mem_writeb(di_base+reg_edi,reg_al);
+               reg_edi+=add_index;
+       }
+       return count_left;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=1;
+       for (;count>0;count--) {
+               mem_writew(di_base+reg_di,reg_ax);
+               reg_di+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=1;
+       for (;count>0;count--) {
+               mem_writew(di_base+reg_edi,reg_ax);
+               reg_edi+=add_index;
+       }
+       return count_left;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) {
+       Bit16u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=(Bit16u)(count-CPU_Cycles);
+               count=(Bit16u)CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=2;
+       for (;count>0;count--) {
+               mem_writed(di_base+reg_di,reg_eax);
+               reg_di+=add_index;
+       }
+       return count_left;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) {
+       Bit32u count_left;
+       if (count<(Bitu)CPU_Cycles) {
+               count_left=0;
+       } else {
+               count_left=count-CPU_Cycles;
+               count=CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       add_index<<=2;
+       for (;count>0;count--) {
+               mem_writed(di_base+reg_edi,reg_eax);
+               reg_edi+=add_index;
+       }
+       return count_left;
+}
+
+
+static void DRC_CALL_CONV dynrec_push_word(Bit16u value) DRC_FC;
+static void DRC_CALL_CONV dynrec_push_word(Bit16u value) {
+       Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask);
+       mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask),value);
+       reg_esp=new_esp;
+}
+
+static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) DRC_FC;
+static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) {
+       Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-4)&cpu.stack.mask);
+       mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value);
+       reg_esp=new_esp;
+}
+
+static Bit16u DRC_CALL_CONV dynrec_pop_word(void) DRC_FC;
+static Bit16u DRC_CALL_CONV dynrec_pop_word(void) {
+       Bit16u val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+       reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask);
+       return val;
+}
+
+static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) DRC_FC;
+static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) {
+       Bit32u val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+       reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask);
+       return val;
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-common.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-common.h
new file mode 100644 (file)
index 0000000..c6ab612
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/* ARMv4 (little endian) backend by M-HT (common data/functions) */
+
+
+// some configuring defines that specify the capabilities of this architecture
+// or aspects of the recompiling
+
+// protect FC_ADDR over function calls if necessaray
+// #define DRC_PROTECT_ADDR_REG
+
+// try to use non-flags generating functions if possible
+#define DRC_FLAGS_INVALIDATION
+// try to replace _simple functions by code
+#define DRC_FLAGS_INVALIDATION_DCODE
+
+// type with the same size as a pointer
+#define DRC_PTR_SIZE_IM Bit32u
+
+// calling convention modifier
+#define DRC_CALL_CONV  /* nothing */
+#define DRC_FC                 /* nothing */
+
+// use FC_REGS_ADDR to hold the address of "cpu_regs" and to access it using FC_REGS_ADDR
+#define DRC_USE_REGS_ADDR
+// use FC_SEGS_ADDR to hold the address of "Segs" and to access it using FC_SEGS_ADDR
+#define DRC_USE_SEGS_ADDR
+
+// register mapping
+typedef Bit8u HostReg;
+
+// "lo" registers
+#define HOST_r0                 0
+#define HOST_r1                 1
+#define HOST_r2                 2
+#define HOST_r3                 3
+#define HOST_r4                 4
+#define HOST_r5                 5
+#define HOST_r6                 6
+#define HOST_r7                 7
+// "hi" registers
+#define HOST_r8                 8
+#define HOST_r9                 9
+#define HOST_r10       10
+#define HOST_r11       11
+#define HOST_r12       12
+#define HOST_r13       13
+#define HOST_r14       14
+#define HOST_r15       15
+
+// register aliases
+// "lo" registers
+#define HOST_a1 HOST_r0
+#define HOST_a2 HOST_r1
+#define HOST_a3 HOST_r2
+#define HOST_a4 HOST_r3
+#define HOST_v1 HOST_r4
+#define HOST_v2 HOST_r5
+#define HOST_v3 HOST_r6
+#define HOST_v4 HOST_r7
+// "hi" registers
+#define HOST_v5 HOST_r8
+#define HOST_v6 HOST_r9
+#define HOST_v7 HOST_r10
+#define HOST_v8 HOST_r11
+#define HOST_ip HOST_r12
+#define HOST_sp HOST_r13
+#define HOST_lr HOST_r14
+#define HOST_pc HOST_r15
+
+
+static void cache_block_closing(Bit8u* block_start,Bitu block_size) {
+#if (__ARM_EABI__)
+       //flush cache - eabi
+       register unsigned long _beg __asm ("a1") = (unsigned long)(block_start);                                // block start
+       register unsigned long _end __asm ("a2") = (unsigned long)(block_start+block_size);             // block end
+       register unsigned long _flg __asm ("a3") = 0;
+       register unsigned long _par __asm ("r7") = 0xf0002;                                                                             // sys_cacheflush
+       __asm __volatile ("swi 0x0"
+               : // no outputs
+               : "r" (_beg), "r" (_end), "r" (_flg), "r" (_par)
+               );
+#else
+// GP2X BEGIN
+       //flush cache - old abi
+       register unsigned long _beg __asm ("a1") = (unsigned long)(block_start);                                // block start
+       register unsigned long _end __asm ("a2") = (unsigned long)(block_start+block_size);             // block end
+       register unsigned long _flg __asm ("a3") = 0;
+       __asm __volatile ("swi 0x9f0002         @ sys_cacheflush"
+               : // no outputs
+               : "r" (_beg), "r" (_end), "r" (_flg)
+               );
+// GP2X END
+#endif
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-o3.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-o3.h
new file mode 100644 (file)
index 0000000..3596c48
--- /dev/null
@@ -0,0 +1,1302 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/* ARMv4/ARMv7 (little endian) backend by M-HT (arm version) */
+
+
+// temporary registers
+#define temp1 HOST_ip
+#define temp2 HOST_v3
+#define temp3 HOST_v4
+
+// register that holds function return values
+#define FC_RETOP HOST_a1
+
+// register used for address calculations,
+#define FC_ADDR HOST_v1                        // has to be saved across calls, see DRC_PROTECT_ADDR_REG
+
+// register that holds the first parameter
+#define FC_OP1 HOST_a1
+
+// register that holds the second parameter
+#define FC_OP2 HOST_a2
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_v2
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_a1
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_a2
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_v2
+
+// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
+#define FC_REGS_ADDR HOST_v7
+
+// used to hold the address of "Segs" - preferably filled in function gen_run_code
+#define FC_SEGS_ADDR HOST_v8
+
+// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
+#define readdata_addr HOST_v5
+
+
+// helper macro
+#define ROTATE_SCALE(x) ( (x)?(32 - x):(0) )
+
+
+// instruction encodings
+
+// move
+// mov dst, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define MOV_IMM(dst, imm, rimm) (0xe3a00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
+// mov dst, src, lsl #imm
+#define MOV_REG_LSL_IMM(dst, src, imm) (0xe1a00000 + ((dst) << 12) + (src) + ((imm) << 7) )
+// movs dst, src, lsl #imm
+#define MOVS_REG_LSL_IMM(dst, src, imm) (0xe1b00000 + ((dst) << 12) + (src) + ((imm) << 7) )
+// mov dst, src, lsr #imm
+#define MOV_REG_LSR_IMM(dst, src, imm) (0xe1a00020 + ((dst) << 12) + (src) + ((imm) << 7) )
+// mov dst, src, asr #imm
+#define MOV_REG_ASR_IMM(dst, src, imm) (0xe1a00040 + ((dst) << 12) + (src) + ((imm) << 7) )
+// mov dst, src, lsl rreg
+#define MOV_REG_LSL_REG(dst, src, rreg) (0xe1a00010 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mov dst, src, lsr rreg
+#define MOV_REG_LSR_REG(dst, src, rreg) (0xe1a00030 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mov dst, src, asr rreg
+#define MOV_REG_ASR_REG(dst, src, rreg) (0xe1a00050 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mov dst, src, ror rreg
+#define MOV_REG_ROR_REG(dst, src, rreg) (0xe1a00070 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mvn dst, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define MVN_IMM(dst, imm, rimm) (0xe3e00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
+#if C_TARGETCPU == ARMV7LE
+// movw dst, #imm              @       0 <= imm <= 65535
+#define MOVW(dst, imm) (0xe3000000 + ((dst) << 12) + (((imm) & 0xf000) << 4) + ((imm) & 0x0fff) )
+// movt dst, #imm              @       0 <= imm <= 65535
+#define MOVT(dst, imm) (0xe3400000 + ((dst) << 12) + (((imm) & 0xf000) << 4) + ((imm) & 0x0fff) )
+#endif
+
+// arithmetic
+// add dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// add dst, src1, src2, lsl #imm
+#define ADD_REG_LSL_IMM(dst, src1, src2, imm) (0xe0800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// sub dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define SUB_IMM(dst, src, imm, rimm) (0xe2400000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// sub dst, src1, src2, lsl #imm
+#define SUB_REG_LSL_IMM(dst, src1, src2, imm) (0xe0400000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// rsb dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define RSB_IMM(dst, src, imm, rimm) (0xe2600000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// cmp src, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define CMP_IMM(src, imm, rimm) (0xe3500000 + ((src) << 16) + (imm) + ((rimm) << 7) )
+// nop
+#if C_TARGETCPU == ARMV7LE
+#define NOP (0xe320f000)
+#else
+#define NOP MOV_REG_LSL_IMM(HOST_r0, HOST_r0, 0)
+#endif
+
+// logical
+// tst src, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define TST_IMM(src, imm, rimm) (0xe3100000 + ((src) << 16) + (imm) + ((rimm) << 7) )
+// and dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define AND_IMM(dst, src, imm, rimm) (0xe2000000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// and dst, src1, src2, lsl #imm
+#define AND_REG_LSL_IMM(dst, src1, src2, imm) (0xe0000000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// orr dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define ORR_IMM(dst, src, imm, rimm) (0xe3800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// orr dst, src1, src2, lsl #imm
+#define ORR_REG_LSL_IMM(dst, src1, src2, imm) (0xe1800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// orr dst, src1, src2, lsr #imm
+#define ORR_REG_LSR_IMM(dst, src1, src2, imm) (0xe1800020 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// eor dst, src1, src2, lsl #imm
+#define EOR_REG_LSL_IMM(dst, src1, src2, imm) (0xe0200000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// bic dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define BIC_IMM(dst, src, imm, rimm) (0xe3c00000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// bic dst, src1, src2, lsl #imm               @       0 <= imm <= 31
+#define BIC_REG_LSL_IMM(dst, src1, src2, imm) (0xe1c00000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 4096
+#define LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// ldr reg, [addr, #-(imm)]            @       0 <= imm < 4096
+#define LDR_IMM_M(reg, addr, imm) (0xe5100000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// ldrh reg, [addr, #imm]              @       0 <= imm < 256
+#define LDRH_IMM(reg, addr, imm) (0xe1d000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
+// ldrh reg, [addr, #-(imm)]           @       0 <= imm < 256
+#define LDRH_IMM_M(reg, addr, imm) (0xe15000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
+// ldrb reg, [addr, #imm]              @       0 <= imm < 4096
+#define LDRB_IMM(reg, addr, imm) (0xe5d00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// ldrb reg, [addr, #-(imm)]           @       0 <= imm < 4096
+#define LDRB_IMM_M(reg, addr, imm) (0xe5500000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// ldr reg, [addr1, addr2, lsl #imm]           @       0 <= imm < 31
+#define LDR_REG_LSL_IMM(reg, addr1, addr2, imm) (0xe7900000 + ((reg) << 12) + ((addr1) << 16) + (addr2) + ((imm) << 7) )
+
+// store
+// str reg, [addr, #imm]               @       0 <= imm < 4096
+#define STR_IMM(reg, addr, imm) (0xe5800000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// str reg, [addr, #-(imm)]            @       0 <= imm < 4096
+#define STR_IMM_M(reg, addr, imm) (0xe5000000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// strh reg, [addr, #imm]              @       0 <= imm < 256
+#define STRH_IMM(reg, addr, imm) (0xe1c000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
+// strh reg, [addr, #-(imm)]           @       0 <= imm < 256
+#define STRH_IMM_M(reg, addr, imm) (0xe14000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
+// strb reg, [addr, #imm]              @       0 <= imm < 4096
+#define STRB_IMM(reg, addr, imm) (0xe5c00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// strb reg, [addr, #-(imm)]           @       0 <= imm < 4096
+#define STRB_IMM_M(reg, addr, imm) (0xe5400000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// branch
+// beq pc+imm          @       0 <= imm < 32M  &       imm mod 4 = 0
+#define BEQ_FWD(imm) (0x0a000000 + ((imm) >> 2) )
+// bne pc+imm          @       0 <= imm < 32M  &       imm mod 4 = 0
+#define BNE_FWD(imm) (0x1a000000 + ((imm) >> 2) )
+// ble pc+imm          @       0 <= imm < 32M  &       imm mod 4 = 0
+#define BLE_FWD(imm) (0xda000000 + ((imm) >> 2) )
+// b pc+imm            @       0 <= imm < 32M  &       imm mod 4 = 0
+#define B_FWD(imm) (0xea000000 + ((imm) >> 2) )
+// bx reg
+#define BX(reg) (0xe12fff10 + (reg) )
+#if C_TARGETCPU == ARMV7LE
+// blx reg
+#define BLX_REG(reg) (0xe12fff30 + (reg) )
+
+// extend
+// sxth dst, src, ror #rimm            @       rimm = 0 | 8 | 16 | 24
+#define SXTH(dst, src, rimm) (0xe6bf0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
+// sxtb dst, src, ror #rimm            @       rimm = 0 | 8 | 16 | 24
+#define SXTB(dst, src, rimm) (0xe6af0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
+// uxth dst, src, ror #rimm            @       rimm = 0 | 8 | 16 | 24
+#define UXTH(dst, src, rimm) (0xe6ff0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
+// uxtb dst, src, ror #rimm            @       rimm = 0 | 8 | 16 | 24
+#define UXTB(dst, src, rimm) (0xe6ef0070 + ((dst) << 12) + (src) + (((rimm) & 24) << 7) )
+
+// bit field
+// bfi dst, src, #lsb, #width          @       lsb >= 0, width >= 1, lsb+width <= 32
+#define BFI(dst, src, lsb, width) (0xe7c00010 + ((dst) << 12) + (src) + ((lsb) << 7) + (((lsb) + (width) - 1) << 16) )
+// bfc dst, #lsb, #width               @       lsb >= 0, width >= 1, lsb+width <= 32
+#define BFC(dst, lsb, width) (0xe7c0001f + ((dst) << 12) + ((lsb) << 7) + (((lsb) + (width) - 1) << 16) )
+#endif
+
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       if(reg_src == reg_dst) return;
+       cache_addd( MOV_REG_LSL_IMM(reg_dst, reg_src, 0) );      // mov reg_dst, reg_src
+}
+
+// helper function
+static bool val_is_operand2(Bit32u value, Bit32u *val_shift) {
+       Bit32u shift;
+
+       if (GCC_UNLIKELY(value == 0)) {
+               *val_shift = 0;
+               return true;
+       }
+
+       shift = 0;
+       while ((value & 3) == 0) {
+               value>>=2;
+               shift+=2;
+       }
+
+       if ((value >> 8) != 0) return false;
+
+       *val_shift = shift;
+       return true;
+}
+
+#if C_TARGETCPU != ARMV7LE
+// helper function
+static Bits get_imm_gen_len(Bit32u imm) {
+       Bits ret;
+       if (imm == 0) {
+               return 1;
+       } else {
+               ret = 0;
+               while (imm) {
+                       while ((imm & 3) == 0) {
+                               imm>>=2;
+                       }
+                       ret++;
+                       imm>>=8;
+               }
+               return ret;
+       }
+}
+
+// helper function
+static Bits get_min_imm_gen_len(Bit32u imm) {
+       Bits num1, num2;
+
+       num1 = get_imm_gen_len(imm);
+       num2 = get_imm_gen_len(~imm);
+
+       return (num1 <= num2)?num1:num2;
+}
+#endif
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+#if C_TARGETCPU == ARMV7LE
+       Bit32u scale;
+
+       if ( val_is_operand2(imm, &scale) ) {
+               cache_addd( MOV_IMM(dest_reg, imm >> scale, ROTATE_SCALE(scale)) );      // mov dest_reg, #imm
+       } else if ( val_is_operand2(~imm, &scale) ) {
+               cache_addd( MVN_IMM(dest_reg, (~imm) >> scale, ROTATE_SCALE(scale)) );      // mvn dest_reg, #~imm
+       } else {
+               cache_addd( MOVW(dest_reg, imm & 0xffff) );      // movw dest_reg, #(imm & 0xffff)
+
+               if (imm >= 0x10000)
+               {
+                       cache_addd( MOVT(dest_reg, imm >> 16) );      // movt dest_reg, #(imm >> 16)
+               }
+       }
+#else
+       Bit32u imm2, first, scale;
+
+       scale = 0;
+       first = 1;
+       imm2 = ~imm;
+
+       if (get_imm_gen_len(imm) <= get_imm_gen_len(imm2)) {
+               if (imm == 0) {
+                       cache_addd( MOV_IMM(dest_reg, 0, 0) );      // mov dest_reg, #0
+               } else {
+                       while (imm) {
+                               while ((imm & 3) == 0) {
+                                       imm>>=2;
+                                       scale+=2;
+                               }
+                               if (first) {
+                                       cache_addd( MOV_IMM(dest_reg, imm & 0xff, ROTATE_SCALE(scale)) );      // mov dest_reg, #((imm & 0xff) << scale)
+                                       first = 0;
+                               } else {
+                                       cache_addd( ORR_IMM(dest_reg, dest_reg, imm & 0xff, ROTATE_SCALE(scale)) );      // orr dest_reg, dest_reg, #((imm & 0xff) << scale)
+                               }
+                               imm>>=8;
+                               scale+=8;
+                       }
+               }
+       } else {
+               if (imm2 == 0) {
+                       cache_addd( MVN_IMM(dest_reg, 0, 0) );      // mvn dest_reg, #0
+               } else {
+                       while (imm2) {
+                               while ((imm2 & 3) == 0) {
+                                       imm2>>=2;
+                                       scale+=2;
+                               }
+                               if (first) {
+                                       cache_addd( MVN_IMM(dest_reg, imm2 & 0xff, ROTATE_SCALE(scale)) );      // mvn dest_reg, #((imm2 & 0xff) << scale)
+                                       first = 0;
+                               } else {
+                                       cache_addd( BIC_IMM(dest_reg, dest_reg, imm2 & 0xff, ROTATE_SCALE(scale)) );      // bic dest_reg, dest_reg, #((imm2 & 0xff) << scale)
+                               }
+                               imm2>>=8;
+                               scale+=8;
+                       }
+               }
+       }
+#endif
+}
+
+// helper function
+static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 4096)) {
+                                       cache_addd( LDR_IMM(dest_reg, addr_reg, data - addr_data) );      // ldr dest_reg, [addr_reg, #(data - addr_data)]
+                                       return true;
+                               } else if ((data < addr_data) && (data > addr_data - 4096)) {
+                                       cache_addd( LDR_IMM_M(dest_reg, addr_reg, addr_data - data) );      // ldr dest_reg, [addr_reg, #-(addr_data - data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 256)) {
+                                       cache_addd( LDRH_IMM(dest_reg, addr_reg, data - addr_data) );      // ldrh dest_reg, [addr_reg, #(data - addr_data)]
+                                       return true;
+                               } else if ((data < addr_data) && (data > addr_data - 256)) {
+                                       cache_addd( LDRH_IMM_M(dest_reg, addr_reg, addr_data - data) );      // ldrh dest_reg, [addr_reg, #-(addr_data - data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 4096)) {
+                               cache_addd( LDRB_IMM(dest_reg, addr_reg, data - addr_data) );      // ldrb dest_reg, [addr_reg, #(data - addr_data)]
+                               return true;
+                       } else if ((data < addr_data) && (data > addr_data - 4096)) {
+                               cache_addd( LDRB_IMM_M(dest_reg, addr_reg, addr_data - data) );      // ldrb dest_reg, [addr_reg, #-(addr_data - data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_to_reg
+static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+               if ((Bit32u)data & 3) {
+                       if ( ((Bit32u)data & 3) == 2 ) {
+                               cache_addd( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+                               cache_addd( LDRH_IMM(temp2, data_reg, 2) );      // ldrh temp2, [data_reg, #2]
+                               cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 16) );      // orr dest_reg, dest_reg, temp2, lsl #16
+                       } else {
+                               cache_addd( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                               cache_addd( LDRH_IMM(temp2, data_reg, 1) );      // ldrh temp2, [data_reg, #1]
+                               cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) );      // orr dest_reg, dest_reg, temp2, lsl #8
+                               cache_addd( LDRB_IMM(temp2, data_reg, 3) );      // ldrb temp2, [data_reg, #3]
+                               cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 24) );      // orr dest_reg, dest_reg, temp2, lsl #24
+                       }
+               } else
+#endif
+               {
+                       cache_addd( LDR_IMM(dest_reg, data_reg, 0) );      // ldr dest_reg, [data_reg]
+               }
+       } else {
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+               if ((Bit32u)data & 1) {
+                       cache_addd( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                       cache_addd( LDRB_IMM(temp2, data_reg, 1) );      // ldrb temp2, [data_reg, #1]
+                       cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) );      // orr dest_reg, dest_reg, temp2, lsl #8
+               } else
+#endif
+               {
+                       cache_addd( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+               }
+       }
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
+               gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1);
+       }
+}
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
+}
+
+// helper function
+static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 4096)) {
+                                       cache_addd( STR_IMM(src_reg, addr_reg, data - addr_data) );      // str src_reg, [addr_reg, #(data - addr_data)]
+                                       return true;
+                               } else if ((data < addr_data) && (data > addr_data - 4096)) {
+                                       cache_addd( STR_IMM_M(src_reg, addr_reg, addr_data - data) );      // str src_reg, [addr_reg, #-(addr_data - data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 256)) {
+                                       cache_addd( STRH_IMM(src_reg, addr_reg, data - addr_data) );      // strh src_reg, [addr_reg, #(data - addr_data)]
+                                       return true;
+                               } else if ((data < addr_data) && (data > addr_data - 256)) {
+                                       cache_addd( STRH_IMM_M(src_reg, addr_reg, addr_data - data) );      // strh src_reg, [addr_reg, #-(addr_data - data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 4096)) {
+                               cache_addd( STRB_IMM(src_reg, addr_reg, data - addr_data) );      // strb src_reg, [addr_reg, #(data - addr_data)]
+                               return true;
+                       } else if ((data < addr_data) && (data > addr_data - 4096)) {
+                               cache_addd( STRB_IMM_M(src_reg, addr_reg, addr_data - data) );      // strb src_reg, [addr_reg, #-(addr_data - data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_from_reg
+static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+               if ((Bit32u)dest & 3) {
+                       if ( ((Bit32u)dest & 3) == 2 ) {
+                               cache_addd( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+                               cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 16) );      // mov temp2, src_reg, lsr #16
+                               cache_addd( STRH_IMM(temp2, data_reg, 2) );      // strh temp2, [data_reg, #2]
+                       } else {
+                               cache_addd( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                               cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) );      // mov temp2, src_reg, lsr #8
+                               cache_addd( STRH_IMM(temp2, data_reg, 1) );      // strh temp2, [data_reg, #1]
+                               cache_addd( MOV_REG_LSR_IMM(temp2, temp2, 16) );      // mov temp2, temp2, lsr #16
+                               cache_addd( STRB_IMM(temp2, data_reg, 3) );      // strb temp2, [data_reg, #3]
+                       }
+               } else
+#endif
+               {
+                       cache_addd( STR_IMM(src_reg, data_reg, 0) );      // str src_reg, [data_reg]
+               }
+       } else {
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+               if ((Bit32u)dest & 1) {
+                       cache_addd( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                       cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) );      // mov temp2, src_reg, lsr #8
+                       cache_addd( STRB_IMM(temp2, data_reg, 1) );      // strb temp2, [data_reg, #1]
+               } else
+#endif
+               {
+                       cache_addd( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+               }
+       }
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+               gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1);
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
+               gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
+               cache_addd( LDRB_IMM(dest_reg, temp1, 0) );      // ldrb dest_reg, [temp1]
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       gen_mov_byte_to_reg_low(dest_reg, data);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       cache_addd( MOV_IMM(dest_reg, imm, 0) );      // mov dest_reg, #(imm)
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       gen_mov_byte_to_reg_low_imm(dest_reg, imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
+               gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+               cache_addd( STRB_IMM(src_reg, temp1, 0) );      // strb src_reg, [temp1]
+       }
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       if (sign) {
+#if C_TARGETCPU == ARMV7LE
+               cache_addd( SXTB(reg, reg, 0) );      // sxtb reg, reg
+#else
+               cache_addd( MOV_REG_LSL_IMM(reg, reg, 24) );      // mov reg, reg, lsl #24
+               cache_addd( MOV_REG_ASR_IMM(reg, reg, 24) );      // mov reg, reg, asr #24
+#endif
+       } else {
+#if C_TARGETCPU == ARMV7LE
+               cache_addd( UXTB(reg, reg, 0) );      // uxtb reg, reg
+#else
+               cache_addd( AND_IMM(reg, reg, 0xff, 0) );      // and reg, reg, #0xff
+#endif
+       }
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       if (sign) {
+#if C_TARGETCPU == ARMV7LE
+               cache_addd( SXTH(reg, reg, 0) );      // sxth reg, reg
+#else
+               cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) );      // mov reg, reg, lsl #16
+               cache_addd( MOV_REG_ASR_IMM(reg, reg, 16) );      // mov reg, reg, asr #16
+#endif
+       } else {
+#if C_TARGETCPU == ARMV7LE
+               cache_addd( UXTH(reg, reg, 0) );      // uxth reg, reg
+#else
+               cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) );      // mov reg, reg, lsl #16
+               cache_addd( MOV_REG_LSR_IMM(reg, reg, 16) );      // mov reg, reg, lsr #16
+#endif
+       }
+}
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       gen_mov_word_to_reg(temp3, op, 1);
+       cache_addd( ADD_REG_LSL_IMM(reg, reg, temp3, 0) );      // add reg, reg, temp3
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       if(!imm) return;
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if ( val_is_operand2(imm, &scale) ) {
+               cache_addd( ADD_IMM(reg, reg, imm >> scale, ROTATE_SCALE(scale)) );      // add reg, reg, #imm
+       } else if ( val_is_operand2(imm2, &scale) ) {
+               cache_addd( SUB_IMM(reg, reg, imm2 >> scale, ROTATE_SCALE(scale)) );      // sub reg, reg, #(-imm)
+#if C_TARGETCPU == ARMV7LE
+       } else if (imm2 < 0x10000) {
+               cache_addd( MOVW(temp2, imm2) );      // movw temp2, #(-imm)
+               cache_addd( SUB_REG_LSL_IMM(reg, reg, temp2, 0) );      // sub reg, reg, temp2
+#endif
+       } else {
+#if C_TARGETCPU != ARMV7LE
+               if (get_min_imm_gen_len(imm) <= get_min_imm_gen_len(imm2)) {
+#endif
+                       gen_mov_dword_to_reg_imm(temp2, imm);
+                       cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) );      // add reg, reg, temp2
+#if C_TARGETCPU != ARMV7LE
+               } else {
+                       gen_mov_dword_to_reg_imm(temp2, imm2);
+                       cache_addd( SUB_REG_LSL_IMM(reg, reg, temp2, 0) );      // sub reg, reg, temp2
+               }
+#endif
+       }
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       imm2 = ~imm;
+       if(!imm2) return;
+
+       if (!imm) {
+               cache_addd( MOV_IMM(reg, 0, 0) );      // mov reg, #0
+       } else if ( val_is_operand2(imm, &scale) ) {
+               cache_addd( AND_IMM(reg, reg, imm >> scale, ROTATE_SCALE(scale)) );      // and reg, reg, #imm
+       } else if ( val_is_operand2(imm2, &scale) ) {
+               cache_addd( BIC_IMM(reg, reg, imm2 >> scale, ROTATE_SCALE(scale)) );      // bic reg, reg, #(~imm)
+#if C_TARGETCPU == ARMV7LE
+       } else if (imm2 < 0x10000) {
+               cache_addd( MOVW(temp2, imm2) );      // movw temp2, #(~imm)
+               cache_addd( BIC_REG_LSL_IMM(reg, reg, temp2, 0) );      // bic reg, reg, temp2
+#endif
+       } else {
+               gen_mov_dword_to_reg_imm(temp2, imm);
+               cache_addd( AND_REG_LSL_IMM(reg, reg, temp2, 0) );      // and reg, reg, temp2
+       }
+}
+
+
+// move a 32bit constant value into memory
+static void gen_mov_direct_dword(void* dest,Bit32u imm) {
+       gen_mov_dword_to_reg_imm(temp3, imm);
+       gen_mov_word_from_reg(temp3, dest, 1);
+}
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_direct_dword(dest,(Bit32u)imm);
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(temp3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
+       }
+       gen_add_imm(temp3, imm);
+       if (!gen_mov_memval_from_reg(temp3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
+       }
+}
+
+// add an 8bit constant value to a dword memory value
+static void gen_add_direct_byte(void* dest,Bit8s imm) {
+       gen_add_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       Bit32u imm2, scale;
+
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(temp3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
+       }
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if ( val_is_operand2(imm, &scale) ) {
+               cache_addd( SUB_IMM(temp3, temp3, imm >> scale, ROTATE_SCALE(scale)) );      // sub temp3, temp3, #imm
+       } else if ( val_is_operand2(imm2, &scale) ) {
+               cache_addd( ADD_IMM(temp3, temp3, imm2 >> scale, ROTATE_SCALE(scale)) );      // add temp3, temp3, #(-imm)
+#if C_TARGETCPU == ARMV7LE
+       } else if (imm2 < 0x10000) {
+               cache_addd( MOVW(temp2, imm2) );      // movw temp2, #(-imm)
+               cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // add temp3, temp3, temp2
+#endif
+       } else {
+#if C_TARGETCPU != ARMV7LE
+               if (get_min_imm_gen_len(imm) <= get_min_imm_gen_len(imm2)) {
+#endif
+                       gen_mov_dword_to_reg_imm(temp2, imm);
+                       cache_addd( SUB_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // sub temp3, temp3, temp2
+#if C_TARGETCPU != ARMV7LE
+               } else {
+                       gen_mov_dword_to_reg_imm(temp2, imm2);
+                       cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // add temp3, temp3, temp2
+               }
+#endif
+       }
+
+       if (!gen_mov_memval_from_reg(temp3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
+       }
+}
+
+// subtract an 8bit constant value from a dword memory value
+static void gen_sub_direct_byte(void* dest,Bit8s imm) {
+       gen_sub_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       cache_addd( ADD_REG_LSL_IMM(dest_reg, dest_reg, scale_reg, scale) );      // add dest_reg, dest_reg, scale_reg, lsl #(scale)
+       gen_add_imm(dest_reg, imm);
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_addd( MOV_REG_LSL_IMM(dest_reg, dest_reg, scale) );      // mov dest_reg, dest_reg, lsl #(scale)
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+#if C_TARGETCPU == ARMV7LE
+       cache_addd( MOVW(temp1, ((Bit32u)func) & 0xffff) );      // movw temp1, #(func & 0xffff)
+       cache_addd( MOVT(temp1, ((Bit32u)func) >> 16) );      // movt temp1, #(func >> 16)
+       cache_addd( BLX_REG(temp1) );      // blx temp1
+#else
+       cache_addd( LDR_IMM(temp1, HOST_pc, 4) );      // ldr temp1, [pc, #4]
+       cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) );      // add lr, pc, #4
+       cache_addd( BX(temp1) );      // bx temp1
+       cache_addd((Bit32u)func);      // .int func
+#endif
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       Bit32u proc_addr = (Bit32u)cache.pos;
+       gen_call_function_raw(func);
+       return proc_addr;
+}
+
+#if (1)
+// max of 4 parameters in a1-a4
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, imm);
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, addr);
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       gen_mov_regs(param, reg);
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       gen_mov_word_to_reg(param, (void *)mem, 1);
+}
+#else
+       other arm abis
+#endif
+
+// jump to an address pointed at by ptr, offset is in imm
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       Bit32u scale;
+
+       gen_mov_word_to_reg(temp3, ptr, 1);
+
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+// (*ptr) should be word aligned
+       if ((imm & 0x03) == 0) {
+#endif
+               if ((imm >= 0) && (imm < 4096)) {
+                       cache_addd( LDR_IMM(temp1, temp3, imm) );      // ldr temp1, [temp3, #imm]
+               } else {
+                       gen_mov_dword_to_reg_imm(temp2, imm);
+                       cache_addd( LDR_REG_LSL_IMM(temp1, temp3, temp2, 0) );      // ldr temp1, [temp3, temp2]
+               }
+#if !(defined(C_UNALIGNED_MEMORY) || (C_TARGETCPU == ARMV7LE))
+       } else {
+               gen_add_imm(temp3, imm);
+
+               cache_addd( LDRB_IMM(temp1, temp3, 0) );      // ldrb temp1, [temp3]
+               cache_addd( LDRB_IMM(temp2, temp3, 1) );      // ldrb temp2, [temp3, #1]
+               cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 8) );      // orr temp1, temp1, temp2, lsl #8
+               cache_addd( LDRB_IMM(temp2, temp3, 2) );      // ldrb temp2, [temp3, #2]
+               cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 16) );      // orr temp1, temp1, temp2, lsl #16
+               cache_addd( LDRB_IMM(temp2, temp3, 3) );      // ldrb temp2, [temp3, #3]
+               cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 24) );      // orr temp1, temp1, temp2, lsl #24
+       }
+#endif
+
+       cache_addd( BX(temp1) );      // bx temp1
+}
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
+       if (dword) {
+               cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       } else {
+               cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) );      // movs temp1, reg, lsl #16
+       }
+       cache_addd( BEQ_FWD(0) );      // beq j
+       return ((Bit32u)cache.pos-4);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       if (dword) {
+               cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       } else {
+               cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) );      // movs temp1, reg, lsl #16
+       }
+       cache_addd( BNE_FWD(0) );      // bne j
+       return ((Bit32u)cache.pos-4);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bits len=(Bit32u)cache.pos-(data+8);
+       if (len<0) len=-len;
+       if (len>0x02000000) LOG_MSG("Big jump %d",len);
+#endif
+       *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff );
+}
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       if (isdword) {
+               cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       } else {
+               cache_addd( TST_IMM(reg, 0xff, 0) );      // tst reg, #0xff
+       }
+       cache_addd( BNE_FWD(0) );      // bne j
+       return ((Bit32u)cache.pos-4);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
+       cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       cache_addd( BLE_FWD(0) );      // ble j
+       return ((Bit32u)cache.pos-4);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch_long(Bit32u data) {
+       *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff );
+}
+
+static void gen_run_code(void) {
+#if C_TARGETCPU == ARMV7LE
+       cache_addd(0xe92d4df0);                 // stmfd sp!, {v1-v5,v7,v8,lr}
+
+       cache_addd( MOVW(FC_SEGS_ADDR, ((Bit32u)&Segs) & 0xffff) );      // movw FC_SEGS_ADDR, #(&Segs & 0xffff)
+       cache_addd( MOVT(FC_SEGS_ADDR, ((Bit32u)&Segs) >> 16) );      // movt FC_SEGS_ADDR, #(&Segs >> 16)
+
+       cache_addd( MOVW(FC_REGS_ADDR, ((Bit32u)&cpu_regs) & 0xffff) );      // movw FC_REGS_ADDR, #(&cpu_regs & 0xffff)
+       cache_addd( MOVT(FC_REGS_ADDR, ((Bit32u)&cpu_regs) >> 16) );      // movt FC_REGS_ADDR, #(&cpu_regs >> 16)
+
+       cache_addd( MOVW(readdata_addr, ((Bitu)&core_dynrec.readdata) & 0xffff) );      // movw readdata_addr, #(&core_dynrec.readdata & 0xffff)
+       cache_addd( MOVT(readdata_addr, ((Bitu)&core_dynrec.readdata) >> 16) );      // movt readdata_addr, #(&core_dynrec.readdata >> 16)
+
+       cache_addd( BX(HOST_r0) );                      // bx r0
+#else
+       Bit8u *pos1, *pos2, *pos3;
+
+       cache_addd(0xe92d4df0);                 // stmfd sp!, {v1-v5,v7,v8,lr}
+
+       pos1 = cache.pos;
+       cache_addd( 0 );
+       pos2 = cache.pos;
+       cache_addd( 0 );
+       pos3 = cache.pos;
+       cache_addd( 0 );
+
+       cache_addd( BX(HOST_r0) );                      // bx r0
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+
+       *(Bit32u*)pos1 = LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8));      // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
+       cache_addd((Bit32u)&Segs);      // address of "Segs"
+
+       *(Bit32u*)pos2 = LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8));      // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
+       cache_addd((Bit32u)&cpu_regs);  // address of "cpu_regs"
+
+       *(Bit32u*)pos3 = LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8));      // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
+       cache_addd((Bit32u)&core_dynrec.readdata);  // address of "core_dynrec.readdata"
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+#endif
+}
+
+// return from a function
+static void gen_return_function(void) {
+       cache_addd(0xe8bd8df0);                 // ldmfd sp!, {v1-v5,v7,v8,pc}
+}
+
+#ifdef DRC_FLAGS_INVALIDATION
+
+// called when a call to a function can be replaced by a
+// call to a simpler function
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       // try to avoid function calls but rather directly fill in code
+       switch (flags_type) {
+               case t_ADDb:
+               case t_ADDw:
+               case t_ADDd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=ADD_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // add FC_RETOP, a1, a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_ORb:
+               case t_ORw:
+               case t_ORd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=ORR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // orr FC_RETOP, a1, a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_ANDb:
+               case t_ANDw:
+               case t_ANDd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=AND_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // and FC_RETOP, a1, a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_SUBb:
+               case t_SUBw:
+               case t_SUBd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=SUB_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // sub FC_RETOP, a1, a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_XORb:
+               case t_XORw:
+               case t_XORd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=EOR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);       // eor FC_RETOP, a1, a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_CMPb:
+               case t_CMPw:
+               case t_CMPd:
+               case t_TESTb:
+               case t_TESTw:
+               case t_TESTd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_INCb:
+               case t_INCw:
+               case t_INCd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=ADD_IMM(FC_RETOP, HOST_a1, 1, 0);     // add FC_RETOP, a1, #1
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_DECb:
+               case t_DECw:
+               case t_DECd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=SUB_IMM(FC_RETOP, HOST_a1, 1, 0);     // sub FC_RETOP, a1, #1
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_SHLb:
+               case t_SHLw:
+               case t_SHLd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=MOV_REG_LSL_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsl a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_SHRb:
+                       *(Bit32u*)pos=NOP;                                      // nop
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)(pos+4)=BFC(HOST_a1, 8, 24);  // bfc a1, 8, 24
+                       *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsr a2
+#else
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=AND_IMM(FC_RETOP, HOST_a1, 0xff, 0);                          // and FC_RETOP, a1, #0xff
+                       *(Bit32u*)(pos+12)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, lsr a2
+#endif
+                       break;
+               case t_SHRw:
+                       *(Bit32u*)pos=NOP;                                      // nop
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)(pos+4)=BFC(HOST_a1, 16, 16); // bfc a1, 16, 16
+                       *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsr a2
+#else
+                       *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                       // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+8)=MOV_REG_LSR_IMM(FC_RETOP, FC_RETOP, 16);                      // mov FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+12)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, lsr a2
+#endif
+                       break;
+               case t_SHRd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, lsr a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_SARb:
+                       *(Bit32u*)pos=NOP;                                      // nop
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)(pos+4)=SXTB(FC_RETOP, HOST_a1, 0);                                   // sxtb FC_RETOP, a1
+                       *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
+#else
+                       *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24);                       // mov FC_RETOP, a1, lsl #24
+                       *(Bit32u*)(pos+8)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 24);                      // mov FC_RETOP, FC_RETOP, asr #24
+                       *(Bit32u*)(pos+12)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, asr a2
+#endif
+                       break;
+               case t_SARw:
+                       *(Bit32u*)pos=NOP;                                      // nop
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)(pos+4)=SXTH(FC_RETOP, HOST_a1, 0);                                   // sxth FC_RETOP, a1
+                       *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
+#else
+                       *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                       // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+8)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 16);                      // mov FC_RETOP, FC_RETOP, asr #16
+                       *(Bit32u*)(pos+12)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2);        // mov FC_RETOP, FC_RETOP, asr a2
+#endif
+                       break;
+               case t_SARd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, asr a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_RORb:
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)pos=BFI(HOST_a1, HOST_a1, 8, 8);                                              // bfi a1, a1, 8, 8
+                       *(Bit32u*)(pos+4)=BFI(HOST_a1, HOST_a1, 16, 16);                                // bfi a1, a1, 16, 16
+                       *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
+#else
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24);                                   // mov FC_RETOP, a1, lsl #24
+                       *(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 8);             // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8
+                       *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
+#endif
+                       break;
+               case t_RORw:
+                       *(Bit32u*)pos=NOP;                                      // nop
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)(pos+4)=BFI(HOST_a1, HOST_a1, 16, 16);                                // bfi a1, a1, 16, 16
+                       *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
+#else
+                       *(Bit32u*)(pos+4)=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                               // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
+#endif
+                       break;
+               case t_RORd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               case t_ROLw:
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)pos=BFI(HOST_a1, HOST_a1, 16, 16);                                    // bfi a1, a1, 16, 16
+                       *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                             // rsb a2, a2, #32
+                       *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
+#else
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                                   // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                                             // rsb a2, a2, #32
+                       *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
+#endif
+                       break;
+               case t_ROLd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                             // rsb a2, a2, #32
+                       *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
+#else
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                             // rsb a2, a2, #32
+                       *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2
+#endif
+                       break;
+               case t_NEGb:
+               case t_NEGw:
+               case t_NEGd:
+                       *(Bit32u*)pos=NOP;                                      // nop
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=RSB_IMM(FC_RETOP, HOST_a1, 0, 0);     // rsb FC_RETOP, a1, #0
+#if C_TARGETCPU != ARMV7LE
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+#endif
+                       break;
+               default:
+#if C_TARGETCPU == ARMV7LE
+                       *(Bit32u*)pos=MOVW(temp1, ((Bit32u)fct_ptr) & 0xffff);      // movw temp1, #(fct_ptr & 0xffff)
+                       *(Bit32u*)(pos+4)=MOVT(temp1, ((Bit32u)fct_ptr) >> 16);      // movt temp1, #(fct_ptr >> 16)
+#else
+                       *(Bit32u*)(pos+12)=(Bit32u)fct_ptr;             // simple_func
+#endif
+                       break;
+
+       }
+#else
+#if C_TARGETCPU == ARMV7LE
+       *(Bit32u*)pos=MOVW(temp1, ((Bit32u)fct_ptr) & 0xffff);      // movw temp1, #(fct_ptr & 0xffff)
+       *(Bit32u*)(pos+4)=MOVT(temp1, ((Bit32u)fct_ptr) >> 16);      // movt temp1, #(fct_ptr >> 16)
+#else
+       *(Bit32u*)(pos+12)=(Bit32u)fct_ptr;             // simple_func
+#endif
+#endif
+}
+#endif
+
+static void cache_block_before_close(void) { }
+
+#ifdef DRC_USE_SEGS_ADDR
+
+// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRH_IMM(dest_reg, FC_SEGS_ADDR, index) );      // ldrh dest_reg, [FC_SEGS_ADDR, #index]
+}
+
+// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDR_IMM(dest_reg, FC_SEGS_ADDR, index) );      // ldr dest_reg, [FC_SEGS_ADDR, #index]
+}
+
+// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
+       cache_addd( LDR_IMM(temp1, FC_SEGS_ADDR, index) );      // ldr temp1, [FC_SEGS_ADDR, #index]
+       cache_addd( ADD_REG_LSL_IMM(reg, reg, temp1, 0) );      // add reg, reg, temp1
+}
+
+#endif
+
+#ifdef DRC_USE_REGS_ADDR
+
+// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrh dest_reg, [FC_REGS_ADDR, #index]
+}
+
+// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldr dest_reg, [FC_REGS_ADDR, #index]
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
+       if (dword) {
+               cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldr dest_reg, [FC_REGS_ADDR, #index]
+       } else {
+               cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrh dest_reg, [FC_REGS_ADDR, #index]
+       }
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrb dest_reg, [FC_REGS_ADDR, #index]
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrb dest_reg, [FC_REGS_ADDR, #index]
+}
+
+
+// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
+       cache_addd( LDR_IMM(temp2, FC_REGS_ADDR, index) );      // ldr temp2, [FC_REGS_ADDR, #index]
+       cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) );      // add reg, reg, temp2
+}
+
+
+// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
+static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
+       cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) );      // strh src_reg, [FC_REGS_ADDR, #index]
+}
+
+// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
+       cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) );      // str src_reg, [FC_REGS_ADDR, #index]
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
+       if (dword) {
+               cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) );      // str src_reg, [FC_REGS_ADDR, #index]
+       } else {
+               cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) );      // strh src_reg, [FC_REGS_ADDR, #index]
+       }
+}
+
+// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
+static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
+       cache_addd( STRB_IMM(src_reg, FC_REGS_ADDR, index) );      // strb src_reg, [FC_REGS_ADDR, #index]
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-s3.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-s3.h
new file mode 100644 (file)
index 0000000..8690802
--- /dev/null
@@ -0,0 +1,919 @@
+/*
+ *  Copyright (C) 2002-2010  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* $Id: risc_armv4le-s3.h,v 1.6 2009-06-27 12:51:10 c2woody Exp $ */
+
+
+/* ARMv4 (little endian) backend by M-HT (speed-tweaked arm version) */
+
+
+// temporary registers
+#define temp1 HOST_ip
+#define temp2 HOST_v3
+#define temp3 HOST_v4
+
+// register that holds function return values
+#define FC_RETOP HOST_a1
+
+// register used for address calculations,
+#define FC_ADDR HOST_v1                        // has to be saved across calls, see DRC_PROTECT_ADDR_REG
+
+// register that holds the first parameter
+#define FC_OP1 HOST_a1
+
+// register that holds the second parameter
+#define FC_OP2 HOST_a2
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_v2
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_a1
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_a2
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_v2
+
+#ifdef DRC_USE_REGS_ADDR
+// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
+#define FC_REGS_ADDR HOST_v7
+#endif
+
+#ifdef DRC_USE_SEGS_ADDR
+// used to hold the address of "Segs" - preferably filled in function gen_run_code
+#define FC_SEGS_ADDR HOST_v8
+#endif
+
+
+// helper macro
+#define ROTATE_SCALE(x) ( (x)?(32 - x):(0) )
+
+
+// instruction encodings
+
+// move
+// mov dst, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define MOV_IMM(dst, imm, rimm) (0xe3a00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
+// mov dst, src, lsl #imm
+#define MOV_REG_LSL_IMM(dst, src, imm) (0xe1a00000 + ((dst) << 12) + (src) + ((imm) << 7) )
+// movs dst, src, lsl #imm
+#define MOVS_REG_LSL_IMM(dst, src, imm) (0xe1b00000 + ((dst) << 12) + (src) + ((imm) << 7) )
+// mov dst, src, lsr #imm
+#define MOV_REG_LSR_IMM(dst, src, imm) (0xe1a00020 + ((dst) << 12) + (src) + ((imm) << 7) )
+// mov dst, src, asr #imm
+#define MOV_REG_ASR_IMM(dst, src, imm) (0xe1a00040 + ((dst) << 12) + (src) + ((imm) << 7) )
+// mov dst, src, lsl rreg
+#define MOV_REG_LSL_REG(dst, src, rreg) (0xe1a00010 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mov dst, src, lsr rreg
+#define MOV_REG_LSR_REG(dst, src, rreg) (0xe1a00030 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mov dst, src, asr rreg
+#define MOV_REG_ASR_REG(dst, src, rreg) (0xe1a00050 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mov dst, src, ror rreg
+#define MOV_REG_ROR_REG(dst, src, rreg) (0xe1a00070 + ((dst) << 12) + (src) + ((rreg) << 8) )
+// mvn dst, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define MVN_IMM(dst, imm, rimm) (0xe3e00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
+
+// arithmetic
+// add dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// add dst, src1, src2, lsl #imm
+#define ADD_REG_LSL_IMM(dst, src1, src2, imm) (0xe0800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// sub dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define SUB_IMM(dst, src, imm, rimm) (0xe2400000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// sub dst, src1, src2, lsl #imm
+#define SUB_REG_LSL_IMM(dst, src1, src2, imm) (0xe0400000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// rsb dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define RSB_IMM(dst, src, imm, rimm) (0xe2600000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// cmp src, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define CMP_IMM(src, imm, rimm) (0xe3500000 + ((src) << 16) + (imm) + ((rimm) << 7) )
+// nop
+#define NOP MOV_REG_LSL_IMM(HOST_r0, HOST_r0, 0)
+
+// logical
+// tst src, #(imm ror rimm)            @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define TST_IMM(src, imm, rimm) (0xe3100000 + ((src) << 16) + (imm) + ((rimm) << 7) )
+// and dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define AND_IMM(dst, src, imm, rimm) (0xe2000000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// and dst, src1, src2, lsl #imm
+#define AND_REG_LSL_IMM(dst, src1, src2, imm) (0xe0000000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// orr dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define ORR_IMM(dst, src, imm, rimm) (0xe3800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+// orr dst, src1, src2, lsl #imm
+#define ORR_REG_LSL_IMM(dst, src1, src2, imm) (0xe1800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// orr dst, src1, src2, lsr #imm
+#define ORR_REG_LSR_IMM(dst, src1, src2, imm) (0xe1800020 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// eor dst, src1, src2, lsl #imm
+#define EOR_REG_LSL_IMM(dst, src1, src2, imm) (0xe0200000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
+// bic dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define BIC_IMM(dst, src, imm, rimm) (0xe3c00000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 4096
+#define LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// ldrh reg, [addr, #imm]              @       0 <= imm < 256
+#define LDRH_IMM(reg, addr, imm) (0xe1d000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
+// ldrb reg, [addr, #imm]              @       0 <= imm < 4096
+#define LDRB_IMM(reg, addr, imm) (0xe5d00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// store
+// str reg, [addr, #imm]               @       0 <= imm < 4096
+#define STR_IMM(reg, addr, imm) (0xe5800000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+// strh reg, [addr, #imm]              @       0 <= imm < 256
+#define STRH_IMM(reg, addr, imm) (0xe1c000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
+// strb reg, [addr, #imm]              @       0 <= imm < 4096
+#define STRB_IMM(reg, addr, imm) (0xe5c00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// branch
+// beq pc+imm          @       0 <= imm < 32M  &       imm mod 4 = 0
+#define BEQ_FWD(imm) (0x0a000000 + ((imm) >> 2) )
+// bne pc+imm          @       0 <= imm < 32M  &       imm mod 4 = 0
+#define BNE_FWD(imm) (0x1a000000 + ((imm) >> 2) )
+// bgt pc+imm          @       0 <= imm < 32M  &       imm mod 4 = 0
+#define BGT_FWD(imm) (0xca000000 + ((imm) >> 2) )
+// b pc+imm            @       0 <= imm < 32M  &       imm mod 4 = 0
+#define B_FWD(imm) (0xea000000 + ((imm) >> 2) )
+// bx reg
+#define BX(reg) (0xe12fff10 + (reg) )
+
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       if(reg_src == reg_dst) return;
+       cache_addd( MOV_REG_LSL_IMM(reg_dst, reg_src, 0) );      // mov reg_dst, reg_src
+}
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+       Bits first, scale;
+       if (imm == 0) {
+               cache_addd( MOV_IMM(dest_reg, 0, 0) );      // mov dest_reg, #0
+       } else {
+               scale = 0;
+               first = 1;
+               while (imm) {
+                       while ((imm & 3) == 0) {
+                               imm>>=2;
+                               scale+=2;
+                       }
+                       if (first) {
+                               cache_addd( MOV_IMM(dest_reg, imm & 0xff, ROTATE_SCALE(scale)) );      // mov dest_reg, #((imm & 0xff) << scale)
+                               first = 0;
+                       } else {
+                               cache_addd( ORR_IMM(dest_reg, dest_reg, imm & 0xff, ROTATE_SCALE(scale)) );      // orr dest_reg, dest_reg, #((imm & 0xff) << scale)
+                       }
+                       imm>>=8;
+                       scale+=8;
+               }
+       }
+}
+
+// helper function for gen_mov_word_to_reg
+static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
+       // alignment....
+       if (dword) {
+               if ((Bit32u)data & 3) {
+                       if ( ((Bit32u)data & 3) == 2 ) {
+                               cache_addd( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+                               cache_addd( LDRH_IMM(temp2, data_reg, 2) );      // ldrh temp2, [data_reg, #2]
+                               cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 16) );      // orr dest_reg, dest_reg, temp2, lsl #16
+                       } else {
+                               cache_addd( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                               cache_addd( LDRH_IMM(temp2, data_reg, 1) );      // ldrh temp2, [data_reg, #1]
+                               cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) );      // orr dest_reg, dest_reg, temp2, lsl #8
+                               cache_addd( LDRB_IMM(temp2, data_reg, 3) );      // ldrb temp2, [data_reg, #3]
+                               cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 24) );      // orr dest_reg, dest_reg, temp2, lsl #24
+                       }
+               } else {
+                       cache_addd( LDR_IMM(dest_reg, data_reg, 0) );      // ldr dest_reg, [data_reg]
+               }
+       } else {
+               if ((Bit32u)data & 1) {
+                       cache_addd( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                       cache_addd( LDRB_IMM(temp2, data_reg, 1) );      // ldrb temp2, [data_reg, #1]
+                       cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) );      // orr dest_reg, dest_reg, temp2, lsl #8
+               } else {
+                       cache_addd( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+               }
+       }
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
+       gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1);
+}
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
+}
+
+// helper function for gen_mov_word_from_reg
+static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
+       // alignment....
+       if (dword) {
+               if ((Bit32u)dest & 3) {
+                       if ( ((Bit32u)dest & 3) == 2 ) {
+                               cache_addd( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+                               cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 16) );      // mov temp2, src_reg, lsr #16
+                               cache_addd( STRH_IMM(temp2, data_reg, 2) );      // strh temp2, [data_reg, #2]
+                       } else {
+                               cache_addd( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                               cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) );      // mov temp2, src_reg, lsr #8
+                               cache_addd( STRH_IMM(temp2, data_reg, 1) );      // strh temp2, [data_reg, #1]
+                               cache_addd( MOV_REG_LSR_IMM(temp2, temp2, 16) );      // mov temp2, temp2, lsr #16
+                               cache_addd( STRB_IMM(temp2, data_reg, 3) );      // strb temp2, [data_reg, #3]
+                       }
+               } else {
+                       cache_addd( STR_IMM(src_reg, data_reg, 0) );      // str src_reg, [data_reg]
+               }
+       } else {
+               if ((Bit32u)dest & 1) {
+                       cache_addd( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                       cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) );      // mov temp2, src_reg, lsr #8
+                       cache_addd( STRB_IMM(temp2, data_reg, 1) );      // strb temp2, [data_reg, #1]
+               } else {
+                       cache_addd( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+               }
+       }
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+       gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1);
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
+       cache_addd( LDRB_IMM(dest_reg, temp1, 0) );      // ldrb dest_reg, [temp1]
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       gen_mov_byte_to_reg_low(dest_reg, data);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       cache_addd( MOV_IMM(dest_reg, imm, 0) );      // mov dest_reg, #(imm)
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       gen_mov_byte_to_reg_low_imm(dest_reg, imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+       cache_addd( STRB_IMM(src_reg, temp1, 0) );      // strb src_reg, [temp1]
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       if (sign) {
+               cache_addd( MOV_REG_LSL_IMM(reg, reg, 24) );      // mov reg, reg, lsl #24
+               cache_addd( MOV_REG_ASR_IMM(reg, reg, 24) );      // mov reg, reg, asr #24
+       } else {
+               cache_addd( AND_IMM(reg, reg, 0xff, 0) );      // and reg, reg, #0xff
+       }
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       if (sign) {
+               cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) );      // mov reg, reg, lsl #16
+               cache_addd( MOV_REG_ASR_IMM(reg, reg, 16) );      // mov reg, reg, asr #16
+       } else {
+               cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) );      // mov reg, reg, lsl #16
+               cache_addd( MOV_REG_LSR_IMM(reg, reg, 16) );      // mov reg, reg, lsr #16
+       }
+}
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       gen_mov_word_to_reg(temp3, op, 1);
+       cache_addd( ADD_REG_LSL_IMM(reg, reg, temp3, 0) );      // add reg, reg, temp3
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       Bits scale;
+       if(!imm) return;
+       if (imm == 0xffffffff) {
+               cache_addd( SUB_IMM(reg, reg, 1, 0) );      // sub reg, reg, #1
+       } else {
+               scale = 0;
+               while (imm) {
+                       while ((imm & 3) == 0) {
+                               imm>>=2;
+                               scale+=2;
+                       }
+                       cache_addd( ADD_IMM(reg, reg, imm & 0xff, ROTATE_SCALE(scale)) );      // add reg, reg, #((imm & 0xff) << scale)
+                       imm>>=8;
+                       scale+=8;
+               }
+       }
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       Bits scale;
+       Bit32u imm2;
+       imm2 = ~imm;
+       if(!imm2) return;
+       if (!imm) {
+               cache_addd( MOV_IMM(reg, 0, 0) );      // mov reg, #0
+       } else {
+               scale = 0;
+               while (imm2) {
+                       while ((imm2 & 3) == 0) {
+                               imm2>>=2;
+                               scale+=2;
+                       }
+                       cache_addd( BIC_IMM(reg, reg, imm2 & 0xff, ROTATE_SCALE(scale)) );      // bic reg, reg, #((imm2 & 0xff) << scale)
+                       imm2>>=8;
+                       scale+=8;
+               }
+       }
+}
+
+
+// move a 32bit constant value into memory
+static void gen_mov_direct_dword(void* dest,Bit32u imm) {
+       gen_mov_dword_to_reg_imm(temp3, imm);
+       gen_mov_word_from_reg(temp3, dest, 1);
+}
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_direct_dword(dest,(Bit32u)imm);
+}
+
+// add an 8bit constant value to a dword memory value
+static void gen_add_direct_byte(void* dest,Bit8s imm) {
+       if(!imm) return;
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+       gen_mov_word_to_reg_helper(temp3, dest, 1, temp1);
+       if (imm >= 0) {
+               cache_addd( ADD_IMM(temp3, temp3, (Bit32s)imm, 0) );      // add temp3, temp3, #(imm)
+       } else {
+               cache_addd( SUB_IMM(temp3, temp3, -((Bit32s)imm), 0) );      // sub temp3, temp3, #(-imm)
+       }
+       gen_mov_word_from_reg_helper(temp3, dest, 1, temp1);
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if(!imm) return;
+       if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
+               gen_add_direct_byte(dest,(Bit8s)imm);
+               return;
+       }
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+       gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
+       // maybe use function gen_add_imm
+       if (dword) {
+               gen_mov_dword_to_reg_imm(temp2, imm);
+       } else {
+               gen_mov_word_to_reg_imm(temp2, (Bit16u)imm);
+       }
+       cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // add temp3, temp3, temp2
+       gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
+}
+
+// subtract an 8bit constant value from a dword memory value
+static void gen_sub_direct_byte(void* dest,Bit8s imm) {
+       if(!imm) return;
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+       gen_mov_word_to_reg_helper(temp3, dest, 1, temp1);
+       if (imm >= 0) {
+               cache_addd( SUB_IMM(temp3, temp3, (Bit32s)imm, 0) );      // sub temp3, temp3, #(imm)
+       } else {
+               cache_addd( ADD_IMM(temp3, temp3, -((Bit32s)imm), 0) );      // add temp3, temp3, #(-imm)
+       }
+       gen_mov_word_from_reg_helper(temp3, dest, 1, temp1);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       if(!imm) return;
+       if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
+               gen_sub_direct_byte(dest,(Bit8s)imm);
+               return;
+       }
+       gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
+       gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
+       // maybe use function gen_add_imm/gen_sub_imm
+       if (dword) {
+               gen_mov_dword_to_reg_imm(temp2, imm);
+       } else {
+               gen_mov_word_to_reg_imm(temp2, (Bit16u)imm);
+       }
+       cache_addd( SUB_REG_LSL_IMM(temp3, temp3, temp2, 0) );      // sub temp3, temp3, temp2
+       gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
+}
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       cache_addd( ADD_REG_LSL_IMM(dest_reg, dest_reg, scale_reg, scale) );      // add dest_reg, dest_reg, scale_reg, lsl #(scale)
+       gen_add_imm(dest_reg, imm);
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_addd( MOV_REG_LSL_IMM(dest_reg, dest_reg, scale) );      // mov dest_reg, dest_reg, lsl #(scale)
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+       cache_addd( LDR_IMM(temp1, HOST_pc, 4) );      // ldr temp1, [pc, #4]
+       cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) );      // add lr, pc, #4
+       cache_addd( BX(temp1) );      // bx temp1
+       cache_addd((Bit32u)func);      // .int func
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       Bit32u proc_addr = (Bit32u)cache.pos;
+       gen_call_function_raw(func);
+       return proc_addr;
+}
+
+#if (1)
+// max of 4 parameters in a1-a4
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, imm);
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, addr);
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       gen_mov_regs(param, reg);
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       gen_mov_word_to_reg(param, (void *)mem, 1);
+}
+#else
+       other arm abis
+#endif
+
+// jump to an address pointed at by ptr, offset is in imm
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       Bits scale;
+       Bitu imm2;
+       gen_mov_word_to_reg(temp3, ptr, 1);
+
+       if (imm) {
+               scale = 0;
+               imm2 = (Bitu)imm;
+               while (imm2) {
+                       while ((imm2 & 3) == 0) {
+                               imm2>>=2;
+                               scale+=2;
+                       }
+                       cache_addd( ADD_IMM(temp3, temp3, imm2 & 0xff, ROTATE_SCALE(scale)) );      // add temp3, temp3, #((imm2 & 0xff) << scale)
+                       imm2>>=8;
+                       scale+=8;
+               }
+       }
+
+#if (1)
+// (*ptr) should be word aligned 
+       if ((imm & 0x03) == 0) {
+               cache_addd( LDR_IMM(temp1, temp3, 0) );      // ldr temp1, [temp3]
+       } else
+#endif
+       {
+               cache_addd( LDRB_IMM(temp1, temp3, 0) );      // ldrb temp1, [temp3]
+               cache_addd( LDRB_IMM(temp2, temp3, 1) );      // ldrb temp2, [temp3, #1]
+               cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 8) );      // orr temp1, temp1, temp2, lsl #8
+               cache_addd( LDRB_IMM(temp2, temp3, 2) );      // ldrb temp2, [temp3, #2]
+               cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 16) );      // orr temp1, temp1, temp2, lsl #16
+               cache_addd( LDRB_IMM(temp2, temp3, 3) );      // ldrb temp2, [temp3, #3]
+               cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 24) );      // orr temp1, temp1, temp2, lsl #24
+       }
+
+       cache_addd( BX(temp1) );      // bx temp1
+}
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
+       if (dword) {
+               cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       } else {
+               cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) );      // movs temp1, reg, lsl #16
+       }
+       cache_addd( BEQ_FWD(0) );      // beq j
+       return ((Bit32u)cache.pos-4);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       if (dword) {
+               cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       } else {
+               cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) );      // movs temp1, reg, lsl #16
+       }
+       cache_addd( BNE_FWD(0) );      // bne j
+       return ((Bit32u)cache.pos-4);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bits len=(Bit32u)cache.pos-(data+8);
+       if (len<0) len=-len;
+       if (len>0x02000000) LOG_MSG("Big jump %d",len);
+#endif
+       *(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff );
+}
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       if (isdword) {
+               cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       } else {
+               cache_addd( TST_IMM(reg, 0xff, 0) );      // tst reg, #0xff
+       }
+       cache_addd( BEQ_FWD(8) );      // beq nobranch (pc +8)
+       cache_addd( LDR_IMM(temp1, HOST_pc, 0) );      // ldr temp1, [pc, #0]
+       cache_addd( BX(temp1) );      // bx temp1
+       cache_addd(0);      // fill j
+       // nobranch:
+       return ((Bit32u)cache.pos-4);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
+       cache_addd( CMP_IMM(reg, 0, 0) );      // cmp reg, #0
+       cache_addd( BGT_FWD(8) );      // bgt nobranch (pc+8)
+       cache_addd( LDR_IMM(temp1, HOST_pc, 0) );      // ldr temp1, [pc, #0]
+       cache_addd( BX(temp1) );      // bx temp1
+       cache_addd(0);      // fill j
+       // nobranch:
+       return ((Bit32u)cache.pos-4);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch_long(Bit32u data) {
+       // this is an absolute branch
+       *(Bit32u*)data=(Bit32u)cache.pos;
+}
+
+static void gen_run_code(void) {
+       cache_addd(0xe92d4000);                 // stmfd sp!, {lr}
+       cache_addd(0xe92d0cf0);                 // stmfd sp!, {v1-v4,v7,v8}
+
+       // adr: 8
+       cache_addd( LDR_IMM(FC_SEGS_ADDR, HOST_pc, 64 - (8 + 8)) );      // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
+       // adr: 12
+       cache_addd( LDR_IMM(FC_REGS_ADDR, HOST_pc, 68 - (12 + 8)) );      // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
+
+       cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) );                  // add lr, pc, #4
+       cache_addd(0xe92d4000);                 // stmfd sp!, {lr}
+       cache_addd( BX(HOST_r0) );                      // bx r0        
+
+       cache_addd(0xe8bd0cf0);                 // ldmfd sp!, {v1-v4,v7,v8}
+
+       cache_addd(0xe8bd4000);                 // ldmfd sp!, {lr}
+       cache_addd( BX(HOST_lr) );                      // bx lr
+
+       // fill up to 64 bytes
+       cache_addd( NOP );                      // nop
+       cache_addd( NOP );                      // nop
+       cache_addd( NOP );                      // nop
+       cache_addd( NOP );                      // nop
+       cache_addd( NOP );                      // nop
+       cache_addd( NOP );                      // nop
+
+       // adr: 64
+       cache_addd((Bit32u)&Segs);      // address of "Segs"
+       // adr: 68
+       cache_addd((Bit32u)&cpu_regs);  // address of "cpu_regs"
+}
+
+// return from a function
+static void gen_return_function(void) {
+       cache_addd(0xe8bd4000);                 // ldmfd sp!, {lr}
+       cache_addd( BX(HOST_lr) );                      // bx lr
+}
+
+#ifdef DRC_FLAGS_INVALIDATION
+
+// called when a call to a function can be replaced by a
+// call to a simpler function
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       // try to avoid function calls but rather directly fill in code
+       switch (flags_type) {
+               case t_ADDb:
+               case t_ADDw:
+               case t_ADDd:
+                       *(Bit32u*)pos=ADD_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);   // add FC_RETOP, a1, a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_ORb:
+               case t_ORw:
+               case t_ORd:
+                       *(Bit32u*)pos=ORR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);   // orr FC_RETOP, a1, a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_ANDb:
+               case t_ANDw:
+               case t_ANDd:
+                       *(Bit32u*)pos=AND_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);   // and FC_RETOP, a1, a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SUBb:
+               case t_SUBw:
+               case t_SUBd:
+                       *(Bit32u*)pos=SUB_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);   // sub FC_RETOP, a1, a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_XORb:
+               case t_XORw:
+               case t_XORd:
+                       *(Bit32u*)pos=EOR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0);   // eor FC_RETOP, a1, a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_CMPb:
+               case t_CMPw:
+               case t_CMPd:
+               case t_TESTb:
+               case t_TESTw:
+               case t_TESTd:
+                       *(Bit32u*)pos=B_FWD(8);                         // b (pc+2*4)
+                       break;
+               case t_INCb:
+               case t_INCw:
+               case t_INCd:
+                       *(Bit32u*)pos=ADD_IMM(FC_RETOP, HOST_a1, 1, 0); // add FC_RETOP, a1, #1
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_DECb:
+               case t_DECw:
+               case t_DECd:
+                       *(Bit32u*)pos=SUB_IMM(FC_RETOP, HOST_a1, 1, 0); // sub FC_RETOP, a1, #1
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SHLb:
+               case t_SHLw:
+               case t_SHLd:
+                       *(Bit32u*)pos=MOV_REG_LSL_REG(FC_RETOP, HOST_a1, HOST_a2);      // mov FC_RETOP, a1, lsl a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SHRb:
+                       *(Bit32u*)pos=AND_IMM(FC_RETOP, HOST_a1, 0xff, 0);                              // and FC_RETOP, a1, #0xff
+                       *(Bit32u*)(pos+4)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SHRw:
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                   // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+4)=MOV_REG_LSR_IMM(FC_RETOP, FC_RETOP, 16);              // mov FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SHRd:
+                       *(Bit32u*)pos=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2);      // mov FC_RETOP, a1, lsr a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SARb:
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24);                   // mov FC_RETOP, a1, lsl #24
+                       *(Bit32u*)(pos+4)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 24);              // mov FC_RETOP, FC_RETOP, asr #24
+                       *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SARw:
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                   // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+4)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 16);              // mov FC_RETOP, FC_RETOP, asr #16
+                       *(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_SARd:
+                       *(Bit32u*)pos=MOV_REG_ASR_REG(FC_RETOP, HOST_a1, HOST_a2);      // mov FC_RETOP, a1, asr a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_RORb:
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24);                                   // mov FC_RETOP, a1, lsl #24
+                       *(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 8);             // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8
+                       *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
+                       break;
+               case t_RORw:
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                                   // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                 // mov FC_RETOP, FC_RETOP, ror a2
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_RORd:
+                       *(Bit32u*)pos=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);      // mov FC_RETOP, a1, ror a2
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_ROLw:
+                       *(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16);                                   // mov FC_RETOP, a1, lsl #16
+                       *(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                                             // rsb a2, a2, #32
+                       *(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16);    // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
+                       *(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2);                // mov FC_RETOP, FC_RETOP, ror a2
+                       break;
+               case t_ROLd:
+                       *(Bit32u*)pos=RSB_IMM(HOST_a2, HOST_a2, 32, 0);                                 // rsb a2, a2, #32
+                       *(Bit32u*)(pos+4)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2);  // mov FC_RETOP, a1, ror a2
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               case t_NEGb:
+               case t_NEGw:
+               case t_NEGd:
+                       *(Bit32u*)pos=RSB_IMM(FC_RETOP, HOST_a1, 0, 0); // rsb FC_RETOP, a1, #0
+                       *(Bit32u*)(pos+4)=NOP;                          // nop
+                       *(Bit32u*)(pos+8)=NOP;                          // nop
+                       *(Bit32u*)(pos+12)=NOP;                         // nop
+                       break;
+               default:
+                       *(Bit32u*)(pos+12)=(Bit32u)fct_ptr;             // simple_func
+                       break;
+
+       }
+#else
+       *(Bit32u*)(pos+12)=(Bit32u)fct_ptr;             // simple_func
+#endif
+}
+#endif
+
+static void cache_block_before_close(void) { }
+
+#ifdef DRC_USE_SEGS_ADDR
+
+// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRH_IMM(dest_reg, FC_SEGS_ADDR, index) );      // ldrh dest_reg, [FC_SEGS_ADDR, #index]
+}
+
+// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDR_IMM(dest_reg, FC_SEGS_ADDR, index) );      // ldr dest_reg, [FC_SEGS_ADDR, #index]
+}
+
+// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
+       cache_addd( LDR_IMM(temp1, FC_SEGS_ADDR, index) );      // ldr temp1, [FC_SEGS_ADDR, #index]
+       cache_addd( ADD_REG_LSL_IMM(reg, reg, temp1, 0) );      // add reg, reg, temp1
+}
+
+#endif
+
+#ifdef DRC_USE_REGS_ADDR
+
+// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrh dest_reg, [FC_REGS_ADDR, #index]
+}
+
+// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldr dest_reg, [FC_REGS_ADDR, #index]
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
+       if (dword) {
+               cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldr dest_reg, [FC_REGS_ADDR, #index]
+       } else {
+               cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrh dest_reg, [FC_REGS_ADDR, #index]
+       }
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrb dest_reg, [FC_REGS_ADDR, #index]
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
+       cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) );      // ldrb dest_reg, [FC_REGS_ADDR, #index]
+}
+
+
+// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
+       cache_addd( LDR_IMM(temp2, FC_REGS_ADDR, index) );      // ldr temp2, [FC_REGS_ADDR, #index]
+       cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) );      // add reg, reg, temp2
+}
+
+
+// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
+static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
+       cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) );      // strh src_reg, [FC_REGS_ADDR, #index]
+}
+
+// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
+       cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) );      // str src_reg, [FC_REGS_ADDR, #index]
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
+       if (dword) {
+               cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) );      // str src_reg, [FC_REGS_ADDR, #index]
+       } else {
+               cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) );      // strh src_reg, [FC_REGS_ADDR, #index]
+       }
+}
+
+// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
+static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
+       cache_addd( STRB_IMM(src_reg, FC_REGS_ADDR, index) );      // strb src_reg, [FC_REGS_ADDR, #index]
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb-iw.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb-iw.h
new file mode 100644 (file)
index 0000000..5d8f8b5
--- /dev/null
@@ -0,0 +1,1505 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/* ARMv4 (little endian) backend by M-HT (thumb version with data pool, requires -mthumb-interwork switch when compiling dosbox) */
+
+
+// temporary "lo" registers
+#define templo1 HOST_v3
+#define templo2 HOST_v4
+#define templo3 HOST_v2
+
+// register that holds function return values
+#define FC_RETOP HOST_a1
+
+// register used for address calculations,
+#define FC_ADDR HOST_v1                        // has to be saved across calls, see DRC_PROTECT_ADDR_REG
+
+// register that holds the first parameter
+#define FC_OP1 HOST_a1
+
+// register that holds the second parameter
+#define FC_OP2 HOST_a2
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_a4
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_a1
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_a2
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_a4
+
+// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
+#define FC_REGS_ADDR HOST_v7
+
+// used to hold the address of "Segs" - preferably filled in function gen_run_code
+#define FC_SEGS_ADDR HOST_v8
+
+// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
+#define readdata_addr HOST_v5
+
+
+// instruction encodings
+
+// move
+// mov dst, #imm               @       0 <= imm <= 255
+#define MOV_IMM(dst, imm) (0x2000 + ((dst) << 8) + (imm) )
+// mov dst, src
+#define MOV_REG(dst, src) ADD_IMM3(dst, src, 0)
+// mov dst, src
+#define MOV_LO_HI(dst, src) (0x4640 + (dst) + (((src) - HOST_r8) << 3) )
+// mov dst, src
+#define MOV_HI_LO(dst, src) (0x4680 + ((dst) - HOST_r8) + ((src) << 3) )
+
+// arithmetic
+// add dst, src, #imm          @       0 <= imm <= 7
+#define ADD_IMM3(dst, src, imm) (0x1c00 + (dst) + ((src) << 3) + ((imm) << 6) )
+// add dst, #imm               @       0 <= imm <= 255
+#define ADD_IMM8(dst, imm) (0x3000 + ((dst) << 8) + (imm) )
+// add dst, src1, src2
+#define ADD_REG(dst, src1, src2) (0x1800 + (dst) + ((src1) << 3) + ((src2) << 6) )
+// add dst, pc, #imm           @       0 <= imm < 1024 &       imm mod 4 = 0
+#define ADD_LO_PC_IMM(dst, imm) (0xa000 + ((dst) << 8) + ((imm) >> 2) )
+// sub dst, src1, src2
+#define SUB_REG(dst, src1, src2) (0x1a00 + (dst) + ((src1) << 3) + ((src2) << 6) )
+// sub dst, src, #imm          @       0 <= imm <= 7
+#define SUB_IMM3(dst, src, imm) (0x1e00 + (dst) + ((src) << 3) + ((imm) << 6) )
+// sub dst, #imm               @       0 <= imm <= 255
+#define SUB_IMM8(dst, imm) (0x3800 + ((dst) << 8) + (imm) )
+// neg dst, src
+#define NEG(dst, src) (0x4240 + (dst) + ((src) << 3) )
+// cmp dst, #imm               @       0 <= imm <= 255
+#define CMP_IMM(dst, imm) (0x2800 + ((dst) << 8) + (imm) )
+// nop
+#define NOP (0x46c0)
+
+// logical
+// and dst, src
+#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) )
+// bic dst, src
+#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) )
+// eor dst, src
+#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) )
+// orr dst, src
+#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) )
+// mvn dst, src
+#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) )
+
+// shift/rotate
+// lsl dst, src, #imm
+#define LSL_IMM(dst, src, imm) (0x0000 + (dst) + ((src) << 3) + ((imm) << 6) )
+// lsl dst, reg
+#define LSL_REG(dst, reg) (0x4080 + (dst) + ((reg) << 3) )
+// lsr dst, src, #imm
+#define LSR_IMM(dst, src, imm) (0x0800 + (dst) + ((src) << 3) + ((imm) << 6) )
+// lsr dst, reg
+#define LSR_REG(dst, reg) (0x40c0 + (dst) + ((reg) << 3) )
+// asr dst, src, #imm
+#define ASR_IMM(dst, src, imm) (0x1000 + (dst) + ((src) << 3) + ((imm) << 6) )
+// asr dst, reg
+#define ASR_REG(dst, reg) (0x4100 + (dst) + ((reg) << 3) )
+// ror dst, reg
+#define ROR_REG(dst, reg) (0x41c0 + (dst) + ((reg) << 3) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 128  &       imm mod 4 = 0
+#define LDR_IMM(reg, addr, imm) (0x6800 + (reg) + ((addr) << 3) + ((imm) << 4) )
+// ldrh reg, [addr, #imm]              @       0 <= imm < 64   &       imm mod 2 = 0
+#define LDRH_IMM(reg, addr, imm) (0x8800 + (reg) + ((addr) << 3) + ((imm) << 5) )
+// ldrb reg, [addr, #imm]              @       0 <= imm < 32
+#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) )
+// ldr reg, [pc, #imm]         @       0 <= imm < 1024 &       imm mod 4 = 0
+#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) )
+// ldr reg, [addr1, addr2]
+#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) )
+
+// store
+// str reg, [addr, #imm]               @       0 <= imm < 128  &       imm mod 4 = 0
+#define STR_IMM(reg, addr, imm) (0x6000 + (reg) + ((addr) << 3) + ((imm) << 4) )
+// strh reg, [addr, #imm]              @       0 <= imm < 64   &       imm mod 2 = 0
+#define STRH_IMM(reg, addr, imm) (0x8000 + (reg) + ((addr) << 3) + ((imm) << 5) )
+// strb reg, [addr, #imm]              @       0 <= imm < 32
+#define STRB_IMM(reg, addr, imm) (0x7000 + (reg) + ((addr) << 3) + ((imm) << 6) )
+
+// branch
+// beq pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BEQ_FWD(imm) (0xd000 + ((imm) >> 1) )
+// bne pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BNE_FWD(imm) (0xd100 + ((imm) >> 1) )
+// bgt pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BGT_FWD(imm) (0xdc00 + ((imm) >> 1) )
+// b pc+imm            @       0 <= imm < 2048 &       imm mod 2 = 0
+#define B_FWD(imm) (0xe000 + ((imm) >> 1) )
+// bx reg
+#define BX(reg) (0x4700 + ((reg) << 3) )
+
+
+// arm instructions
+
+// arithmetic
+// add dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 4096
+#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// store
+// str reg, [addr, #-(imm)]!           @       0 <= imm < 4096
+#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// branch
+// bx reg
+#define ARM_BX(reg) (0xe12fff10 + (reg) )
+
+
+// data pool defines
+#define CACHE_DATA_JUMP         (2)
+#define CACHE_DATA_ALIGN (32)
+#define CACHE_DATA_MIN  (32)
+#define CACHE_DATA_MAX  (288)
+
+// data pool variables
+static Bit8u * cache_datapos = NULL;   // position of data pool in the cache block
+static Bit32u cache_datasize = 0;              // total size of data pool
+static Bit32u cache_dataindex = 0;             // used size of data pool = index of free data item (in bytes) in data pool
+
+
+// forwarded function
+static void INLINE gen_create_branch_short(void * func);
+
+// function to check distance to data pool
+// if too close, then generate jump after data pool
+static void cache_checkinstr(Bit32u size) {
+       if (cache_datasize == 0) {
+               if (cache_datapos != NULL) {
+                       if (cache.pos + size + CACHE_DATA_JUMP >= cache_datapos) {
+                               cache_datapos = NULL;
+                       }
+               }
+               return;
+       }
+
+       if (cache.pos + size + CACHE_DATA_JUMP <= cache_datapos) return;
+
+       {
+               register Bit8u * newcachepos;
+
+               newcachepos = cache_datapos + cache_datasize;
+               gen_create_branch_short(newcachepos);
+               cache.pos = newcachepos;
+       }
+
+       if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size &&
+               cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size)
+       {
+               cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1));
+       } else {
+               register Bit32u cachemodsize;
+
+               cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1);
+
+               if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE ||
+                       cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE)
+               {
+                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1));
+               } else {
+                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1));
+               }
+       }
+
+       cache_datasize = 0;
+       cache_dataindex = 0;
+}
+
+// function to reserve item in data pool
+// returns address of item
+static Bit8u * cache_reservedata(void) {
+       // if data pool not yet initialized, then initialize data pool
+       if (GCC_UNLIKELY(cache_datapos == NULL)) {
+               if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN < cache.block.active->cache.start + CACHE_DATA_MAX) {
+                       cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1));
+               }
+       }
+
+       // if data pool not yet used, then set data pool
+       if (cache_datasize == 0) {
+               // set data pool address is too close (or behind)  cache.pos then set new data pool size
+               if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_JUMP /*+ CACHE_DATA_ALIGN*/ > cache_datapos) {
+                       if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size &&
+                               cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size)
+                       {
+                               cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1));
+                       } else {
+                               register Bit32u cachemodsize;
+
+                               cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1);
+
+                               if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE ||
+                                       cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE)
+                               {
+                                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1));
+                               } else {
+                                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1));
+                               }
+                       }
+               }
+               // set initial data pool size
+               cache_datasize = CACHE_DATA_ALIGN;
+       }
+
+       // if data pool is full, then enlarge data pool
+       if (cache_dataindex == cache_datasize) {
+               cache_datasize += CACHE_DATA_ALIGN;
+       }
+
+       cache_dataindex += 4;
+       return (cache_datapos + (cache_dataindex - 4));
+}
+
+static void cache_block_before_close(void) {
+       // if data pool in use, then resize cache block to include the data pool
+       if (cache_datasize != 0)
+       {
+               cache.pos = cache_datapos + cache_dataindex;
+       }
+
+       // clear the values before next use
+       cache_datapos = NULL;
+       cache_datasize = 0;
+       cache_dataindex = 0;
+}
+
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       if(reg_src == reg_dst) return;
+       cache_checkinstr(2);
+       cache_addw( MOV_REG(reg_dst, reg_src) );      // mov reg_dst, reg_src
+}
+
+// helper function
+static bool val_single_shift(Bit32u value, Bit32u *val_shift) {
+       Bit32u shift;
+
+       if (GCC_UNLIKELY(value == 0)) {
+               *val_shift = 0;
+               return true;
+       }
+
+       shift = 0;
+       while ((value & 1) == 0) {
+               value>>=1;
+               shift+=1;
+       }
+
+       if ((value >> 8) != 0) return false;
+
+       *val_shift = shift;
+       return true;
+}
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+       Bit32u scale;
+
+       if (imm < 256) {
+               cache_checkinstr(2);
+               cache_addw( MOV_IMM(dest_reg, imm) );      // mov dest_reg, #(imm)
+       } else if ((~imm) < 256) {
+               cache_checkinstr(4);
+               cache_addw( MOV_IMM(dest_reg, ~imm) );      // mov dest_reg, #(~imm)
+               cache_addw( MVN(dest_reg, dest_reg) );      // mvn dest_reg, dest_reg
+       } else if (val_single_shift(imm, &scale)) {
+               cache_checkinstr(4);
+               cache_addw( MOV_IMM(dest_reg, imm >> scale) );      // mov dest_reg, #(imm >> scale)
+               cache_addw( LSL_IMM(dest_reg, dest_reg, scale) );      // lsl dest_reg, dest_reg, #scale
+       } else {
+               Bit32u diff;
+
+               cache_checkinstr(4);
+
+               diff = imm - ((Bit32u)cache.pos+4);
+
+               if ((diff < 1024) && ((imm & 0x03) == 0)) {
+                       if (((Bit32u)cache.pos & 0x03) == 0) {
+                               cache_addw( ADD_LO_PC_IMM(dest_reg, diff >> 2) );      // add dest_reg, pc, #(diff >> 2)
+                       } else {
+                               cache_addw( NOP );      // nop
+                               cache_addw( ADD_LO_PC_IMM(dest_reg, (diff - 2) >> 2) );      // add dest_reg, pc, #((diff - 2) >> 2)
+                       }
+               } else {
+                       Bit8u *datapos;
+
+                       datapos = cache_reservedata();
+                       *(Bit32u*)datapos=imm;
+
+                       if (((Bit32u)cache.pos & 0x03) == 0) {
+                               cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 4)) );      // ldr dest_reg, [pc, datapos]
+                       } else {
+                               cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 2)) );      // ldr dest_reg, [pc, datapos]
+                       }
+               }
+       }
+}
+
+// helper function
+static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) );      // ldr dest_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) );      // ldrh dest_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 32)) {
+                               cache_checkinstr(4);
+                               cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                               cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) );      // ldrb dest_reg, [templo2, #(data - addr_data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_to_reg
+static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)data & 3) {
+                       if ( ((Bit32u)data & 3) == 2 ) {
+                               cache_checkinstr(8);
+                               cache_addw( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+                               cache_addw( LDRH_IMM(templo1, data_reg, 2) );      // ldrh templo1, [data_reg, #2]
+                               cache_addw( LSL_IMM(templo1, templo1, 16) );      // lsl templo1, templo1, #16
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                       } else {
+                               cache_checkinstr(16);
+                               cache_addw( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                               cache_addw( ADD_IMM3(templo1, data_reg, 1) );      // add templo1, data_reg, #1
+                               cache_addw( LDRH_IMM(templo1, templo1, 0) );      // ldrh templo1, [templo1]
+                               cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                               cache_addw( LDRB_IMM(templo1, data_reg, 3) );      // ldrb templo1, [data_reg, #3]
+                               cache_addw( LSL_IMM(templo1, templo1, 24) );      // lsl templo1, templo1, #24
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                       }
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( LDR_IMM(dest_reg, data_reg, 0) );      // ldr dest_reg, [data_reg]
+               }
+       } else {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)data & 1) {
+                       cache_checkinstr(8);
+                       cache_addw( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                       cache_addw( LDRB_IMM(templo1, data_reg, 1) );      // ldrb templo1, [data_reg, #1]
+                       cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+                       cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+               }
+       }
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
+               gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
+       }
+}
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
+}
+
+// helper function
+static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( STR_IMM(src_reg, templo2, data - addr_data) );      // str src_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) );      // strh src_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 32)) {
+                               cache_checkinstr(4);
+                               cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                               cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) );      // strb src_reg, [templo2, #(data - addr_data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_from_reg
+static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)dest & 3) {
+                       if ( ((Bit32u)dest & 3) == 2 ) {
+                               cache_checkinstr(8);
+                               cache_addw( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 16) );      // lsr templo1, templo1, #16
+                               cache_addw( STRH_IMM(templo1, data_reg, 2) );      // strh templo1, [data_reg, #2]
+                       } else {
+                               cache_checkinstr(20);
+                               cache_addw( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 8) );      // lsr templo1, templo1, #8
+                               cache_addw( STRB_IMM(templo1, data_reg, 1) );      // strb templo1, [data_reg, #1]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 16) );      // lsr templo1, templo1, #16
+                               cache_addw( STRB_IMM(templo1, data_reg, 2) );      // strb templo1, [data_reg, #2]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 24) );      // lsr templo1, templo1, #24
+                               cache_addw( STRB_IMM(templo1, data_reg, 3) );      // strb templo1, [data_reg, #3]
+                       }
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( STR_IMM(src_reg, data_reg, 0) );      // str src_reg, [data_reg]
+               }
+       } else {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)dest & 1) {
+                       cache_checkinstr(8);
+                       cache_addw( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                       cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                       cache_addw( LSR_IMM(templo1, templo1, 8) );      // lsr templo1, templo1, #8
+                       cache_addw( STRB_IMM(templo1, data_reg, 1) );      // strb templo1, [data_reg, #1]
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+               }
+       }
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
+               gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
+               cache_checkinstr(2);
+               cache_addw( LDRB_IMM(dest_reg, templo1, 0) );      // ldrb dest_reg, [templo1]
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       gen_mov_byte_to_reg_low(dest_reg, data);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       cache_checkinstr(2);
+       cache_addw( MOV_IMM(dest_reg, imm) );      // mov dest_reg, #(imm)
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       gen_mov_byte_to_reg_low_imm(dest_reg, imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
+               gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
+               cache_checkinstr(2);
+               cache_addw( STRB_IMM(src_reg, templo1, 0) );      // strb src_reg, [templo1]
+       }
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       cache_checkinstr(4);
+       cache_addw( LSL_IMM(reg, reg, 24) );      // lsl reg, reg, #24
+
+       if (sign) {
+               cache_addw( ASR_IMM(reg, reg, 24) );      // asr reg, reg, #24
+       } else {
+               cache_addw( LSR_IMM(reg, reg, 24) );      // lsr reg, reg, #24
+       }
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       cache_checkinstr(4);
+       cache_addw( LSL_IMM(reg, reg, 16) );      // lsl reg, reg, #16
+
+       if (sign) {
+               cache_addw( ASR_IMM(reg, reg, 16) );      // asr reg, reg, #16
+       } else {
+               cache_addw( LSR_IMM(reg, reg, 16) );      // lsr reg, reg, #16
+       }
+}
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       gen_mov_word_to_reg(templo3, op, 1);
+       cache_checkinstr(2);
+       cache_addw( ADD_REG(reg, reg, templo3) );      // add reg, reg, templo3
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       if(!imm) return;
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if (imm <= 255) {
+               cache_checkinstr(2);
+               cache_addw( ADD_IMM8(reg, imm) );      // add reg, #imm
+       } else if (imm2 <= 255) {
+               cache_checkinstr(2);
+               cache_addw( SUB_IMM8(reg, imm2) );      // sub reg, #(-imm)
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_checkinstr((scale)?6:4);
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( SUB_REG(reg, reg, templo1) );      // sub reg, reg, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_checkinstr(2);
+                       cache_addw( ADD_REG(reg, reg, templo1) );      // add reg, reg, templo1
+               }
+       }
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       imm2 = ~imm;
+       if(!imm2) return;
+
+       if (!imm) {
+               cache_checkinstr(2);
+               cache_addw( MOV_IMM(reg, 0) );      // mov reg, #0
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_checkinstr((scale)?6:4);
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( BIC(reg, templo1) );      // bic reg, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_checkinstr(2);
+                       cache_addw( AND(reg, templo1) );      // and reg, templo1
+               }
+       }
+}
+
+
+// move a 32bit constant value into memory
+static void gen_mov_direct_dword(void* dest,Bit32u imm) {
+       gen_mov_dword_to_reg_imm(templo3, imm);
+       gen_mov_word_from_reg(templo3, dest, 1);
+}
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_direct_dword(dest,(Bit32u)imm);
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
+       }
+       gen_add_imm(templo3, imm);
+       if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
+       }
+}
+
+// add an 8bit constant value to a dword memory value
+static void gen_add_direct_byte(void* dest,Bit8s imm) {
+       gen_add_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       Bit32u imm2, scale;
+
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
+       }
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if (imm <= 255) {
+               cache_checkinstr(2);
+               cache_addw( SUB_IMM8(templo3, imm) );      // sub templo3, #imm
+       } else if (imm2 <= 255) {
+               cache_checkinstr(2);
+               cache_addw( ADD_IMM8(templo3, imm2) );      // add templo3, #(-imm)
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_checkinstr((scale)?6:4);
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( ADD_REG(templo3, templo3, templo1) );      // add templo3, templo3, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_checkinstr(2);
+                       cache_addw( SUB_REG(templo3, templo3, templo1) );      // sub templo3, templo3, templo1
+               }
+       }
+
+       if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
+       }
+}
+
+// subtract an 8bit constant value from a dword memory value
+static void gen_sub_direct_byte(void* dest,Bit8s imm) {
+       gen_sub_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_checkinstr(4);
+               cache_addw( LSL_IMM(templo1, scale_reg, scale) );      // lsl templo1, scale_reg, #(scale)
+               cache_addw( ADD_REG(dest_reg, dest_reg, templo1) );      // add dest_reg, dest_reg, templo1
+       } else {
+               cache_checkinstr(2);
+               cache_addw( ADD_REG(dest_reg, dest_reg, scale_reg) );      // add dest_reg, dest_reg, scale_reg
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_checkinstr(2);
+               cache_addw( LSL_IMM(dest_reg, dest_reg, scale) );      // lsl dest_reg, dest_reg, #(scale)
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// helper function for gen_call_function_raw and gen_call_function_setup
+static void gen_call_function_helper(void * func) {
+       Bit8u *datapos;
+
+       datapos = cache_reservedata();
+       *(Bit32u*)datapos=(Bit32u)func;
+
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) );      // ldr templo1, [pc, datapos]
+               cache_addw( ADD_LO_PC_IMM(templo2, 8) );      // adr templo2, after_call (add templo2, pc, #8)
+               cache_addw( ADD_IMM8(templo2, 1) );      // add templo2, #1
+               cache_addw( MOV_HI_LO(HOST_lr, templo2) );      // mov lr, templo2
+               cache_addw( BX(templo1) );      // bx templo1     --- switch to arm state
+               cache_addw( NOP );      // nop
+       } else {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) );      // ldr templo1, [pc, datapos]
+               cache_addw( ADD_LO_PC_IMM(templo2, 4) );      // adr templo2, after_call (add templo2, pc, #4)
+               cache_addw( ADD_IMM8(templo2, 1) );      // add templo2, #1
+               cache_addw( MOV_HI_LO(HOST_lr, templo2) );      // mov lr, templo2
+               cache_addw( BX(templo1) );      // bx templo1     --- switch to arm state
+       }
+       // after_call:
+
+       // thumb state from now on
+}
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+       cache_checkinstr(12);
+       gen_call_function_helper(func);
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       cache_checkinstr(12);
+       Bit32u proc_addr = (Bit32u)cache.pos;
+       gen_call_function_helper(func);
+       return proc_addr;
+       // if proc_addr is on word  boundary ((proc_addr & 0x03) == 0)
+       //   then length of generated code is 12 bytes
+       //   otherwise length of generated code is 10 bytes
+}
+
+#if (1)
+// max of 4 parameters in a1-a4
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, imm);
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, addr);
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       gen_mov_regs(param, reg);
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       gen_mov_word_to_reg(param, (void *)mem, 1);
+}
+#else
+       other arm abis
+#endif
+
+// jump to an address pointed at by ptr, offset is in imm
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       gen_mov_word_to_reg(templo3, ptr, 1);
+
+#if !defined(C_UNALIGNED_MEMORY)
+// (*ptr) should be word aligned
+       if ((imm & 0x03) == 0) {
+#endif
+               if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) {
+                       cache_checkinstr(6);
+                       cache_addw( LDR_IMM(templo2, templo3, imm) );      // ldr templo2, [templo3, #imm]
+               } else {
+                       gen_mov_dword_to_reg_imm(templo2, imm);
+                       cache_checkinstr(6);
+                       cache_addw( LDR_REG(templo2, templo3, templo2) );      // ldr templo2, [templo3, templo2]
+               }
+#if !defined(C_UNALIGNED_MEMORY)
+       } else {
+               gen_add_imm(templo3, imm);
+
+               cache_checkinstr(24);
+               cache_addw( LDRB_IMM(templo2, templo3, 0) );      // ldrb templo2, [templo3]
+               cache_addw( LDRB_IMM(templo1, templo3, 1) );      // ldrb templo1, [templo3, #1]
+               cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+               cache_addw( LDRB_IMM(templo1, templo3, 2) );      // ldrb templo1, [templo3, #2]
+               cache_addw( LSL_IMM(templo1, templo1, 16) );      // lsl templo1, templo1, #16
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+               cache_addw( LDRB_IMM(templo1, templo3, 3) );      // ldrb templo1, [templo3, #3]
+               cache_addw( LSL_IMM(templo1, templo1, 24) );      // lsl templo1, templo1, #24
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+       }
+#endif
+
+       // increase jmp address to keep thumb state
+       cache_addw( ADD_IMM3(templo2, templo2, 1) );      // add templo2, templo2, #1
+
+       cache_addw( BX(templo2) );      // bx templo2
+}
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
+       cache_checkinstr(4);
+       if (dword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo1, reg, 16) );      // lsl templo1, reg, #16
+       }
+       cache_addw( BEQ_FWD(0) );      // beq j
+       return ((Bit32u)cache.pos-2);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       cache_checkinstr(4);
+       if (dword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo1, reg, 16) );      // lsl templo1, reg, #16
+       }
+       cache_addw( BNE_FWD(0) );      // bne j
+       return ((Bit32u)cache.pos-2);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bits len=(Bit32u)cache.pos-(data+4);
+       if (len<0) len=-len;
+       if (len>252) LOG_MSG("Big jump %d",len);
+#endif
+       *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 );
+}
+
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       Bit8u *datapos;
+
+       cache_checkinstr(8);
+       datapos = cache_reservedata();
+
+       if (isdword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo2, reg, 24) );      // lsl templo2, reg, #24
+       }
+       cache_addw( BEQ_FWD(2) );      // beq nobranch (pc+2)
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) );      // ldr templo1, [pc, datapos]
+       } else {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) );      // ldr templo1, [pc, datapos]
+       }
+       cache_addw( BX(templo1) );      // bx templo1
+       // nobranch:
+       return ((Bit32u)datapos);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
+       Bit8u *datapos;
+
+       cache_checkinstr(8);
+       datapos = cache_reservedata();
+
+       cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       cache_addw( BGT_FWD(2) );      // bgt nobranch (pc+2)
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) );      // ldr templo1, [pc, datapos]
+       } else {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) );      // ldr templo1, [pc, datapos]
+       }
+       cache_addw( BX(templo1) );      // bx templo1
+       // nobranch:
+       return ((Bit32u)datapos);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch_long(Bit32u data) {
+       // this is an absolute branch
+       *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state
+}
+
+static void gen_run_code(void) {
+       Bit8u *pos1, *pos2, *pos3;
+
+#if (__ARM_EABI__)
+       // 8-byte stack alignment
+       cache_addd(0xe92d4ff0);                 // stmfd sp!, {v1-v8,lr}
+#else
+       cache_addd(0xe92d4df0);                 // stmfd sp!, {v1-v5,v7,v8,lr}
+#endif
+
+       cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) );      // add r0, r0, #1
+
+       pos1 = cache.pos;
+       cache_addd( 0 );
+       pos2 = cache.pos;
+       cache_addd( 0 );
+       pos3 = cache.pos;
+       cache_addd( 0 );
+
+       cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) );                      // add lr, pc, #4
+       cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) );      // str lr, [sp, #-4]!
+       cache_addd( ARM_BX(HOST_r0) );                  // bx r0
+
+#if (__ARM_EABI__)
+       cache_addd(0xe8bd4ff0);                 // ldmfd sp!, {v1-v8,lr}
+#else
+       cache_addd(0xe8bd4df0);                 // ldmfd sp!, {v1-v5,v7,v8,lr}
+#endif
+       cache_addd( ARM_BX(HOST_lr) );                  // bx lr
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+
+       *(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8));      // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
+       cache_addd((Bit32u)&Segs);      // address of "Segs"
+
+       *(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8));      // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
+       cache_addd((Bit32u)&cpu_regs);  // address of "cpu_regs"
+
+       *(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8));      // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
+       cache_addd((Bit32u)&core_dynrec.readdata);  // address of "core_dynrec.readdata"
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+}
+
+// return from a function
+static void gen_return_function(void) {
+       cache_checkinstr(4);
+       cache_addw(0xbc08);      // pop {r3}
+       cache_addw( BX(HOST_r3) );      // bx r3
+}
+
+
+// short unconditional jump (over data pool)
+// must emit at most CACHE_DATA_JUMP bytes
+static void INLINE gen_create_branch_short(void * func) {
+       cache_addw( B_FWD((Bit32u)func - ((Bit32u)cache.pos + 4)) );      // b func
+}
+
+
+#ifdef DRC_FLAGS_INVALIDATION
+
+// called when a call to a function can be replaced by a
+// call to a simpler function
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+       if ((*(Bit16u*)pos & 0xf000) == 0xe000) {
+               if ((*(Bit16u*)pos & 0x0fff) >= ((CACHE_DATA_ALIGN / 2) - 1) &&
+                       (*(Bit16u*)pos & 0x0fff) < 0x0800)
+               {
+                       pos = (Bit8u *) ( ( ( (Bit32u)(*(Bit16u*)pos & 0x0fff) ) << 1 ) + ((Bit32u)pos + 4) );
+               }
+       }
+
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       if (((Bit32u)pos & 0x03) == 0)
+       {
+               // try to avoid function calls but rather directly fill in code
+               switch (flags_type) {
+                       case t_ADDb:
+                       case t_ADDw:
+                       case t_ADDd:
+                               *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2);       // add a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_ORb:
+                       case t_ORw:
+                       case t_ORd:
+                               *(Bit16u*)pos=ORR(HOST_a1, HOST_a2);                            // orr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_ANDb:
+                       case t_ANDw:
+                       case t_ANDd:
+                               *(Bit16u*)pos=AND(HOST_a1, HOST_a2);                            // and a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SUBb:
+                       case t_SUBw:
+                       case t_SUBd:
+                               *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2);       // sub a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_XORb:
+                       case t_XORw:
+                       case t_XORd:
+                               *(Bit16u*)pos=EOR(HOST_a1, HOST_a2);                            // eor a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_CMPb:
+                       case t_CMPw:
+                       case t_CMPd:
+                       case t_TESTb:
+                       case t_TESTw:
+                       case t_TESTd:
+                               *(Bit16u*)pos=B_FWD(8);                                                         // b after_call (pc+8)
+                               break;
+                       case t_INCb:
+                       case t_INCw:
+                       case t_INCd:
+                               *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1);            // add a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_DECb:
+                       case t_DECw:
+                       case t_DECd:
+                               *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1);            // sub a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SHLb:
+                       case t_SHLw:
+                       case t_SHLd:
+                               *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2);                        // lsl a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SHRb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 24);        // lsr a1, a1, #24
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               break;
+                       case t_SHRw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 16);        // lsr a1, a1, #16
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               break;
+                       case t_SHRd:
+                               *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2);                        // lsr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SARb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 24);        // asr a1, a1, #24
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               break;
+                       case t_SARw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 16);        // asr a1, a1, #16
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               break;
+                       case t_SARd:
+                               *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2);                        // asr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_RORb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_RORw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+4)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+6)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+8)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_RORd:
+                               *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2);                        // ror a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_ROLw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_ROLd:
+                               *(Bit16u*)pos=NEG(HOST_a2, HOST_a2);                            // neg a2, a2
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               break;
+                       case t_NEGb:
+                       case t_NEGw:
+                       case t_NEGd:
+                               *(Bit16u*)pos=NEG(HOST_a1, HOST_a1);                            // neg a1, a1
+                               *(Bit16u*)(pos+2)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       default:
+                               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr;         // simple_func
+                               break;
+               }
+       }
+       else
+       {
+               // try to avoid function calls but rather directly fill in code
+               switch (flags_type) {
+                       case t_ADDb:
+                       case t_ADDw:
+                       case t_ADDd:
+                               *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2);       // add a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_ORb:
+                       case t_ORw:
+                       case t_ORd:
+                               *(Bit16u*)pos=ORR(HOST_a1, HOST_a2);                            // orr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_ANDb:
+                       case t_ANDw:
+                       case t_ANDd:
+                               *(Bit16u*)pos=AND(HOST_a1, HOST_a2);                            // and a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_SUBb:
+                       case t_SUBw:
+                       case t_SUBd:
+                               *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2);       // sub a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_XORb:
+                       case t_XORw:
+                       case t_XORd:
+                               *(Bit16u*)pos=EOR(HOST_a1, HOST_a2);                            // eor a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_CMPb:
+                       case t_CMPw:
+                       case t_CMPd:
+                       case t_TESTb:
+                       case t_TESTw:
+                       case t_TESTd:
+                               *(Bit16u*)pos=B_FWD(6);                                                         // b after_call (pc+6)
+                               break;
+                       case t_INCb:
+                       case t_INCw:
+                       case t_INCd:
+                               *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1);            // add a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_DECb:
+                       case t_DECw:
+                       case t_DECd:
+                               *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1);            // sub a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_SHLb:
+                       case t_SHLw:
+                       case t_SHLd:
+                               *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2);                        // lsl a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_SHRb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 24);        // lsr a1, a1, #24
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               break;
+                       case t_SHRw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=LSR_IMM(HOST_a1, HOST_a1, 16);        // lsr a1, a1, #16
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               break;
+                       case t_SHRd:
+                               *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2);                        // lsr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_SARb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 24);        // asr a1, a1, #24
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               break;
+                       case t_SARw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=ASR_IMM(HOST_a1, HOST_a1, 16);        // asr a1, a1, #16
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               break;
+                       case t_SARd:
+                               *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2);                        // asr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_RORw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+4)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+6)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+8)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               break;
+                       case t_RORd:
+                               *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2);                        // ror a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_ROLd:
+                               *(Bit16u*)pos=NEG(HOST_a2, HOST_a2);                            // neg a2, a2
+                               *(Bit16u*)(pos+2)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+4)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               break;
+                       case t_NEGb:
+                       case t_NEGw:
+                       case t_NEGd:
+                               *(Bit16u*)pos=NEG(HOST_a1, HOST_a1);                            // neg a1, a1
+                               *(Bit16u*)(pos+2)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       default:
+                               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr;         // simple_func
+                               break;
+               }
+
+       }
+#else
+       if (((Bit32u)pos & 0x03) == 0)
+       {
+               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr;         // simple_func
+       }
+       else
+       {
+               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr;         // simple_func
+       }
+#endif
+}
+#endif
+
+#ifdef DRC_USE_SEGS_ADDR
+
+// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDRH_IMM(dest_reg, templo1, index) );      // ldrh dest_reg, [templo1, #index]
+}
+
+// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDR_IMM(dest_reg, templo1, index) );      // ldr dest_reg, [templo1, #index]
+}
+
+// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
+       cache_checkinstr(6);
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDR_IMM(templo2, templo1, index) );      // ldr templo2, [templo1, #index]
+       cache_addw( ADD_REG(reg, reg, templo2) );      // add reg, reg, templo2
+}
+
+#endif
+
+#ifdef DRC_USE_REGS_ADDR
+
+// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRH_IMM(dest_reg, templo2, index) );      // ldrh dest_reg, [templo2, #index]
+}
+
+// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDR_IMM(dest_reg, templo2, index) );      // ldr dest_reg, [templo2, #index]
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       if (dword) {
+               cache_addw( LDR_IMM(dest_reg, templo2, index) );      // ldr dest_reg, [templo2, #index]
+       } else {
+               cache_addw( LDRH_IMM(dest_reg, templo2, index) );      // ldrh dest_reg, [templo2, #index]
+       }
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRB_IMM(dest_reg, templo2, index) );      // ldrb dest_reg, [templo2, #index]
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRB_IMM(dest_reg, templo2, index) );      // ldrb dest_reg, [templo2, #index]
+}
+
+
+// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
+       cache_checkinstr(6);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDR_IMM(templo1, templo2, index) );      // ldr templo1, [templo2, #index]
+       cache_addw( ADD_REG(reg, reg, templo1) );      // add reg, reg, templo1
+}
+
+
+// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
+static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STRH_IMM(src_reg, templo1, index) );      // strh src_reg, [templo1, #index]
+}
+
+// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STR_IMM(src_reg, templo1, index) );      // str src_reg, [templo1, #index]
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       if (dword) {
+               cache_addw( STR_IMM(src_reg, templo1, index) );      // str src_reg, [templo1, #index]
+       } else {
+               cache_addw( STRH_IMM(src_reg, templo1, index) );      // strh src_reg, [templo1, #index]
+       }
+}
+
+// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
+static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STRB_IMM(src_reg, templo1, index) );      // strb src_reg, [templo1, #index]
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb-niw.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb-niw.h
new file mode 100644 (file)
index 0000000..e4890c1
--- /dev/null
@@ -0,0 +1,1538 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/* ARMv4 (little endian) backend by M-HT (thumb version with data pool) */
+
+
+// temporary "lo" registers
+#define templo1 HOST_v3
+#define templo2 HOST_v4
+#define templo3 HOST_v2
+
+// register that holds function return values
+#define FC_RETOP HOST_a1
+
+// register used for address calculations,
+#define FC_ADDR HOST_v1                        // has to be saved across calls, see DRC_PROTECT_ADDR_REG
+
+// register that holds the first parameter
+#define FC_OP1 HOST_a1
+
+// register that holds the second parameter
+#define FC_OP2 HOST_a2
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_a4
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_a1
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_a2
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_a4
+
+// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
+#define FC_REGS_ADDR HOST_v7
+
+// used to hold the address of "Segs" - preferably filled in function gen_run_code
+#define FC_SEGS_ADDR HOST_v8
+
+// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
+#define readdata_addr HOST_v5
+
+
+// instruction encodings
+
+// move
+// mov dst, #imm               @       0 <= imm <= 255
+#define MOV_IMM(dst, imm) (0x2000 + ((dst) << 8) + (imm) )
+// mov dst, src
+#define MOV_REG(dst, src) ADD_IMM3(dst, src, 0)
+// mov dst, src
+#define MOV_LO_HI(dst, src) (0x4640 + (dst) + (((src) - HOST_r8) << 3) )
+// mov dst, src
+#define MOV_HI_LO(dst, src) (0x4680 + ((dst) - HOST_r8) + ((src) << 3) )
+
+// arithmetic
+// add dst, src, #imm          @       0 <= imm <= 7
+#define ADD_IMM3(dst, src, imm) (0x1c00 + (dst) + ((src) << 3) + ((imm) << 6) )
+// add dst, #imm               @       0 <= imm <= 255
+#define ADD_IMM8(dst, imm) (0x3000 + ((dst) << 8) + (imm) )
+// add dst, src1, src2
+#define ADD_REG(dst, src1, src2) (0x1800 + (dst) + ((src1) << 3) + ((src2) << 6) )
+// add dst, pc, #imm           @       0 <= imm < 1024 &       imm mod 4 = 0
+#define ADD_LO_PC_IMM(dst, imm) (0xa000 + ((dst) << 8) + ((imm) >> 2) )
+// sub dst, src1, src2
+#define SUB_REG(dst, src1, src2) (0x1a00 + (dst) + ((src1) << 3) + ((src2) << 6) )
+// sub dst, src, #imm          @       0 <= imm <= 7
+#define SUB_IMM3(dst, src, imm) (0x1e00 + (dst) + ((src) << 3) + ((imm) << 6) )
+// sub dst, #imm               @       0 <= imm <= 255
+#define SUB_IMM8(dst, imm) (0x3800 + ((dst) << 8) + (imm) )
+// neg dst, src
+#define NEG(dst, src) (0x4240 + (dst) + ((src) << 3) )
+// cmp dst, #imm               @       0 <= imm <= 255
+#define CMP_IMM(dst, imm) (0x2800 + ((dst) << 8) + (imm) )
+// nop
+#define NOP (0x46c0)
+
+// logical
+// and dst, src
+#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) )
+// bic dst, src
+#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) )
+// eor dst, src
+#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) )
+// orr dst, src
+#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) )
+// mvn dst, src
+#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) )
+
+// shift/rotate
+// lsl dst, src, #imm
+#define LSL_IMM(dst, src, imm) (0x0000 + (dst) + ((src) << 3) + ((imm) << 6) )
+// lsl dst, reg
+#define LSL_REG(dst, reg) (0x4080 + (dst) + ((reg) << 3) )
+// lsr dst, src, #imm
+#define LSR_IMM(dst, src, imm) (0x0800 + (dst) + ((src) << 3) + ((imm) << 6) )
+// lsr dst, reg
+#define LSR_REG(dst, reg) (0x40c0 + (dst) + ((reg) << 3) )
+// asr dst, src, #imm
+#define ASR_IMM(dst, src, imm) (0x1000 + (dst) + ((src) << 3) + ((imm) << 6) )
+// asr dst, reg
+#define ASR_REG(dst, reg) (0x4100 + (dst) + ((reg) << 3) )
+// ror dst, reg
+#define ROR_REG(dst, reg) (0x41c0 + (dst) + ((reg) << 3) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 128  &       imm mod 4 = 0
+#define LDR_IMM(reg, addr, imm) (0x6800 + (reg) + ((addr) << 3) + ((imm) << 4) )
+// ldrh reg, [addr, #imm]              @       0 <= imm < 64   &       imm mod 2 = 0
+#define LDRH_IMM(reg, addr, imm) (0x8800 + (reg) + ((addr) << 3) + ((imm) << 5) )
+// ldrb reg, [addr, #imm]              @       0 <= imm < 32
+#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) )
+// ldr reg, [pc, #imm]         @       0 <= imm < 1024 &       imm mod 4 = 0
+#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) )
+// ldr reg, [addr1, addr2]
+#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) )
+
+// store
+// str reg, [addr, #imm]               @       0 <= imm < 128  &       imm mod 4 = 0
+#define STR_IMM(reg, addr, imm) (0x6000 + (reg) + ((addr) << 3) + ((imm) << 4) )
+// strh reg, [addr, #imm]              @       0 <= imm < 64   &       imm mod 2 = 0
+#define STRH_IMM(reg, addr, imm) (0x8000 + (reg) + ((addr) << 3) + ((imm) << 5) )
+// strb reg, [addr, #imm]              @       0 <= imm < 32
+#define STRB_IMM(reg, addr, imm) (0x7000 + (reg) + ((addr) << 3) + ((imm) << 6) )
+
+// branch
+// beq pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BEQ_FWD(imm) (0xd000 + ((imm) >> 1) )
+// bne pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BNE_FWD(imm) (0xd100 + ((imm) >> 1) )
+// bgt pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BGT_FWD(imm) (0xdc00 + ((imm) >> 1) )
+// b pc+imm            @       0 <= imm < 2048 &       imm mod 2 = 0
+#define B_FWD(imm) (0xe000 + ((imm) >> 1) )
+// bx reg
+#define BX(reg) (0x4700 + ((reg) << 3) )
+
+
+// arm instructions
+
+// arithmetic
+// add dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 4096
+#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// store
+// str reg, [addr, #-(imm)]!           @       0 <= imm < 4096
+#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// branch
+// bx reg
+#define ARM_BX(reg) (0xe12fff10 + (reg) )
+
+
+// data pool defines
+#define CACHE_DATA_JUMP         (2)
+#define CACHE_DATA_ALIGN (32)
+#define CACHE_DATA_MIN  (32)
+#define CACHE_DATA_MAX  (288)
+
+// data pool variables
+static Bit8u * cache_datapos = NULL;   // position of data pool in the cache block
+static Bit32u cache_datasize = 0;              // total size of data pool
+static Bit32u cache_dataindex = 0;             // used size of data pool = index of free data item (in bytes) in data pool
+
+
+// forwarded function
+static void INLINE gen_create_branch_short(void * func);
+
+// function to check distance to data pool
+// if too close, then generate jump after data pool
+static void cache_checkinstr(Bit32u size) {
+       if (cache_datasize == 0) {
+               if (cache_datapos != NULL) {
+                       if (cache.pos + size + CACHE_DATA_JUMP >= cache_datapos) {
+                               cache_datapos = NULL;
+                       }
+               }
+               return;
+       }
+
+       if (cache.pos + size + CACHE_DATA_JUMP <= cache_datapos) return;
+
+       {
+               register Bit8u * newcachepos;
+
+               newcachepos = cache_datapos + cache_datasize;
+               gen_create_branch_short(newcachepos);
+               cache.pos = newcachepos;
+       }
+
+       if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size &&
+               cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size)
+       {
+               cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1));
+       } else {
+               register Bit32u cachemodsize;
+
+               cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1);
+
+               if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE ||
+                       cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE)
+               {
+                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1));
+               } else {
+                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1));
+               }
+       }
+
+       cache_datasize = 0;
+       cache_dataindex = 0;
+}
+
+// function to reserve item in data pool
+// returns address of item
+static Bit8u * cache_reservedata(void) {
+       // if data pool not yet initialized, then initialize data pool
+       if (GCC_UNLIKELY(cache_datapos == NULL)) {
+               if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN < cache.block.active->cache.start + CACHE_DATA_MAX) {
+                       cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1));
+               }
+       }
+
+       // if data pool not yet used, then set data pool
+       if (cache_datasize == 0) {
+               // set data pool address is too close (or behind)  cache.pos then set new data pool size
+               if (cache.pos + CACHE_DATA_MIN + CACHE_DATA_JUMP /*+ CACHE_DATA_ALIGN*/ > cache_datapos) {
+                       if (cache.pos + CACHE_DATA_MAX + CACHE_DATA_ALIGN >= cache.block.active->cache.start + cache.block.active->cache.size &&
+                               cache.pos + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) < cache.block.active->cache.start + cache.block.active->cache.size)
+                       {
+                               cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1));
+                       } else {
+                               register Bit32u cachemodsize;
+
+                               cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1);
+
+                               if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE ||
+                                       cachemodsize + CACHE_DATA_MIN + CACHE_DATA_ALIGN + (CACHE_DATA_ALIGN - CACHE_ALIGN) > CACHE_MAXSIZE)
+                               {
+                                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + CACHE_DATA_MAX) & ~(CACHE_DATA_ALIGN - 1));
+                               } else {
+                                       cache_datapos = (Bit8u *) (((Bitu)cache.pos + (CACHE_MAXSIZE - CACHE_DATA_ALIGN) - cachemodsize) & ~(CACHE_DATA_ALIGN - 1));
+                               }
+                       }
+               }
+               // set initial data pool size
+               cache_datasize = CACHE_DATA_ALIGN;
+       }
+
+       // if data pool is full, then enlarge data pool
+       if (cache_dataindex == cache_datasize) {
+               cache_datasize += CACHE_DATA_ALIGN;
+       }
+
+       cache_dataindex += 4;
+       return (cache_datapos + (cache_dataindex - 4));
+}
+
+static void cache_block_before_close(void) {
+       // if data pool in use, then resize cache block to include the data pool
+       if (cache_datasize != 0)
+       {
+               cache.pos = cache_datapos + cache_dataindex;
+       }
+
+       // clear the values before next use
+       cache_datapos = NULL;
+       cache_datasize = 0;
+       cache_dataindex = 0;
+}
+
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       if(reg_src == reg_dst) return;
+       cache_checkinstr(2);
+       cache_addw( MOV_REG(reg_dst, reg_src) );      // mov reg_dst, reg_src
+}
+
+// helper function
+static bool val_single_shift(Bit32u value, Bit32u *val_shift) {
+       Bit32u shift;
+
+       if (GCC_UNLIKELY(value == 0)) {
+               *val_shift = 0;
+               return true;
+       }
+
+       shift = 0;
+       while ((value & 1) == 0) {
+               value>>=1;
+               shift+=1;
+       }
+
+       if ((value >> 8) != 0) return false;
+
+       *val_shift = shift;
+       return true;
+}
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+       Bit32u scale;
+
+       if (imm < 256) {
+               cache_checkinstr(2);
+               cache_addw( MOV_IMM(dest_reg, imm) );      // mov dest_reg, #(imm)
+       } else if ((~imm) < 256) {
+               cache_checkinstr(4);
+               cache_addw( MOV_IMM(dest_reg, ~imm) );      // mov dest_reg, #(~imm)
+               cache_addw( MVN(dest_reg, dest_reg) );      // mvn dest_reg, dest_reg
+       } else if (val_single_shift(imm, &scale)) {
+               cache_checkinstr(4);
+               cache_addw( MOV_IMM(dest_reg, imm >> scale) );      // mov dest_reg, #(imm >> scale)
+               cache_addw( LSL_IMM(dest_reg, dest_reg, scale) );      // lsl dest_reg, dest_reg, #scale
+       } else {
+               Bit32u diff;
+
+               cache_checkinstr(4);
+
+               diff = imm - ((Bit32u)cache.pos+4);
+
+               if ((diff < 1024) && ((imm & 0x03) == 0)) {
+                       if (((Bit32u)cache.pos & 0x03) == 0) {
+                               cache_addw( ADD_LO_PC_IMM(dest_reg, diff >> 2) );      // add dest_reg, pc, #(diff >> 2)
+                       } else {
+                               cache_addw( NOP );      // nop
+                               cache_addw( ADD_LO_PC_IMM(dest_reg, (diff - 2) >> 2) );      // add dest_reg, pc, #((diff - 2) >> 2)
+                       }
+               } else {
+                       Bit8u *datapos;
+
+                       datapos = cache_reservedata();
+                       *(Bit32u*)datapos=imm;
+
+                       if (((Bit32u)cache.pos & 0x03) == 0) {
+                               cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 4)) );      // ldr dest_reg, [pc, datapos]
+                       } else {
+                               cache_addw( LDR_PC_IMM(dest_reg, datapos - (cache.pos + 2)) );      // ldr dest_reg, [pc, datapos]
+                       }
+               }
+       }
+}
+
+// helper function
+static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) );      // ldr dest_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) );      // ldrh dest_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 32)) {
+                               cache_checkinstr(4);
+                               cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                               cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) );      // ldrb dest_reg, [templo2, #(data - addr_data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_to_reg
+static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)data & 3) {
+                       if ( ((Bit32u)data & 3) == 2 ) {
+                               cache_checkinstr(8);
+                               cache_addw( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+                               cache_addw( LDRH_IMM(templo1, data_reg, 2) );      // ldrh templo1, [data_reg, #2]
+                               cache_addw( LSL_IMM(templo1, templo1, 16) );      // lsl templo1, templo1, #16
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                       } else {
+                               cache_checkinstr(16);
+                               cache_addw( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                               cache_addw( ADD_IMM3(templo1, data_reg, 1) );      // add templo1, data_reg, #1
+                               cache_addw( LDRH_IMM(templo1, templo1, 0) );      // ldrh templo1, [templo1]
+                               cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                               cache_addw( LDRB_IMM(templo1, data_reg, 3) );      // ldrb templo1, [data_reg, #3]
+                               cache_addw( LSL_IMM(templo1, templo1, 24) );      // lsl templo1, templo1, #24
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                       }
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( LDR_IMM(dest_reg, data_reg, 0) );      // ldr dest_reg, [data_reg]
+               }
+       } else {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)data & 1) {
+                       cache_checkinstr(8);
+                       cache_addw( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                       cache_addw( LDRB_IMM(templo1, data_reg, 1) );      // ldrb templo1, [data_reg, #1]
+                       cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+                       cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+               }
+       }
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
+               gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
+       }
+}
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
+}
+
+// helper function
+static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( STR_IMM(src_reg, templo2, data - addr_data) );      // str src_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
+                                       cache_checkinstr(4);
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) );      // strh src_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 32)) {
+                               cache_checkinstr(4);
+                               cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                               cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) );      // strb src_reg, [templo2, #(data - addr_data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_from_reg
+static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)dest & 3) {
+                       if ( ((Bit32u)dest & 3) == 2 ) {
+                               cache_checkinstr(8);
+                               cache_addw( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 16) );      // lsr templo1, templo1, #16
+                               cache_addw( STRH_IMM(templo1, data_reg, 2) );      // strh templo1, [data_reg, #2]
+                       } else {
+                               cache_checkinstr(20);
+                               cache_addw( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 8) );      // lsr templo1, templo1, #8
+                               cache_addw( STRB_IMM(templo1, data_reg, 1) );      // strb templo1, [data_reg, #1]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 16) );      // lsr templo1, templo1, #16
+                               cache_addw( STRB_IMM(templo1, data_reg, 2) );      // strb templo1, [data_reg, #2]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 24) );      // lsr templo1, templo1, #24
+                               cache_addw( STRB_IMM(templo1, data_reg, 3) );      // strb templo1, [data_reg, #3]
+                       }
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( STR_IMM(src_reg, data_reg, 0) );      // str src_reg, [data_reg]
+               }
+       } else {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)dest & 1) {
+                       cache_checkinstr(8);
+                       cache_addw( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                       cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                       cache_addw( LSR_IMM(templo1, templo1, 8) );      // lsr templo1, templo1, #8
+                       cache_addw( STRB_IMM(templo1, data_reg, 1) );      // strb templo1, [data_reg, #1]
+               } else
+#endif
+               {
+                       cache_checkinstr(2);
+                       cache_addw( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+               }
+       }
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
+               gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
+               cache_checkinstr(2);
+               cache_addw( LDRB_IMM(dest_reg, templo1, 0) );      // ldrb dest_reg, [templo1]
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       gen_mov_byte_to_reg_low(dest_reg, data);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       cache_checkinstr(2);
+       cache_addw( MOV_IMM(dest_reg, imm) );      // mov dest_reg, #(imm)
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       gen_mov_byte_to_reg_low_imm(dest_reg, imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
+               gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
+               cache_checkinstr(2);
+               cache_addw( STRB_IMM(src_reg, templo1, 0) );      // strb src_reg, [templo1]
+       }
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       cache_checkinstr(4);
+       cache_addw( LSL_IMM(reg, reg, 24) );      // lsl reg, reg, #24
+
+       if (sign) {
+               cache_addw( ASR_IMM(reg, reg, 24) );      // asr reg, reg, #24
+       } else {
+               cache_addw( LSR_IMM(reg, reg, 24) );      // lsr reg, reg, #24
+       }
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       cache_checkinstr(4);
+       cache_addw( LSL_IMM(reg, reg, 16) );      // lsl reg, reg, #16
+
+       if (sign) {
+               cache_addw( ASR_IMM(reg, reg, 16) );      // asr reg, reg, #16
+       } else {
+               cache_addw( LSR_IMM(reg, reg, 16) );      // lsr reg, reg, #16
+       }
+}
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       gen_mov_word_to_reg(templo3, op, 1);
+       cache_checkinstr(2);
+       cache_addw( ADD_REG(reg, reg, templo3) );      // add reg, reg, templo3
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       if(!imm) return;
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if (imm <= 255) {
+               cache_checkinstr(2);
+               cache_addw( ADD_IMM8(reg, imm) );      // add reg, #imm
+       } else if (imm2 <= 255) {
+               cache_checkinstr(2);
+               cache_addw( SUB_IMM8(reg, imm2) );      // sub reg, #(-imm)
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_checkinstr((scale)?6:4);
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( SUB_REG(reg, reg, templo1) );      // sub reg, reg, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_checkinstr(2);
+                       cache_addw( ADD_REG(reg, reg, templo1) );      // add reg, reg, templo1
+               }
+       }
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       imm2 = ~imm;
+       if(!imm2) return;
+
+       if (!imm) {
+               cache_checkinstr(2);
+               cache_addw( MOV_IMM(reg, 0) );      // mov reg, #0
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_checkinstr((scale)?6:4);
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( BIC(reg, templo1) );      // bic reg, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_checkinstr(2);
+                       cache_addw( AND(reg, templo1) );      // and reg, templo1
+               }
+       }
+}
+
+
+// move a 32bit constant value into memory
+static void gen_mov_direct_dword(void* dest,Bit32u imm) {
+       gen_mov_dword_to_reg_imm(templo3, imm);
+       gen_mov_word_from_reg(templo3, dest, 1);
+}
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_direct_dword(dest,(Bit32u)imm);
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
+       }
+       gen_add_imm(templo3, imm);
+       if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
+       }
+}
+
+// add an 8bit constant value to a dword memory value
+static void gen_add_direct_byte(void* dest,Bit8s imm) {
+       gen_add_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       Bit32u imm2, scale;
+
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
+       }
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if (imm <= 255) {
+               cache_checkinstr(2);
+               cache_addw( SUB_IMM8(templo3, imm) );      // sub templo3, #imm
+       } else if (imm2 <= 255) {
+               cache_checkinstr(2);
+               cache_addw( ADD_IMM8(templo3, imm2) );      // add templo3, #(-imm)
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_checkinstr((scale)?6:4);
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( ADD_REG(templo3, templo3, templo1) );      // add templo3, templo3, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_checkinstr(2);
+                       cache_addw( SUB_REG(templo3, templo3, templo1) );      // sub templo3, templo3, templo1
+               }
+       }
+
+       if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
+       }
+}
+
+// subtract an 8bit constant value from a dword memory value
+static void gen_sub_direct_byte(void* dest,Bit8s imm) {
+       gen_sub_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_checkinstr(4);
+               cache_addw( LSL_IMM(templo1, scale_reg, scale) );      // lsl templo1, scale_reg, #(scale)
+               cache_addw( ADD_REG(dest_reg, dest_reg, templo1) );      // add dest_reg, dest_reg, templo1
+       } else {
+               cache_checkinstr(2);
+               cache_addw( ADD_REG(dest_reg, dest_reg, scale_reg) );      // add dest_reg, dest_reg, scale_reg
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_checkinstr(2);
+               cache_addw( LSL_IMM(dest_reg, dest_reg, scale) );      // lsl dest_reg, dest_reg, #(scale)
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// helper function for gen_call_function_raw and gen_call_function_setup
+static void gen_call_function_helper(void * func) {
+       Bit8u *datapos;
+
+       datapos = cache_reservedata();
+       *(Bit32u*)datapos=(Bit32u)func;
+
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) );      // ldr templo1, [pc, datapos]
+               cache_addw( ADD_LO_PC_IMM(templo2, 4) );      // adr templo2, after_call (add templo2, pc, #4)
+               cache_addw( MOV_HI_LO(HOST_lr, templo2) );      // mov lr, templo2
+               cache_addw( BX(templo1) );      // bx templo1     --- switch to arm state
+       } else {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) );      // ldr templo1, [pc, datapos]
+               cache_addw( ADD_LO_PC_IMM(templo2, 4) );      // adr templo2, after_call (add templo2, pc, #4)
+               cache_addw( MOV_HI_LO(HOST_lr, templo2) );      // mov lr, templo2
+               cache_addw( BX(templo1) );      // bx templo1     --- switch to arm state
+               cache_addw( NOP );      // nop
+       }
+       // after_call:
+
+       // switch from arm to thumb state
+       cache_addd(0xe2800000 + (templo1 << 12) + (HOST_pc << 16) + (1));      // add templo1, pc, #1
+       cache_addd(0xe12fff10 + (templo1));      // bx templo1
+
+       // thumb state from now on
+}
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+       cache_checkinstr(18);
+       gen_call_function_helper(func);
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       cache_checkinstr(18);
+       Bit32u proc_addr = (Bit32u)cache.pos;
+       gen_call_function_helper(func);
+       return proc_addr;
+       // if proc_addr is on word  boundary ((proc_addr & 0x03) == 0)
+       //   then length of generated code is 16 bytes
+       //   otherwise length of generated code is 18 bytes
+}
+
+#if (1)
+// max of 4 parameters in a1-a4
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, imm);
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, addr);
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       gen_mov_regs(param, reg);
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       gen_mov_word_to_reg(param, (void *)mem, 1);
+}
+#else
+       other arm abis
+#endif
+
+// jump to an address pointed at by ptr, offset is in imm
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       gen_mov_word_to_reg(templo3, ptr, 1);
+
+#if !defined(C_UNALIGNED_MEMORY)
+// (*ptr) should be word aligned
+       if ((imm & 0x03) == 0) {
+#endif
+               if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) {
+                       cache_checkinstr(6);
+                       cache_addw( LDR_IMM(templo2, templo3, imm) );      // ldr templo2, [templo3, #imm]
+               } else {
+                       gen_mov_dword_to_reg_imm(templo2, imm);
+                       cache_checkinstr(6);
+                       cache_addw( LDR_REG(templo2, templo3, templo2) );      // ldr templo2, [templo3, templo2]
+               }
+#if !defined(C_UNALIGNED_MEMORY)
+       } else {
+               gen_add_imm(templo3, imm);
+
+               cache_checkinstr(24);
+               cache_addw( LDRB_IMM(templo2, templo3, 0) );      // ldrb templo2, [templo3]
+               cache_addw( LDRB_IMM(templo1, templo3, 1) );      // ldrb templo1, [templo3, #1]
+               cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+               cache_addw( LDRB_IMM(templo1, templo3, 2) );      // ldrb templo1, [templo3, #2]
+               cache_addw( LSL_IMM(templo1, templo1, 16) );      // lsl templo1, templo1, #16
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+               cache_addw( LDRB_IMM(templo1, templo3, 3) );      // ldrb templo1, [templo3, #3]
+               cache_addw( LSL_IMM(templo1, templo1, 24) );      // lsl templo1, templo1, #24
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+       }
+#endif
+
+       // increase jmp address to keep thumb state
+       cache_addw( ADD_IMM3(templo2, templo2, 1) );      // add templo2, templo2, #1
+
+       cache_addw( BX(templo2) );      // bx templo2
+}
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
+       cache_checkinstr(4);
+       if (dword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo1, reg, 16) );      // lsl templo1, reg, #16
+       }
+       cache_addw( BEQ_FWD(0) );      // beq j
+       return ((Bit32u)cache.pos-2);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       cache_checkinstr(4);
+       if (dword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo1, reg, 16) );      // lsl templo1, reg, #16
+       }
+       cache_addw( BNE_FWD(0) );      // bne j
+       return ((Bit32u)cache.pos-2);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bits len=(Bit32u)cache.pos-(data+4);
+       if (len<0) len=-len;
+       if (len>252) LOG_MSG("Big jump %d",len);
+#endif
+       *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 );
+}
+
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       Bit8u *datapos;
+
+       cache_checkinstr(8);
+       datapos = cache_reservedata();
+
+       if (isdword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo2, reg, 24) );      // lsl templo2, reg, #24
+       }
+       cache_addw( BEQ_FWD(2) );      // beq nobranch (pc+2)
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) );      // ldr templo1, [pc, datapos]
+       } else {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) );      // ldr templo1, [pc, datapos]
+       }
+       cache_addw( BX(templo1) );      // bx templo1
+       // nobranch:
+       return ((Bit32u)datapos);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
+       Bit8u *datapos;
+
+       cache_checkinstr(8);
+       datapos = cache_reservedata();
+
+       cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       cache_addw( BGT_FWD(2) );      // bgt nobranch (pc+2)
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 4)) );      // ldr templo1, [pc, datapos]
+       } else {
+               cache_addw( LDR_PC_IMM(templo1, datapos - (cache.pos + 2)) );      // ldr templo1, [pc, datapos]
+       }
+       cache_addw( BX(templo1) );      // bx templo1
+       // nobranch:
+       return ((Bit32u)datapos);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch_long(Bit32u data) {
+       // this is an absolute branch
+       *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state
+}
+
+static void gen_run_code(void) {
+       Bit8u *pos1, *pos2, *pos3;
+
+#if (__ARM_EABI__)
+       // 8-byte stack alignment
+       cache_addd(0xe92d4ff0);                 // stmfd sp!, {v1-v8,lr}
+#else
+       cache_addd(0xe92d4df0);                 // stmfd sp!, {v1-v5,v7,v8,lr}
+#endif
+
+       cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) );      // add r0, r0, #1
+
+       pos1 = cache.pos;
+       cache_addd( 0 );
+       pos2 = cache.pos;
+       cache_addd( 0 );
+       pos3 = cache.pos;
+       cache_addd( 0 );
+
+       cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) );                      // add lr, pc, #4
+       cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) );      // str lr, [sp, #-4]!
+       cache_addd( ARM_BX(HOST_r0) );                  // bx r0
+
+#if (__ARM_EABI__)
+       cache_addd(0xe8bd4ff0);                 // ldmfd sp!, {v1-v8,lr}
+#else
+       cache_addd(0xe8bd4df0);                 // ldmfd sp!, {v1-v5,v7,v8,lr}
+#endif
+       cache_addd( ARM_BX(HOST_lr) );                  // bx lr
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+
+       *(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8));      // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
+       cache_addd((Bit32u)&Segs);      // address of "Segs"
+
+       *(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8));      // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
+       cache_addd((Bit32u)&cpu_regs);  // address of "cpu_regs"
+
+       *(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8));      // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
+       cache_addd((Bit32u)&core_dynrec.readdata);  // address of "core_dynrec.readdata"
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+}
+
+// return from a function
+static void gen_return_function(void) {
+       cache_checkinstr(4);
+       cache_addw(0xbc08);      // pop {r3}
+       cache_addw( BX(HOST_r3) );      // bx r3
+}
+
+
+// short unconditional jump (over data pool)
+// must emit at most CACHE_DATA_JUMP bytes
+static void INLINE gen_create_branch_short(void * func) {
+       cache_addw( B_FWD((Bit32u)func - ((Bit32u)cache.pos + 4)) );      // b func
+}
+
+
+#ifdef DRC_FLAGS_INVALIDATION
+
+// called when a call to a function can be replaced by a
+// call to a simpler function
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+       if ((*(Bit16u*)pos & 0xf000) == 0xe000) {
+               if ((*(Bit16u*)pos & 0x0fff) >= ((CACHE_DATA_ALIGN / 2) - 1) &&
+                       (*(Bit16u*)pos & 0x0fff) < 0x0800)
+               {
+                       pos = (Bit8u *) ( ( ( (Bit32u)(*(Bit16u*)pos & 0x0fff) ) << 1 ) + ((Bit32u)pos + 4) );
+               }
+       }
+
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       if (((Bit32u)pos & 0x03) == 0)
+       {
+               // try to avoid function calls but rather directly fill in code
+               switch (flags_type) {
+                       case t_ADDb:
+                       case t_ADDw:
+                       case t_ADDd:
+                               *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2);       // add a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_ORb:
+                       case t_ORw:
+                       case t_ORd:
+                               *(Bit16u*)pos=ORR(HOST_a1, HOST_a2);                            // orr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_ANDb:
+                       case t_ANDw:
+                       case t_ANDd:
+                               *(Bit16u*)pos=AND(HOST_a1, HOST_a2);                            // and a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SUBb:
+                       case t_SUBw:
+                       case t_SUBd:
+                               *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2);       // sub a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_XORb:
+                       case t_XORw:
+                       case t_XORd:
+                               *(Bit16u*)pos=EOR(HOST_a1, HOST_a2);                            // eor a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_CMPb:
+                       case t_CMPw:
+                       case t_CMPd:
+                       case t_TESTb:
+                       case t_TESTw:
+                       case t_TESTd:
+                               *(Bit16u*)pos=B_FWD(12);                                                        // b after_call (pc+12)
+                               break;
+                       case t_INCb:
+                       case t_INCw:
+                       case t_INCd:
+                               *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1);            // add a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_DECb:
+                       case t_DECw:
+                       case t_DECd:
+                               *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1);            // sub a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SHLb:
+                       case t_SHLw:
+                       case t_SHLd:
+                               *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2);                        // lsl a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SHRb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24);        // lsr a1, a1, #24
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SHRw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16);        // lsr a1, a1, #16
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SHRd:
+                               *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2);                        // lsr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SARb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24);        // asr a1, a1, #24
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SARw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16);        // asr a1, a1, #16
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_SARd:
+                               *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2);                        // asr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_RORb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1);                       // orr a1, templo1
+                               *(Bit16u*)(pos+14)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_RORw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+8)=B_FWD(4);                                                     // b after_call (pc+4)
+                               break;
+                       case t_RORd:
+                               *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2);                        // ror a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_ROLb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=LSR_IMM(templo1, HOST_a1, 16);       // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1);                       // orr a1, templo1
+                               *(Bit16u*)(pos+14)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_ROLw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+12)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               *(Bit16u*)(pos+14)=NOP;                                                         // nop
+                               break;
+                       case t_ROLd:
+                               *(Bit16u*)pos=NEG(HOST_a2, HOST_a2);                            // neg a2, a2
+                               *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_NEGb:
+                       case t_NEGw:
+                       case t_NEGd:
+                               *(Bit16u*)pos=NEG(HOST_a1, HOST_a1);                            // neg a1, a1
+                               *(Bit16u*)(pos+2)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       default:
+                               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr;         // simple_func
+                               break;
+               }
+       }
+       else
+       {
+               // try to avoid function calls but rather directly fill in code
+               switch (flags_type) {
+                       case t_ADDb:
+                       case t_ADDw:
+                       case t_ADDd:
+                               *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2);       // add a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_ORb:
+                       case t_ORw:
+                       case t_ORd:
+                               *(Bit16u*)pos=ORR(HOST_a1, HOST_a2);                            // orr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_ANDb:
+                       case t_ANDw:
+                       case t_ANDd:
+                               *(Bit16u*)pos=AND(HOST_a1, HOST_a2);                            // and a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SUBb:
+                       case t_SUBw:
+                       case t_SUBd:
+                               *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2);       // sub a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_XORb:
+                       case t_XORw:
+                       case t_XORd:
+                               *(Bit16u*)pos=EOR(HOST_a1, HOST_a2);                            // eor a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_CMPb:
+                       case t_CMPw:
+                       case t_CMPd:
+                       case t_TESTb:
+                       case t_TESTw:
+                       case t_TESTd:
+                               *(Bit16u*)pos=B_FWD(14);                                                        // b after_call (pc+14)
+                               break;
+                       case t_INCb:
+                       case t_INCw:
+                       case t_INCd:
+                               *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1);            // add a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_DECb:
+                       case t_DECw:
+                       case t_DECd:
+                               *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1);            // sub a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SHLb:
+                       case t_SHLw:
+                       case t_SHLd:
+                               *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2);                        // lsl a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SHRb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24);        // lsr a1, a1, #24
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(8);                                                     // b after_call (pc+8)
+                               break;
+                       case t_SHRw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16);        // lsr a1, a1, #16
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(8);                                                     // b after_call (pc+8)
+                               break;
+                       case t_SHRd:
+                               *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2);                        // lsr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SARb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24);        // asr a1, a1, #24
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(8);                                                     // b after_call (pc+8)
+                               break;
+                       case t_SARw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16);        // asr a1, a1, #16
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(8);                                                     // b after_call (pc+8)
+                               break;
+                       case t_SARd:
+                               *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2);                        // asr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_RORb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=NOP;                                                          // nop
+                               *(Bit16u*)(pos+8)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1);                       // orr a1, templo1
+                               *(Bit16u*)(pos+14)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+16)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_RORw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+8)=B_FWD(6);                                                     // b after_call (pc+6)
+                               break;
+                       case t_RORd:
+                               *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2);                        // ror a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_ROLb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=LSR_IMM(templo1, HOST_a1, 16);       // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+12)=ORR(HOST_a1, templo1);                       // orr a1, templo1
+                               *(Bit16u*)(pos+14)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+16)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_ROLw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+12)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               *(Bit16u*)(pos+14)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+16)=NOP;                                                         // nop
+                               break;
+                       case t_ROLd:
+                               *(Bit16u*)pos=NEG(HOST_a2, HOST_a2);                            // neg a2, a2
+                               *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(8);                                                     // b after_call (pc+8)
+                               break;
+                       case t_NEGb:
+                       case t_NEGw:
+                       case t_NEGd:
+                               *(Bit16u*)pos=NEG(HOST_a1, HOST_a1);                            // neg a1, a1
+                               *(Bit16u*)(pos+2)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       default:
+                               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr;         // simple_func
+                               break;
+               }
+
+       }
+#else
+       if (((Bit32u)pos & 0x03) == 0)
+       {
+               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 4) ) = (Bit32u)fct_ptr;         // simple_func
+       }
+       else
+       {
+               *(Bit32u*)( ( ((Bit32u) (*pos)) << 2 ) + ((Bit32u)pos + 2) ) = (Bit32u)fct_ptr;         // simple_func
+       }
+#endif
+}
+#endif
+
+#ifdef DRC_USE_SEGS_ADDR
+
+// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDRH_IMM(dest_reg, templo1, index) );      // ldrh dest_reg, [templo1, #index]
+}
+
+// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDR_IMM(dest_reg, templo1, index) );      // ldr dest_reg, [templo1, #index]
+}
+
+// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
+       cache_checkinstr(6);
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDR_IMM(templo2, templo1, index) );      // ldr templo2, [templo1, #index]
+       cache_addw( ADD_REG(reg, reg, templo2) );      // add reg, reg, templo2
+}
+
+#endif
+
+#ifdef DRC_USE_REGS_ADDR
+
+// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRH_IMM(dest_reg, templo2, index) );      // ldrh dest_reg, [templo2, #index]
+}
+
+// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDR_IMM(dest_reg, templo2, index) );      // ldr dest_reg, [templo2, #index]
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       if (dword) {
+               cache_addw( LDR_IMM(dest_reg, templo2, index) );      // ldr dest_reg, [templo2, #index]
+       } else {
+               cache_addw( LDRH_IMM(dest_reg, templo2, index) );      // ldrh dest_reg, [templo2, #index]
+       }
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRB_IMM(dest_reg, templo2, index) );      // ldrb dest_reg, [templo2, #index]
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRB_IMM(dest_reg, templo2, index) );      // ldrb dest_reg, [templo2, #index]
+}
+
+
+// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
+       cache_checkinstr(6);
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDR_IMM(templo1, templo2, index) );      // ldr templo1, [templo2, #index]
+       cache_addw( ADD_REG(reg, reg, templo1) );      // add reg, reg, templo1
+}
+
+
+// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
+static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STRH_IMM(src_reg, templo1, index) );      // strh src_reg, [templo1, #index]
+}
+
+// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STR_IMM(src_reg, templo1, index) );      // str src_reg, [templo1, #index]
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       if (dword) {
+               cache_addw( STR_IMM(src_reg, templo1, index) );      // str src_reg, [templo1, #index]
+       } else {
+               cache_addw( STRH_IMM(src_reg, templo1, index) );      // strh src_reg, [templo1, #index]
+       }
+}
+
+// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
+static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
+       cache_checkinstr(4);
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STRB_IMM(src_reg, templo1, index) );      // strb src_reg, [templo1, #index]
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le-thumb.h
new file mode 100644 (file)
index 0000000..126cdd1
--- /dev/null
@@ -0,0 +1,1335 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/* ARMv4 (little endian) backend by M-HT (thumb version) */
+
+
+// temporary "lo" registers
+#define templo1 HOST_v3
+#define templo2 HOST_v4
+#define templo3 HOST_v2
+
+// register that holds function return values
+#define FC_RETOP HOST_a1
+
+// register used for address calculations,
+#define FC_ADDR HOST_v1                        // has to be saved across calls, see DRC_PROTECT_ADDR_REG
+
+// register that holds the first parameter
+#define FC_OP1 HOST_a1
+
+// register that holds the second parameter
+#define FC_OP2 HOST_a2
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_a4
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_a1
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_a2
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_a4
+
+// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
+#define FC_REGS_ADDR HOST_v7
+
+// used to hold the address of "Segs" - preferably filled in function gen_run_code
+#define FC_SEGS_ADDR HOST_v8
+
+// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
+#define readdata_addr HOST_v5
+
+
+// instruction encodings
+
+// move
+// mov dst, #imm               @       0 <= imm <= 255
+#define MOV_IMM(dst, imm) (0x2000 + ((dst) << 8) + (imm) )
+// mov dst, src
+#define MOV_REG(dst, src) ADD_IMM3(dst, src, 0)
+// mov dst, src
+#define MOV_LO_HI(dst, src) (0x4640 + (dst) + (((src) - HOST_r8) << 3) )
+// mov dst, src
+#define MOV_HI_LO(dst, src) (0x4680 + ((dst) - HOST_r8) + ((src) << 3) )
+
+// arithmetic
+// add dst, src, #imm          @       0 <= imm <= 7
+#define ADD_IMM3(dst, src, imm) (0x1c00 + (dst) + ((src) << 3) + ((imm) << 6) )
+// add dst, #imm               @       0 <= imm <= 255
+#define ADD_IMM8(dst, imm) (0x3000 + ((dst) << 8) + (imm) )
+// add dst, src1, src2
+#define ADD_REG(dst, src1, src2) (0x1800 + (dst) + ((src1) << 3) + ((src2) << 6) )
+// add dst, pc, #imm           @       0 <= imm < 1024 &       imm mod 4 = 0
+#define ADD_LO_PC_IMM(dst, imm) (0xa000 + ((dst) << 8) + ((imm) >> 2) )
+// sub dst, src1, src2
+#define SUB_REG(dst, src1, src2) (0x1a00 + (dst) + ((src1) << 3) + ((src2) << 6) )
+// sub dst, src, #imm          @       0 <= imm <= 7
+#define SUB_IMM3(dst, src, imm) (0x1e00 + (dst) + ((src) << 3) + ((imm) << 6) )
+// sub dst, #imm               @       0 <= imm <= 255
+#define SUB_IMM8(dst, imm) (0x3800 + ((dst) << 8) + (imm) )
+// neg dst, src
+#define NEG(dst, src) (0x4240 + (dst) + ((src) << 3) )
+// cmp dst, #imm               @       0 <= imm <= 255
+#define CMP_IMM(dst, imm) (0x2800 + ((dst) << 8) + (imm) )
+// nop
+#define NOP (0x46c0)
+
+// logical
+// and dst, src
+#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) )
+// bic dst, src
+#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) )
+// eor dst, src
+#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) )
+// orr dst, src
+#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) )
+// mvn dst, src
+#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) )
+
+// shift/rotate
+// lsl dst, src, #imm
+#define LSL_IMM(dst, src, imm) (0x0000 + (dst) + ((src) << 3) + ((imm) << 6) )
+// lsl dst, reg
+#define LSL_REG(dst, reg) (0x4080 + (dst) + ((reg) << 3) )
+// lsr dst, src, #imm
+#define LSR_IMM(dst, src, imm) (0x0800 + (dst) + ((src) << 3) + ((imm) << 6) )
+// lsr dst, reg
+#define LSR_REG(dst, reg) (0x40c0 + (dst) + ((reg) << 3) )
+// asr dst, src, #imm
+#define ASR_IMM(dst, src, imm) (0x1000 + (dst) + ((src) << 3) + ((imm) << 6) )
+// asr dst, reg
+#define ASR_REG(dst, reg) (0x4100 + (dst) + ((reg) << 3) )
+// ror dst, reg
+#define ROR_REG(dst, reg) (0x41c0 + (dst) + ((reg) << 3) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 128  &       imm mod 4 = 0
+#define LDR_IMM(reg, addr, imm) (0x6800 + (reg) + ((addr) << 3) + ((imm) << 4) )
+// ldrh reg, [addr, #imm]              @       0 <= imm < 64   &       imm mod 2 = 0
+#define LDRH_IMM(reg, addr, imm) (0x8800 + (reg) + ((addr) << 3) + ((imm) << 5) )
+// ldrb reg, [addr, #imm]              @       0 <= imm < 32
+#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) )
+// ldr reg, [pc, #imm]         @       0 <= imm < 1024 &       imm mod 4 = 0
+#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) )
+// ldr reg, [addr1, addr2]
+#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) )
+
+// store
+// str reg, [addr, #imm]               @       0 <= imm < 128  &       imm mod 4 = 0
+#define STR_IMM(reg, addr, imm) (0x6000 + (reg) + ((addr) << 3) + ((imm) << 4) )
+// strh reg, [addr, #imm]              @       0 <= imm < 64   &       imm mod 2 = 0
+#define STRH_IMM(reg, addr, imm) (0x8000 + (reg) + ((addr) << 3) + ((imm) << 5) )
+// strb reg, [addr, #imm]              @       0 <= imm < 32
+#define STRB_IMM(reg, addr, imm) (0x7000 + (reg) + ((addr) << 3) + ((imm) << 6) )
+
+// branch
+// beq pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BEQ_FWD(imm) (0xd000 + ((imm) >> 1) )
+// bne pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BNE_FWD(imm) (0xd100 + ((imm) >> 1) )
+// bgt pc+imm          @       0 <= imm < 256  &       imm mod 2 = 0
+#define BGT_FWD(imm) (0xdc00 + ((imm) >> 1) )
+// b pc+imm            @       0 <= imm < 2048 &       imm mod 2 = 0
+#define B_FWD(imm) (0xe000 + ((imm) >> 1) )
+// bx reg
+#define BX(reg) (0x4700 + ((reg) << 3) )
+
+
+// arm instructions
+
+// arithmetic
+// add dst, src, #(imm ror rimm)               @       0 <= imm <= 255 &       rimm mod 2 = 0
+#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
+
+// load
+// ldr reg, [addr, #imm]               @       0 <= imm < 4096
+#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// store
+// str reg, [addr, #-(imm)]!           @       0 <= imm < 4096
+#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) )
+
+// branch
+// bx reg
+#define ARM_BX(reg) (0xe12fff10 + (reg) )
+
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       if(reg_src == reg_dst) return;
+       cache_addw( MOV_REG(reg_dst, reg_src) );      // mov reg_dst, reg_src
+}
+
+// helper function
+static bool val_single_shift(Bit32u value, Bit32u *val_shift) {
+       Bit32u shift;
+
+       if (GCC_UNLIKELY(value == 0)) {
+               *val_shift = 0;
+               return true;
+       }
+
+       shift = 0;
+       while ((value & 1) == 0) {
+               value>>=1;
+               shift+=1;
+       }
+
+       if ((value >> 8) != 0) return false;
+
+       *val_shift = shift;
+       return true;
+}
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+       Bit32u scale;
+
+       if (imm < 256) {
+               cache_addw( MOV_IMM(dest_reg, imm) );      // mov dest_reg, #imm
+       } else if ((~imm) < 256) {
+               cache_addw( MOV_IMM(dest_reg, ~imm) );      // mov dest_reg, #(~imm)
+               cache_addw( MVN(dest_reg, dest_reg) );      // mvn dest_reg, dest_reg
+       } else if (val_single_shift(imm, &scale)) {
+               cache_addw( MOV_IMM(dest_reg, imm >> scale) );      // mov dest_reg, #(imm >> scale)
+               cache_addw( LSL_IMM(dest_reg, dest_reg, scale) );      // lsl dest_reg, dest_reg, #scale
+       } else {
+               Bit32u diff;
+
+               diff = imm - ((Bit32u)cache.pos+4);
+
+               if ((diff < 1024) && ((imm & 0x03) == 0)) {
+                       if (((Bit32u)cache.pos & 0x03) == 0) {
+                               cache_addw( ADD_LO_PC_IMM(dest_reg, diff) );      // add dest_reg, pc, #(diff >> 2)
+                       } else {
+                               cache_addw( NOP );      // nop
+                               cache_addw( ADD_LO_PC_IMM(dest_reg, diff - 2) );      // add dest_reg, pc, #((diff - 2) >> 2)
+                       }
+               } else {
+                       if (((Bit32u)cache.pos & 0x03) == 0) {
+                               cache_addw( LDR_PC_IMM(dest_reg, 0) );      // ldr dest_reg, [pc, #0]
+                               cache_addw( B_FWD(2) );      // b next_code (pc+2)
+                               cache_addd(imm);      // .int imm
+                               // next_code:
+                       } else {
+                               cache_addw( LDR_PC_IMM(dest_reg, 4) );      // ldr dest_reg, [pc, #4]
+                               cache_addw( B_FWD(4) );      // b next_code (pc+4)
+                               cache_addw( NOP );      // nop
+                               cache_addd(imm);      // .int imm
+                               // next_code:
+                       }
+               }
+       }
+}
+
+// helper function
+static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) );      // ldr dest_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) );      // ldrh dest_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 32)) {
+                               cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                               cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) );      // ldrb dest_reg, [templo2, #(data - addr_data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_to_reg
+static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)data & 3) {
+                       if ( ((Bit32u)data & 3) == 2 ) {
+                               cache_addw( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+                               cache_addw( LDRH_IMM(templo1, data_reg, 2) );      // ldrh templo1, [data_reg, #2]
+                               cache_addw( LSL_IMM(templo1, templo1, 16) );      // lsl templo1, templo1, #16
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                       } else {
+                               cache_addw( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                               cache_addw( ADD_IMM3(templo1, data_reg, 1) );      // add templo1, data_reg, #1
+                               cache_addw( LDRH_IMM(templo1, templo1, 0) );      // ldrh templo1, [templo1]
+                               cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                               cache_addw( LDRB_IMM(templo1, data_reg, 3) );      // ldrb templo1, [data_reg, #3]
+                               cache_addw( LSL_IMM(templo1, templo1, 24) );      // lsl templo1, templo1, #24
+                               cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+                       }
+               } else
+#endif
+               {
+                       cache_addw( LDR_IMM(dest_reg, data_reg, 0) );      // ldr dest_reg, [data_reg]
+               }
+       } else {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)data & 1) {
+                       cache_addw( LDRB_IMM(dest_reg, data_reg, 0) );      // ldrb dest_reg, [data_reg]
+                       cache_addw( LDRB_IMM(templo1, data_reg, 1) );      // ldrb templo1, [data_reg, #1]
+                       cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+                       cache_addw( ORR(dest_reg, templo1) );      // orr dest_reg, templo1
+               } else
+#endif
+               {
+                       cache_addw( LDRH_IMM(dest_reg, data_reg, 0) );      // ldrh dest_reg, [data_reg]
+               }
+       }
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
+               gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
+       }
+}
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
+}
+
+// helper function
+static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
+       switch (size) {
+               case 4:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 3) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( STR_IMM(src_reg, templo2, data - addr_data) );      // str src_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 2:
+#if !defined(C_UNALIGNED_MEMORY)
+                       if ((data & 1) == 0)
+#endif
+                       {
+                               if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
+                                       cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                                       cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) );      // strh src_reg, [templo2, #(data - addr_data)]
+                                       return true;
+                               }
+                       }
+                       break;
+               case 1:
+                       if ((data >= addr_data) && (data < addr_data + 32)) {
+                               cache_addw( MOV_LO_HI(templo2, addr_reg) );      // mov templo2, addr_reg
+                               cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) );      // strb src_reg, [templo2, #(data - addr_data)]
+                               return true;
+                       }
+               default:
+                       break;
+       }
+       return false;
+}
+
+// helper function
+static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
+       if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
+       return false;
+}
+
+// helper function for gen_mov_word_from_reg
+static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
+       // alignment....
+       if (dword) {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)dest & 3) {
+                       if ( ((Bit32u)dest & 3) == 2 ) {
+                               cache_addw( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 16) );      // lsr templo1, templo1, #16
+                               cache_addw( STRH_IMM(templo1, data_reg, 2) );      // strh templo1, [data_reg, #2]
+                       } else {
+                               cache_addw( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 8) );      // lsr templo1, templo1, #8
+                               cache_addw( STRB_IMM(templo1, data_reg, 1) );      // strb templo1, [data_reg, #1]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 16) );      // lsr templo1, templo1, #16
+                               cache_addw( STRB_IMM(templo1, data_reg, 2) );      // strb templo1, [data_reg, #2]
+                               cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                               cache_addw( LSR_IMM(templo1, templo1, 24) );      // lsr templo1, templo1, #24
+                               cache_addw( STRB_IMM(templo1, data_reg, 3) );      // strb templo1, [data_reg, #3]
+                       }
+               } else
+#endif
+               {
+                       cache_addw( STR_IMM(src_reg, data_reg, 0) );      // str src_reg, [data_reg]
+               }
+       } else {
+#if !defined(C_UNALIGNED_MEMORY)
+               if ((Bit32u)dest & 1) {
+                       cache_addw( STRB_IMM(src_reg, data_reg, 0) );      // strb src_reg, [data_reg]
+                       cache_addw( MOV_REG(templo1, src_reg) );      // mov templo1, src_reg
+                       cache_addw( LSR_IMM(templo1, templo1, 8) );      // lsr templo1, templo1, #8
+                       cache_addw( STRB_IMM(templo1, data_reg, 1) );      // strb templo1, [data_reg, #1]
+               } else
+#endif
+               {
+                       cache_addw( STRH_IMM(src_reg, data_reg, 0) );      // strh src_reg, [data_reg]
+               }
+       }
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
+               gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
+               cache_addw( LDRB_IMM(dest_reg, templo1, 0) );      // ldrb dest_reg, [templo1]
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       gen_mov_byte_to_reg_low(dest_reg, data);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       cache_addw( MOV_IMM(dest_reg, imm) );      // mov dest_reg, #(imm)
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       gen_mov_byte_to_reg_low_imm(dest_reg, imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
+               gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
+               cache_addw( STRB_IMM(src_reg, templo1, 0) );      // strb src_reg, [templo1]
+       }
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       cache_addw( LSL_IMM(reg, reg, 24) );      // lsl reg, reg, #24
+
+       if (sign) {
+               cache_addw( ASR_IMM(reg, reg, 24) );      // asr reg, reg, #24
+       } else {
+               cache_addw( LSR_IMM(reg, reg, 24) );      // lsr reg, reg, #24
+       }
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       cache_addw( LSL_IMM(reg, reg, 16) );      // lsl reg, reg, #16
+
+       if (sign) {
+               cache_addw( ASR_IMM(reg, reg, 16) );      // asr reg, reg, #16
+       } else {
+               cache_addw( LSR_IMM(reg, reg, 16) );      // lsr reg, reg, #16
+       }
+}
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       gen_mov_word_to_reg(templo3, op, 1);
+       cache_addw( ADD_REG(reg, reg, templo3) );      // add reg, reg, templo3
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       if(!imm) return;
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if (imm <= 255) {
+               cache_addw( ADD_IMM8(reg, imm) );      // add reg, #imm
+       } else if (imm2 <= 255) {
+               cache_addw( SUB_IMM8(reg, imm2) );      // sub reg, #(-imm)
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( SUB_REG(reg, reg, templo1) );      // sub reg, reg, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_addw( ADD_REG(reg, reg, templo1) );      // add reg, reg, templo1
+               }
+       }
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       Bit32u imm2, scale;
+
+       imm2 = ~imm;
+       if(!imm2) return;
+
+       if (!imm) {
+               cache_addw( MOV_IMM(reg, 0) );      // mov reg, #0
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( BIC(reg, templo1) );      // bic reg, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_addw( AND(reg, templo1) );      // and reg, templo1
+               }
+       }
+}
+
+
+// move a 32bit constant value into memory
+static void gen_mov_direct_dword(void* dest,Bit32u imm) {
+       gen_mov_dword_to_reg_imm(templo3, imm);
+       gen_mov_word_from_reg(templo3, dest, 1);
+}
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_direct_dword(dest,(Bit32u)imm);
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
+       }
+       gen_add_imm(templo3, imm);
+       if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
+       }
+}
+
+// add an 8bit constant value to a dword memory value
+static void gen_add_direct_byte(void* dest,Bit8s imm) {
+       gen_add_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       Bit32u imm2, scale;
+
+       if (!dword) imm &= 0xffff;
+       if(!imm) return;
+
+       if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
+               gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
+       }
+
+       imm2 = (Bit32u) (-((Bit32s)imm));
+
+       if (imm <= 255) {
+               cache_addw( SUB_IMM8(templo3, imm) );      // sub templo3, #imm
+       } else if (imm2 <= 255) {
+               cache_addw( ADD_IMM8(templo3, imm2) );      // add templo3, #(-imm)
+       } else {
+               if (val_single_shift(imm2, &scale)) {
+                       cache_addw( MOV_IMM(templo1, imm2 >> scale) );      // mov templo1, #(~imm >> scale)
+                       if (scale) {
+                               cache_addw( LSL_IMM(templo1, templo1, scale) );      // lsl templo1, templo1, #scale
+                       }
+                       cache_addw( ADD_REG(templo3, templo3, templo1) );      // add templo3, templo3, templo1
+               } else {
+                       gen_mov_dword_to_reg_imm(templo1, imm);
+                       cache_addw( SUB_REG(templo3, templo3, templo1) );      // sub templo3, templo3, templo1
+               }
+       }
+
+       if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
+               gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
+       }
+}
+
+// subtract an 8bit constant value from a dword memory value
+static void gen_sub_direct_byte(void* dest,Bit8s imm) {
+       gen_sub_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_addw( LSL_IMM(templo1, scale_reg, scale) );      // lsl templo1, scale_reg, #(scale)
+               cache_addw( ADD_REG(dest_reg, dest_reg, templo1) );      // add dest_reg, dest_reg, templo1
+       } else {
+               cache_addw( ADD_REG(dest_reg, dest_reg, scale_reg) );      // add dest_reg, dest_reg, scale_reg
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_addw( LSL_IMM(dest_reg, dest_reg, scale) );      // lsl dest_reg, dest_reg, #(scale)
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( LDR_PC_IMM(templo1, 4) );      // ldr templo1, [pc, #4]
+               cache_addw( ADD_LO_PC_IMM(templo2, 8) );      // adr templo2, after_call (add templo2, pc, #8)
+               cache_addw( MOV_HI_LO(HOST_lr, templo2) );      // mov lr, templo2
+               cache_addw( BX(templo1) );      // bx templo1     --- switch to arm state
+       } else {
+               cache_addw( LDR_PC_IMM(templo1, 8) );      // ldr templo1, [pc, #8]
+               cache_addw( ADD_LO_PC_IMM(templo2, 8) );      // adr templo2, after_call (add templo2, pc, #8)
+               cache_addw( MOV_HI_LO(HOST_lr, templo2) );      // mov lr, templo2
+               cache_addw( BX(templo1) );      // bx templo1     --- switch to arm state
+               cache_addw( NOP );      // nop
+       }
+       cache_addd((Bit32u)func);      // .int func
+       // after_call:
+
+       // switch from arm to thumb state
+       cache_addd(0xe2800000 + (templo1 << 12) + (HOST_pc << 16) + (1));      // add templo1, pc, #1
+       cache_addd(0xe12fff10 + (templo1));      // bx templo1
+
+       // thumb state from now on
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       Bit32u proc_addr = (Bit32u)cache.pos;
+       gen_call_function_raw(func);
+       return proc_addr;
+       // if proc_addr is on word  boundary ((proc_addr & 0x03) == 0)
+       //   then length of generated code is 20 bytes
+       //   otherwise length of generated code is 22 bytes
+}
+
+#if (1)
+// max of 4 parameters in a1-a4
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, imm);
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
+       gen_mov_dword_to_reg_imm(param, addr);
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       gen_mov_regs(param, reg);
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       gen_mov_word_to_reg(param, (void *)mem, 1);
+}
+#else
+       other arm abis
+#endif
+
+// jump to an address pointed at by ptr, offset is in imm
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       gen_mov_word_to_reg(templo3, ptr, 1);
+
+#if !defined(C_UNALIGNED_MEMORY)
+// (*ptr) should be word aligned
+       if ((imm & 0x03) == 0) {
+#endif
+               if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) {
+                       cache_addw( LDR_IMM(templo2, templo3, imm) );      // ldr templo2, [templo3, #imm]
+               } else {
+                       gen_mov_dword_to_reg_imm(templo2, imm);
+                       cache_addw( LDR_REG(templo2, templo3, templo2) );      // ldr templo2, [templo3, templo2]
+               }
+#if !defined(C_UNALIGNED_MEMORY)
+       } else {
+               gen_add_imm(templo3, imm);
+
+               cache_addw( LDRB_IMM(templo2, templo3, 0) );      // ldrb templo2, [templo3]
+               cache_addw( LDRB_IMM(templo1, templo3, 1) );      // ldrb templo1, [templo3, #1]
+               cache_addw( LSL_IMM(templo1, templo1, 8) );      // lsl templo1, templo1, #8
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+               cache_addw( LDRB_IMM(templo1, templo3, 2) );      // ldrb templo1, [templo3, #2]
+               cache_addw( LSL_IMM(templo1, templo1, 16) );      // lsl templo1, templo1, #16
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+               cache_addw( LDRB_IMM(templo1, templo3, 3) );      // ldrb templo1, [templo3, #3]
+               cache_addw( LSL_IMM(templo1, templo1, 24) );      // lsl templo1, templo1, #24
+               cache_addw( ORR(templo2, templo1) );      // orr templo2, templo1
+       }
+#endif
+
+       // increase jmp address to keep thumb state
+       cache_addw( ADD_IMM3(templo2, templo2, 1) );      // add templo2, templo2, #1
+
+       cache_addw( BX(templo2) );      // bx templo2
+}
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
+       if (dword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo1, reg, 16) );      // lsl templo1, reg, #16
+       }
+       cache_addw( BEQ_FWD(0) );      // beq j
+       return ((Bit32u)cache.pos-2);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       if (dword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo1, reg, 16) );      // lsl templo1, reg, #16
+       }
+       cache_addw( BNE_FWD(0) );      // bne j
+       return ((Bit32u)cache.pos-2);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bits len=(Bit32u)cache.pos-(data+4);
+       if (len<0) len=-len;
+       if (len>252) LOG_MSG("Big jump %d",len);
+#endif
+       *(Bit8u*)data=(Bit8u)( ((Bit32u)cache.pos-(data+4)) >> 1 );
+}
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       if (isdword) {
+               cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       } else {
+               cache_addw( LSL_IMM(templo2, reg, 24) );      // lsl templo2, reg, #24
+       }
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( BEQ_FWD(8) );      // beq nobranch (pc+8)
+               cache_addw( LDR_PC_IMM(templo1, 4) );      // ldr templo1, [pc, #4]
+               cache_addw( BX(templo1) );      // bx templo1
+               cache_addw( NOP );      // nop
+       } else {
+               cache_addw( BEQ_FWD(6) );      // beq nobranch (pc+6)
+               cache_addw( LDR_PC_IMM(templo1, 0) );      // ldr templo1, [pc, #0]
+               cache_addw( BX(templo1) );      // bx templo1
+       }
+       cache_addd(0);      // fill j
+       // nobranch:
+       return ((Bit32u)cache.pos-4);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
+       cache_addw( CMP_IMM(reg, 0) );      // cmp reg, #0
+       if (((Bit32u)cache.pos & 0x03) == 0) {
+               cache_addw( BGT_FWD(8) );      // bgt nobranch (pc+8)
+               cache_addw( LDR_PC_IMM(templo1, 4) );      // ldr templo1, [pc, #4]
+               cache_addw( BX(templo1) );      // bx templo1
+               cache_addw( NOP );      // nop
+       } else {
+               cache_addw( BGT_FWD(6) );      // bgt nobranch (pc+6)
+               cache_addw( LDR_PC_IMM(templo1, 0) );      // ldr templo1, [pc, #0]
+               cache_addw( BX(templo1) );      // bx templo1
+       }
+       cache_addd(0);      // fill j
+       // nobranch:
+       return ((Bit32u)cache.pos-4);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch_long(Bit32u data) {
+       // this is an absolute branch
+       *(Bit32u*)data=((Bit32u)cache.pos) + 1; // add 1 to keep processor in thumb state
+}
+
+static void gen_run_code(void) {
+       Bit8u *pos1, *pos2, *pos3;
+
+#if (__ARM_EABI__)
+       // 8-byte stack alignment
+       cache_addd(0xe92d4ff0);                 // stmfd sp!, {v1-v8,lr}
+#else
+       cache_addd(0xe92d4df0);                 // stmfd sp!, {v1-v5,v7,v8,lr}
+#endif
+
+       cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) );      // add r0, r0, #1
+
+       pos1 = cache.pos;
+       cache_addd( 0 );
+       pos2 = cache.pos;
+       cache_addd( 0 );
+       pos3 = cache.pos;
+       cache_addd( 0 );
+
+       cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) );                      // add lr, pc, #4
+       cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) );      // str lr, [sp, #-4]!
+       cache_addd( ARM_BX(HOST_r0) );                  // bx r0
+
+#if (__ARM_EABI__)
+       cache_addd(0xe8bd4ff0);                 // ldmfd sp!, {v1-v8,lr}
+#else
+       cache_addd(0xe8bd4df0);                 // ldmfd sp!, {v1-v5,v7,v8,lr}
+#endif
+       cache_addd( ARM_BX(HOST_lr) );                  // bx lr
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+
+       *(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8));      // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
+       cache_addd((Bit32u)&Segs);      // address of "Segs"
+
+       *(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8));      // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
+       cache_addd((Bit32u)&cpu_regs);  // address of "cpu_regs"
+
+       *(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8));      // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
+       cache_addd((Bit32u)&core_dynrec.readdata);  // address of "core_dynrec.readdata"
+
+       // align cache.pos to 32 bytes
+       if ((((Bitu)cache.pos) & 0x1f) != 0) {
+               cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
+       }
+}
+
+// return from a function
+static void gen_return_function(void) {
+       cache_addw(0xbc08);      // pop {r3}
+       cache_addw( BX(HOST_r3) );      // bx r3
+}
+
+#ifdef DRC_FLAGS_INVALIDATION
+
+// called when a call to a function can be replaced by a
+// call to a simpler function
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       if (((Bit32u)pos & 0x03) == 0)
+       {
+               // try to avoid function calls but rather directly fill in code
+               switch (flags_type) {
+                       case t_ADDb:
+                       case t_ADDw:
+                       case t_ADDd:
+                               *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2);       // add a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_ORb:
+                       case t_ORw:
+                       case t_ORd:
+                               *(Bit16u*)pos=ORR(HOST_a1, HOST_a2);                            // orr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_ANDb:
+                       case t_ANDw:
+                       case t_ANDd:
+                               *(Bit16u*)pos=AND(HOST_a1, HOST_a2);                            // and a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_SUBb:
+                       case t_SUBw:
+                       case t_SUBd:
+                               *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2);       // sub a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_XORb:
+                       case t_XORw:
+                       case t_XORd:
+                               *(Bit16u*)pos=EOR(HOST_a1, HOST_a2);                            // eor a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_CMPb:
+                       case t_CMPw:
+                       case t_CMPd:
+                       case t_TESTb:
+                       case t_TESTw:
+                       case t_TESTd:
+                               *(Bit16u*)pos=B_FWD(16);                                                        // b after_call (pc+16)
+                               break;
+                       case t_INCb:
+                       case t_INCw:
+                       case t_INCd:
+                               *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1);            // add a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_DECb:
+                       case t_DECw:
+                       case t_DECd:
+                               *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1);            // sub a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_SHLb:
+                       case t_SHLw:
+                       case t_SHLd:
+                               *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2);                        // lsl a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_SHRb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24);        // lsr a1, a1, #24
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SHRw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16);        // lsr a1, a1, #16
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SHRd:
+                               *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2);                        // lsr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_SARb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24);        // asr a1, a1, #24
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SARw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16);        // asr a1, a1, #16
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_SARd:
+                               *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2);                        // asr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_RORb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               *(Bit16u*)(pos+12)=B_FWD(4);                                            // b after_call (pc+4)
+                               break;
+                       case t_RORw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+8)=B_FWD(8);                                                     // b after_call (pc+8)
+                               break;
+                       case t_RORd:
+                               *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2);                        // ror a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       case t_ROLb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+12)=LSR_IMM(templo1, HOST_a1, 16);       // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+14)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+16)=ORR(HOST_a1, templo1);                       // orr a1, templo1
+                               *(Bit16u*)(pos+18)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_ROLw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               *(Bit16u*)(pos+12)=B_FWD(4);                                            // b after_call (pc+4)
+                               break;
+                       case t_ROLd:
+                               *(Bit16u*)pos=NEG(HOST_a2, HOST_a2);                            // neg a2, a2
+                               *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_NEGb:
+                       case t_NEGw:
+                       case t_NEGd:
+                               *(Bit16u*)pos=NEG(HOST_a1, HOST_a1);                            // neg a1, a1
+                               *(Bit16u*)(pos+2)=B_FWD(14);                                            // b after_call (pc+14)
+                               break;
+                       default:
+                               *(Bit32u*)(pos+8)=(Bit32u)fct_ptr;              // simple_func
+                               break;
+               }
+       }
+       else
+       {
+               // try to avoid function calls but rather directly fill in code
+               switch (flags_type) {
+                       case t_ADDb:
+                       case t_ADDw:
+                       case t_ADDd:
+                               *(Bit16u*)pos=ADD_REG(HOST_a1, HOST_a1, HOST_a2);       // add a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_ORb:
+                       case t_ORw:
+                       case t_ORd:
+                               *(Bit16u*)pos=ORR(HOST_a1, HOST_a2);                            // orr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_ANDb:
+                       case t_ANDw:
+                       case t_ANDd:
+                               *(Bit16u*)pos=AND(HOST_a1, HOST_a2);                            // and a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_SUBb:
+                       case t_SUBw:
+                       case t_SUBd:
+                               *(Bit16u*)pos=SUB_REG(HOST_a1, HOST_a1, HOST_a2);       // sub a1, a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_XORb:
+                       case t_XORw:
+                       case t_XORd:
+                               *(Bit16u*)pos=EOR(HOST_a1, HOST_a2);                            // eor a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_CMPb:
+                       case t_CMPw:
+                       case t_CMPd:
+                       case t_TESTb:
+                       case t_TESTw:
+                       case t_TESTd:
+                               *(Bit16u*)pos=B_FWD(18);                                                        // b after_call (pc+18)
+                               break;
+                       case t_INCb:
+                       case t_INCw:
+                       case t_INCd:
+                               *(Bit16u*)pos=ADD_IMM3(HOST_a1, HOST_a1, 1);            // add a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_DECb:
+                       case t_DECw:
+                       case t_DECd:
+                               *(Bit16u*)pos=SUB_IMM3(HOST_a1, HOST_a1, 1);            // sub a1, a1, #1
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_SHLb:
+                       case t_SHLw:
+                       case t_SHLd:
+                               *(Bit16u*)pos=LSL_REG(HOST_a1, HOST_a2);                        // lsl a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_SHRb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 24);        // lsr a1, a1, #24
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SHRw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(HOST_a1, HOST_a1, 16);        // lsr a1, a1, #16
+                               *(Bit16u*)(pos+4)=LSR_REG(HOST_a1, HOST_a2);            // lsr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SHRd:
+                               *(Bit16u*)pos=LSR_REG(HOST_a1, HOST_a2);                        // lsr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_SARb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 24);        // asr a1, a1, #24
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SARw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=ASR_IMM(HOST_a1, HOST_a1, 16);        // asr a1, a1, #16
+                               *(Bit16u*)(pos+4)=ASR_REG(HOST_a1, HOST_a2);            // asr a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_SARd:
+                               *(Bit16u*)pos=ASR_REG(HOST_a1, HOST_a2);                        // asr a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_RORb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               *(Bit16u*)(pos+12)=B_FWD(6);                                            // b after_call (pc+6)
+                               break;
+                       case t_RORw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+4)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+6)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+8)=B_FWD(10);                                            // b after_call (pc+10)
+                               break;
+                       case t_RORd:
+                               *(Bit16u*)pos=ROR_REG(HOST_a1, HOST_a2);                        // ror a1, a2
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       case t_ROLb:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 24);            // lsl a1, a1, #24
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 8);         // lsr templo1, a1, #8
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+12)=LSR_IMM(templo1, HOST_a1, 16);       // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+14)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+16)=ORR(HOST_a1, templo1);                       // orr a1, templo1
+                               *(Bit16u*)(pos+18)=NOP;                                                         // nop
+                               *(Bit16u*)(pos+20)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               break;
+                       case t_ROLw:
+                               *(Bit16u*)pos=LSL_IMM(HOST_a1, HOST_a1, 16);            // lsl a1, a1, #16
+                               *(Bit16u*)(pos+2)=NEG(HOST_a2, HOST_a2);                        // neg a2, a2
+                               *(Bit16u*)(pos+4)=LSR_IMM(templo1, HOST_a1, 16);        // lsr templo1, a1, #16
+                               *(Bit16u*)(pos+6)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+8)=ORR(HOST_a1, templo1);                        // orr a1, templo1
+                               *(Bit16u*)(pos+10)=ROR_REG(HOST_a1, HOST_a2);           // ror a1, a2
+                               *(Bit16u*)(pos+12)=B_FWD(6);                                            // b after_call (pc+6)
+                               break;
+                       case t_ROLd:
+                               *(Bit16u*)pos=NEG(HOST_a2, HOST_a2);                            // neg a2, a2
+                               *(Bit16u*)(pos+2)=ADD_IMM8(HOST_a2, 32);                        // add a2, #32
+                               *(Bit16u*)(pos+4)=ROR_REG(HOST_a1, HOST_a2);            // ror a1, a2
+                               *(Bit16u*)(pos+6)=B_FWD(12);                                            // b after_call (pc+12)
+                               break;
+                       case t_NEGb:
+                       case t_NEGw:
+                       case t_NEGd:
+                               *(Bit16u*)pos=NEG(HOST_a1, HOST_a1);                            // neg a1, a1
+                               *(Bit16u*)(pos+2)=B_FWD(16);                                            // b after_call (pc+16)
+                               break;
+                       default:
+                               *(Bit32u*)(pos+10)=(Bit32u)fct_ptr;             // simple_func
+                               break;
+               }
+
+       }
+#else
+       if (((Bit32u)pos & 0x03) == 0)
+       {
+               *(Bit32u*)(pos+8)=(Bit32u)fct_ptr;              // simple_func
+       }
+       else
+       {
+               *(Bit32u*)(pos+10)=(Bit32u)fct_ptr;             // simple_func
+       }
+#endif
+}
+#endif
+
+static void cache_block_before_close(void) {
+       if ((((Bit32u)cache.pos) & 3) != 0) {
+               cache_addw( NOP );      // nop
+       }
+}
+
+#ifdef DRC_USE_SEGS_ADDR
+
+// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDRH_IMM(dest_reg, templo1, index) );      // ldrh dest_reg, [templo1, #index]
+}
+
+// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDR_IMM(dest_reg, templo1, index) );      // ldr dest_reg, [templo1, #index]
+}
+
+// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo1, FC_SEGS_ADDR) );      // mov templo1, FC_SEGS_ADDR
+       cache_addw( LDR_IMM(templo2, templo1, index) );      // ldr templo2, [templo1, #index]
+       cache_addw( ADD_REG(reg, reg, templo2) );      // add reg, reg, templo2
+}
+
+#endif
+
+#ifdef DRC_USE_REGS_ADDR
+
+// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRH_IMM(dest_reg, templo2, index) );      // ldrh dest_reg, [templo2, #index]
+}
+
+// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDR_IMM(dest_reg, templo2, index) );      // ldr dest_reg, [templo2, #index]
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       if (dword) {
+               cache_addw( LDR_IMM(dest_reg, templo2, index) );      // ldr dest_reg, [templo2, #index]
+       } else {
+               cache_addw( LDRH_IMM(dest_reg, templo2, index) );      // ldrh dest_reg, [templo2, #index]
+       }
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRB_IMM(dest_reg, templo2, index) );      // ldrb dest_reg, [templo2, #index]
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDRB_IMM(dest_reg, templo2, index) );      // ldrb dest_reg, [templo2, #index]
+}
+
+
+// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo2, FC_REGS_ADDR) );      // mov templo2, FC_REGS_ADDR
+       cache_addw( LDR_IMM(templo1, templo2, index) );      // ldr templo1, [templo2, #index]
+       cache_addw( ADD_REG(reg, reg, templo1) );      // add reg, reg, templo1
+}
+
+
+// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
+static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STRH_IMM(src_reg, templo1, index) );      // strh src_reg, [templo1, #index]
+}
+
+// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STR_IMM(src_reg, templo1, index) );      // str src_reg, [templo1, #index]
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       if (dword) {
+               cache_addw( STR_IMM(src_reg, templo1, index) );      // str src_reg, [templo1, #index]
+       } else {
+               cache_addw( STRH_IMM(src_reg, templo1, index) );      // strh src_reg, [templo1, #index]
+       }
+}
+
+// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
+static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
+       cache_addw( MOV_LO_HI(templo1, FC_REGS_ADDR) );      // mov templo1, FC_REGS_ADDR
+       cache_addw( STRB_IMM(src_reg, templo1, index) );      // strb src_reg, [templo1, #index]
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_armv4le.h
new file mode 100644 (file)
index 0000000..8a3b343
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/* ARMv4/ARMv7 (little endian) backend (switcher) by M-HT */
+
+#include "risc_armv4le-common.h"
+
+// choose your destiny:
+#if C_TARGETCPU == ARMV7LE
+       #include "risc_armv4le-o3.h"
+#else
+       #if defined(__THUMB_INTERWORK__)
+               #include "risc_armv4le-thumb-iw.h"
+       #else
+               #include "risc_armv4le-o3.h"
+//             #include "risc_armv4le-thumb-niw.h"
+//             #include "risc_armv4le-thumb.h"
+       #endif
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_mipsel32.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_mipsel32.h
new file mode 100644 (file)
index 0000000..0e7d474
--- /dev/null
@@ -0,0 +1,750 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+/* MIPS32 (little endian) backend by crazyc */
+
+
+// some configuring defines that specify the capabilities of this architecture
+// or aspects of the recompiling
+
+// protect FC_ADDR over function calls if necessaray
+// #define DRC_PROTECT_ADDR_REG
+
+// try to use non-flags generating functions if possible
+#define DRC_FLAGS_INVALIDATION
+// try to replace _simple functions by code
+#define DRC_FLAGS_INVALIDATION_DCODE
+
+// type with the same size as a pointer
+#define DRC_PTR_SIZE_IM Bit32u
+
+// calling convention modifier
+#define DRC_CALL_CONV  /* nothing */
+#define DRC_FC                 /* nothing */
+
+// use FC_REGS_ADDR to hold the address of "cpu_regs" and to access it using FC_REGS_ADDR
+//#define DRC_USE_REGS_ADDR
+// use FC_SEGS_ADDR to hold the address of "Segs" and to access it using FC_SEGS_ADDR
+//#define DRC_USE_SEGS_ADDR
+
+// register mapping
+typedef Bit8u HostReg;
+
+#define HOST_v0 2
+#define HOST_v1 3
+#define HOST_a0 4
+#define HOST_a1 5
+#define HOST_t4 12
+#define HOST_t5 13
+#define HOST_t6 14
+#define HOST_t7 15
+#define HOST_s0 16
+#define HOST_t8 24
+#define HOST_t9 25
+#define temp1 HOST_v1
+#define temp2 HOST_t9 
+
+// register that holds function return values
+#define FC_RETOP HOST_v0
+
+// register used for address calculations,
+#define FC_ADDR HOST_s0                        // has to be saved across calls, see DRC_PROTECT_ADDR_REG
+
+// register that holds the first parameter
+#define FC_OP1 HOST_a0
+
+// register that holds the second parameter
+#define FC_OP2 HOST_a1
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_???
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_t5
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_t6
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_t7
+
+#ifdef DRC_USE_REGS_ADDR
+// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
+#define FC_REGS_ADDR HOST_???
+#endif
+
+#ifdef DRC_USE_SEGS_ADDR
+// used to hold the address of "Segs" - preferably filled in function gen_run_code
+#define FC_SEGS_ADDR HOST_???
+#endif
+
+// save some state to improve code gen
+static bool temp1_valid = false;
+static Bit32u temp1_value;
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       if(reg_src == reg_dst) return; 
+       cache_addw((reg_dst<<11)+0x21);      // addu reg_dst, $0, reg_src 
+       cache_addw(reg_src); 
+}
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+       if(imm < 65536) {
+               cache_addw((Bit16u)imm);                // ori dest_reg, $0, imm
+               cache_addw(0x3400+dest_reg);
+       } else if(((Bit32s)imm < 0) && ((Bit32s)imm >= -32768)) {
+               cache_addw((Bit16u)imm);                // addiu dest_reg, $0, imm
+               cache_addw(0x2400+dest_reg);
+       } else if(!(imm & 0xffff)) {
+               cache_addw((Bit16u)(imm >> 16));        // lui dest_reg, %hi(imm)
+               cache_addw(0x3c00+dest_reg);
+       } else {
+               cache_addw((Bit16u)(imm >> 16));        // lui dest_reg, %hi(imm)
+               cache_addw(0x3c00+dest_reg);
+               cache_addw((Bit16u)imm);                // ori dest_reg, dest_reg, %lo(imm)
+               cache_addw(0x3400+(dest_reg<<5)+dest_reg);
+       }
+}
+
+// this is the only place temp1 should be modified
+static void INLINE mov_imm_to_temp1(Bit32u imm) {
+       if (temp1_valid && (temp1_value == imm)) return;
+       gen_mov_dword_to_reg_imm(temp1, imm);
+       temp1_valid = true;
+       temp1_value = imm;
+}
+
+static Bit16s gen_addr_temp1(Bit32u addr) {
+       Bit32u hihalf = addr & 0xffff0000;
+       Bit16s lohalf = addr & 0xffff;
+       if (lohalf > 32764) {  // [l,s]wl will overflow
+               hihalf = addr;
+               lohalf = 0;
+       } else if(lohalf < 0) hihalf += 0x10000;
+       mov_imm_to_temp1(hihalf);
+       return lohalf;
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
+       Bit16s lohalf = gen_addr_temp1((Bit32u)data);
+       // alignment....
+       if (dword) {
+               if ((Bit32u)data & 3) {
+                       cache_addw(lohalf+3);           // lwl dest_reg, 3(temp1)
+                       cache_addw(0x8800+(temp1<<5)+dest_reg);
+                       cache_addw(lohalf);             // lwr dest_reg, 0(temp1)
+                       cache_addw(0x9800+(temp1<<5)+dest_reg);
+               } else {
+                       cache_addw(lohalf);             // lw dest_reg, 0(temp1)
+                       cache_addw(0x8C00+(temp1<<5)+dest_reg);
+               }
+       } else {
+               if ((Bit32u)data & 1) {
+                       cache_addw(lohalf);             // lbu dest_reg, 0(temp1)
+                       cache_addw(0x9000+(temp1<<5)+dest_reg);
+                       cache_addw(lohalf+1);           // lbu temp2, 1(temp1)
+                       cache_addw(0x9000+(temp1<<5)+temp2);
+#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
+                       cache_addw(0x7a04);             // ins dest_reg, temp2, 8, 8
+                       cache_addw(0x7c00+(temp2<<5)+dest_reg);
+#else
+                       cache_addw((temp2<<11)+0x200);          // sll temp2, temp2, 8
+                       cache_addw(temp2);
+                       cache_addw((dest_reg<<11)+0x25);        // or dest_reg, temp2, dest_reg
+                       cache_addw((temp2<<5)+dest_reg);
+#endif
+               } else {
+                       cache_addw(lohalf);             // lhu dest_reg, 0(temp1);
+                       cache_addw(0x9400+(temp1<<5)+dest_reg);
+               }
+       }
+}
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       cache_addw(imm);                        // ori dest_reg, $0, imm
+       cache_addw(0x3400+dest_reg);
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
+       Bit16s lohalf = gen_addr_temp1((Bit32u)dest);
+       // alignment....
+       if (dword) {
+               if ((Bit32u)dest & 3) {
+                       cache_addw(lohalf+3);           // swl src_reg, 3(temp1)
+                       cache_addw(0xA800+(temp1<<5)+src_reg);
+                       cache_addw(lohalf);             // swr src_reg, 0(temp1)
+                       cache_addw(0xB800+(temp1<<5)+src_reg);
+               } else {
+                       cache_addw(lohalf);             // sw src_reg, 0(temp1)
+                       cache_addw(0xAC00+(temp1<<5)+src_reg);
+               }
+       } else {
+               if((Bit32u)dest & 1) {
+                       cache_addw(lohalf);             // sb src_reg, 0(temp1)
+                       cache_addw(0xA000+(temp1<<5)+src_reg);
+                       cache_addw((temp2<<11)+0x202);          // srl temp2, src_reg, 8
+                       cache_addw(src_reg);
+                       cache_addw(lohalf+1);           // sb temp2, 1(temp1)
+                       cache_addw(0xA000+(temp1<<5)+temp2);
+               } else {
+                       cache_addw(lohalf);             // sh src_reg, 0(temp1);
+                       cache_addw(0xA400+(temp1<<5)+src_reg);
+               }
+       }
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       Bit16s lohalf = gen_addr_temp1((Bit32u)data);
+       cache_addw(lohalf);                     // lbu dest_reg, 0(temp1)
+       cache_addw(0x9000+(temp1<<5)+dest_reg);
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       gen_mov_byte_to_reg_low(dest_reg, data);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       gen_mov_word_to_reg_imm(dest_reg, imm);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       gen_mov_byte_to_reg_low_imm(dest_reg, imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       Bit16s lohalf = gen_addr_temp1((Bit32u)dest);
+       cache_addw(lohalf);                     // sb src_reg, 0(temp1)
+       cache_addw(0xA000+(temp1<<5)+src_reg);
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       if (sign) {
+#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
+               cache_addw((reg<<11)+0x420);    // seb reg, reg
+               cache_addw(0x7c00+reg);
+#else
+               arch that lacks seb
+#endif
+       } else {
+               cache_addw(0xff);               // andi reg, reg, 0xff
+               cache_addw(0x3000+(reg<<5)+reg);
+       }
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       if (sign) {
+#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
+               cache_addw((reg<<11)+0x620);    // seh reg, reg
+               cache_addw(0x7c00+reg);
+#else
+               arch that lacks seh
+#endif
+       } else {
+               cache_addw(0xffff);             // andi reg, reg, 0xffff
+               cache_addw(0x3000+(reg<<5)+reg);
+       }
+}
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       gen_mov_word_to_reg(temp2, op, 1);
+       cache_addw((reg<<11)+0x21);             // addu reg, reg, temp2 
+       cache_addw((reg<<5)+temp2);
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       if(!imm) return;
+       if(((Bit32s)imm >= -32768) && ((Bit32s)imm < 32768)) {
+               cache_addw((Bit16u)imm);        // addiu reg, reg, imm
+               cache_addw(0x2400+(reg<<5)+reg);
+       } else {
+               mov_imm_to_temp1(imm);
+               cache_addw((reg<<11)+0x21);     // addu reg, reg, temp1
+               cache_addw((reg<<5)+temp1);
+       }
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       if(imm < 65536) { 
+               cache_addw((Bit16u)imm);      // andi reg, reg, imm 
+               cache_addw(0x3000+(reg<<5)+reg); 
+       } else { 
+               mov_imm_to_temp1((Bit32u)imm); 
+               cache_addw((reg<<11)+0x24);      // and reg, temp1, reg 
+               cache_addw((temp1<<5)+reg); 
+       } 
+}
+
+
+// move a 32bit constant value into memory
+static void INLINE gen_mov_direct_dword(void* dest,Bit32u imm) {
+       gen_mov_dword_to_reg_imm(temp2, imm);
+       gen_mov_word_from_reg(temp2, dest, 1);
+}
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_direct_dword(dest,(Bit32u)imm);
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void INLINE gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if(!imm) return;
+       gen_mov_word_to_reg(temp2, dest, dword);
+       gen_add_imm(temp2, imm);
+       gen_mov_word_from_reg(temp2, dest, dword);
+}
+
+// add an 8bit constant value to a dword memory value
+static void INLINE gen_add_direct_byte(void* dest,Bit8s imm) {
+       gen_add_direct_word(dest, (Bit32s)imm, 1);
+}
+
+// subtract an 8bit constant value from a dword memory value
+static void INLINE gen_sub_direct_byte(void* dest,Bit8s imm) {
+       gen_add_direct_word(dest, -((Bit32s)imm), 1);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void INLINE gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       gen_add_direct_word(dest, -(Bit32s)imm, dword);
+}
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_addw((scale_reg<<11)+(scale<<6));         // sll scale_reg, scale_reg, scale
+               cache_addw(scale_reg);
+       }
+       cache_addw((dest_reg<<11)+0x21);                        // addu dest_reg, dest_reg, scale_reg
+       cache_addw((dest_reg<<5)+scale_reg);
+       gen_add_imm(dest_reg, imm);
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       if (scale) {
+               cache_addw((dest_reg<<11)+(scale<<6));          // sll dest_reg, dest_reg, scale
+               cache_addw(dest_reg);
+       }
+       gen_add_imm(dest_reg, imm);
+}
+
+#define DELAY cache_addd(0)                    // nop
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+#if C_DEBUG
+       if ((cache.pos ^ func) & 0xf0000000) LOG_MSG("jump overflow\n");
+#endif
+       temp1_valid = false;
+       cache_addd(0x0c000000+(((Bit32u)func>>2)&0x3ffffff));           // jal func
+       DELAY;
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       Bit32u proc_addr = (Bit32u)cache.pos;
+       gen_call_function_raw(func);
+       return proc_addr;
+}
+
+#ifdef __mips_eabi
+// max of 8 parameters in $a0-$a3 and $t0-$t3
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       gen_mov_dword_to_reg_imm(param+4, imm);
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
+       gen_mov_dword_to_reg_imm(param+4, addr);
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       gen_mov_regs(param+4, reg);
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       gen_mov_word_to_reg(param+4, (void *)mem, 1);
+}
+#else
+       other mips abis
+#endif
+
+// jump to an address pointed at by ptr, offset is in imm
+static void INLINE gen_jmp_ptr(void * ptr,Bits imm=0) {
+       gen_mov_word_to_reg(temp2, ptr, 1);
+       if((imm < -32768) || (imm >= 32768)) {
+               gen_add_imm(temp2, imm);
+               imm = 0;
+       }
+       temp1_valid = false;
+       cache_addw((Bit16u)imm);        // lw temp2, imm(temp2)
+       cache_addw(0x8C00+(temp2<<5)+temp2);
+       cache_addd((temp2<<21)+8);      // jr temp2 
+       DELAY;
+}
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit32u INLINE gen_create_branch_on_zero(HostReg reg,bool dword) {
+       temp1_valid = false;
+       if(!dword) { 
+               cache_addw(0xffff);     // andi temp1, reg, 0xffff
+               cache_addw(0x3000+(reg<<5)+temp1);
+       }
+       cache_addw(0);                  // beq $0, reg, 0
+       cache_addw(0x1000+(dword?reg:temp1));
+       DELAY;
+       return ((Bit32u)cache.pos-8);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit32u INLINE gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       temp1_valid = false;
+       if(!dword) { 
+               cache_addw(0xffff);     // andi temp1, reg, 0xffff
+               cache_addw(0x3000+(reg<<5)+temp1);
+       }
+       cache_addw(0);                  // bne $0, reg, 0
+       cache_addw(0x1400+(dword?reg:temp1));
+       DELAY;
+       return ((Bit32u)cache.pos-8);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bits len=(Bit32u)cache.pos-data;
+       if (len<0) len=-len;
+       if (len>126) LOG_MSG("Big jump %d",len);
+#endif
+       temp1_valid = false;                    // this is a branch target
+       *(Bit16u*)data=((Bit16u)((Bit32u)cache.pos-data-4)>>2);
+}
+
+#if 0  // assume for the moment no branch will go farther then +/- 128KB
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       temp1_valid = false;
+       if (!isdword) {
+               cache_addw(0xff);       // andi temp1, reg, 0xff
+               cache_addw(0x3000+(reg<<5)+temp1);
+       }
+       cache_addw(3);                  // beq $0, reg, +12
+       cache_addw(0x1000+(isdword?reg:temp1)); 
+       DELAY;
+       cache_addd(0x00000000);         // fill j
+       DELAY;
+       return ((Bit32u)cache.pos-8);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) {
+       temp1_valid = false;
+       cache_addw(3);                          // bgtz reg, +12
+       cache_addw(0x1c00+(reg<<5));
+       DELAY;
+       cache_addd(0x00000000);                 // fill j 
+       DELAY;
+       return ((Bit32u)cache.pos-8);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch_long(Bit32u data) {
+       temp1_valid = false;
+       // this is an absolute branch
+       *(Bit32u*)data=0x08000000+(((Bit32u)cache.pos>>2)&0x3ffffff);
+}
+#else          
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       temp1_valid = false;
+       if (!isdword) {
+               cache_addw(0xff);       // andi temp1, reg, 0xff
+               cache_addw(0x3000+(reg<<5)+temp1);
+       }
+       cache_addw(0);                  // bne $0, reg, 0
+       cache_addw(0x1400+(isdword?reg:temp1)); 
+       DELAY;
+       return ((Bit32u)cache.pos-8);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) {
+       temp1_valid = false;
+       cache_addw(0);                  // blez reg, 0
+       cache_addw(0x1800+(reg<<5));
+       DELAY;
+       return ((Bit32u)cache.pos-8);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void INLINE gen_fill_branch_long(Bit32u data) {
+       gen_fill_branch(data);
+}
+#endif
+
+static void gen_run_code(void) {
+       temp1_valid = false;
+       cache_addd(0x27bdfff0);                 // addiu $sp, $sp, -16
+       cache_addd(0xafb00004);                 // sw $s0, 4($sp)
+       cache_addd(0x00800008);                 // jr $a0
+       cache_addd(0xafbf0000);                 // sw $ra, 0($sp)
+}
+
+// return from a function
+static void gen_return_function(void) {
+       temp1_valid = false;
+       cache_addd(0x8fbf0000);                 // lw $ra, 0($sp)
+       cache_addd(0x8fb00004);                 // lw $s0, 4($sp)
+       cache_addd(0x03e00008);                 // jr $ra
+       cache_addd(0x27bd0010);                 // addiu $sp, $sp, 16
+}
+
+#ifdef DRC_FLAGS_INVALIDATION
+// called when a call to a function can be replaced by a
+// call to a simpler function
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       // try to avoid function calls but rather directly fill in code
+       switch (flags_type) {
+               case t_ADDb:
+               case t_ADDw:
+               case t_ADDd:
+                       *(Bit32u*)pos=0x00851021;                                       // addu $v0, $a0, $a1
+                       break;
+               case t_ORb:
+               case t_ORw:
+               case t_ORd:
+                       *(Bit32u*)pos=0x00851025;                                       // or $v0, $a0, $a1
+                       break;
+               case t_ANDb:
+               case t_ANDw:
+               case t_ANDd:
+                       *(Bit32u*)pos=0x00851024;                                       // and $v0, $a0, $a1
+                       break;
+               case t_SUBb:
+               case t_SUBw:
+               case t_SUBd:
+                       *(Bit32u*)pos=0x00851023;                                       // subu $v0, $a0, $a1
+                       break;
+               case t_XORb:
+               case t_XORw:
+               case t_XORd:
+                       *(Bit32u*)pos=0x00851026;                                       // xor $v0, $a0, $a1
+                       break;
+               case t_CMPb:
+               case t_CMPw:
+               case t_CMPd:
+               case t_TESTb:
+               case t_TESTw:
+               case t_TESTd:
+                       *(Bit32u*)pos=0;                                                        // nop
+                       break;
+               case t_INCb:
+               case t_INCw:
+               case t_INCd:
+                       *(Bit32u*)pos=0x24820001;                                       // addiu $v0, $a0, 1
+                       break;
+               case t_DECb:
+               case t_DECw:
+               case t_DECd:
+                       *(Bit32u*)pos=0x2482ffff;                                       // addiu $v0, $a0, -1
+                       break;
+               case t_SHLb:
+               case t_SHLw:
+               case t_SHLd:
+                       *(Bit32u*)pos=0x00a41004;                                       // sllv $v0, $a0, $a1
+                       break;
+               case t_SHRb:
+               case t_SHRw:
+               case t_SHRd:
+                       *(Bit32u*)pos=0x00a41006;                                       // srlv $v0, $a0, $a1
+                       break;
+               case t_SARd:
+                       *(Bit32u*)pos=0x00a41007;                                       // srav $v0, $a0, $a1
+                       break;
+#if (_MIPS_ISA==MIPS32R2) || defined(PSP)
+               case t_RORd:
+                       *(Bit32u*)pos=0x00a41046;                                       // rotr $v0, $a0, $a1
+                       break;
+#endif
+               case t_NEGb:
+               case t_NEGw:
+               case t_NEGd:
+                       *(Bit32u*)pos=0x00041023;                                       // subu $v0, $0, $a0
+                       break;
+               default:
+                       *(Bit32u*)pos=0x0c000000+((((Bit32u)fct_ptr)>>2)&0x3ffffff);            // jal simple_func
+                       break;
+       }
+#else
+       *(Bit32u*)pos=0x0c000000+(((Bit32u)fct_ptr)>>2)&0x3ffffff);             // jal simple_func
+#endif
+}
+#endif
+
+static void cache_block_closing(Bit8u* block_start,Bitu block_size) {
+#ifdef PSP
+// writeback dcache and invalidate icache
+       Bit32u inval_start = ((Bit32u)block_start) & ~63;
+       Bit32u inval_end = (((Bit32u)block_start) + block_size + 64) & ~63;
+       for (;inval_start < inval_end; inval_start+=64) {
+               __builtin_allegrex_cache(0x1a, inval_start);
+               __builtin_allegrex_cache(0x08, inval_start);
+       }
+#endif
+}
+
+static void cache_block_before_close(void) { }
+
+
+#ifdef DRC_USE_SEGS_ADDR
+
+// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
+// stub
+}
+
+// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
+// stub
+}
+
+// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
+static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
+// stub
+}
+
+#endif
+
+#ifdef DRC_USE_REGS_ADDR
+
+// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
+// stub
+}
+
+// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
+// stub
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
+// stub
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
+// stub
+}
+
+// move an 8bit value from cpu_regs[index]  into dest_reg using FC_REGS_ADDR
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
+// stub
+}
+
+
+// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
+// stub
+}
+
+
+// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
+static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
+// stub
+}
+
+// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
+static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
+// stub
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
+static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
+// stub
+}
+
+// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
+static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
+// stub
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_x64.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_x64.h
new file mode 100644 (file)
index 0000000..e293e95
--- /dev/null
@@ -0,0 +1,746 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+// some configuring defines that specify the capabilities of this architecture
+// or aspects of the recompiling
+
+// protect FC_ADDR over function calls if necessaray
+// #define DRC_PROTECT_ADDR_REG
+
+// try to use non-flags generating functions if possible
+#define DRC_FLAGS_INVALIDATION
+// try to replace _simple functions by code
+#define DRC_FLAGS_INVALIDATION_DCODE
+
+// type with the same size as a pointer
+#define DRC_PTR_SIZE_IM Bit64u
+
+// calling convention modifier
+#define DRC_CALL_CONV  /* nothing */
+#define DRC_FC                 /* nothing */
+
+
+// register mapping
+typedef Bit8u HostReg;
+
+#define HOST_EAX 0
+#define HOST_ECX 1
+#define HOST_EDX 2
+#define HOST_EBX 3
+#define HOST_ESI 6
+#define HOST_EDI 7
+
+
+// register that holds function return values
+#define FC_RETOP HOST_EAX
+
+// register used for address calculations, if the ABI does not
+// state that this register is preserved across function calls
+// then define DRC_PROTECT_ADDR_REG above
+#define FC_ADDR HOST_EBX
+
+// register that holds the first parameter
+#define FC_OP1 HOST_EDI
+
+// register that holds the second parameter
+#define FC_OP2 HOST_ESI
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_EAX
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_ECX
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_EDX
+
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_ESI
+
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       cache_addb(0x8b);                                       // mov reg_dst,reg_src
+       cache_addb(0xc0+(reg_dst<<3)+reg_src);
+}
+
+// move a 64bit constant value into a full register
+static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) {
+       cache_addb(0x48);
+       cache_addb(0xb8+dest_reg);                      // mov dest_reg,imm
+       cache_addq(imm);
+}
+
+
+// This function generates an instruction with register addressing and a memory location
+static INLINE void gen_reg_memaddr(HostReg reg,void* data,Bit8u op,Bit8u prefix=0) {
+       Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+(prefix?7:6));
+//     if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { //clang messes itself up on this...
+       if ( (diff>>63) == (diff>>31) ) { //signed bit extend, test to see if value fits in a Bit32s
+               // mov reg,[rip+diff] (or similar, depending on the op) to fetch *data
+               if(prefix) cache_addb(prefix);
+               cache_addb(op);
+               cache_addb(0x05+(reg<<3));
+               // RIP-relative addressing is offset after the instruction 
+               cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL)); 
+       } else if ((Bit64u)data<0x100000000LL) {
+               // mov reg,[data] (or similar, depending on the op) when absolute address of data is <4GB
+               if(prefix) cache_addb(prefix);
+               cache_addb(op);
+               cache_addw(0x2504+(reg<<3));
+               cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL));
+       } else {
+               // load 64-bit data into tmp_reg and do mov reg,[tmp_reg] (or similar, depending on the op)
+               HostReg tmp_reg = HOST_EAX;
+               if(reg == HOST_EAX) tmp_reg = HOST_ECX;
+
+               cache_addb(0x50+tmp_reg);       // push rax/rcx
+               gen_mov_reg_qword(tmp_reg,(Bit64u)data);
+
+               if(prefix) cache_addb(prefix);
+               cache_addb(op);
+               cache_addb(tmp_reg+(reg<<3));
+
+               cache_addb(0x58+tmp_reg);       // pop rax/rcx
+       }
+}
+
+// Same as above, but with immediate addressing and a memory location
+static INLINE void gen_memaddr(Bitu modreg,void* data,Bitu off,Bitu imm,Bit8u op,Bit8u prefix=0) {
+       Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+off+(prefix?7:6));
+//     if ((diff<0x80000000LL) && (diff>-0x80000000LL)) {
+       if ( (diff>>63) == (diff>>31) ) {
+               // RIP-relative addressing is offset after the instruction 
+               if(prefix) cache_addb(prefix);
+               cache_addw(op+((modreg+1)<<8));
+               cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL));
+
+               switch(off) {
+                       case 1: cache_addb(((Bit8u)imm&0xff)); break;
+                       case 2: cache_addw(((Bit16u)imm&0xffff)); break;
+                       case 4: cache_addd(((Bit32u)imm&0xffffffff)); break;
+               }
+
+       } else if ((Bit64u)data<0x100000000LL) {
+               if(prefix) cache_addb(prefix);
+               cache_addw(op+(modreg<<8));
+               cache_addb(0x25);
+               cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL));
+
+               switch(off) {
+                       case 1: cache_addb(((Bit8u)imm&0xff)); break;
+                       case 2: cache_addw(((Bit16u)imm&0xffff)); break;
+                       case 4: cache_addd(((Bit32u)imm&0xffffffff)); break;
+               }
+
+       } else {
+               HostReg tmp_reg = HOST_EAX;
+
+               cache_addb(0x50+tmp_reg);       // push rax
+               gen_mov_reg_qword(tmp_reg,(Bit64u)data);
+
+               if(prefix) cache_addb(prefix);
+               cache_addw(op+((modreg-4+tmp_reg)<<8));
+
+               switch(off) {
+                       case 1: cache_addb(((Bit8u)imm&0xff)); break;
+                       case 2: cache_addw(((Bit16u)imm&0xffff)); break;
+                       case 4: cache_addd(((Bit32u)imm&0xffffffff)); break;
+               }
+
+               cache_addb(0x58+tmp_reg);       // pop rax
+       }
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword,Bit8u prefix=0) {
+       if (!dword) gen_reg_memaddr(dest_reg,data,0xb7,0x0f);   // movzx reg,[data] - zero extend data, fixes LLVM compile where the called function does not extend the parameters
+       else gen_reg_memaddr(dest_reg,data,0x8b,prefix);        // mov reg,[data]
+} 
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       cache_addb(0xb8+dest_reg);                      // mov reg,imm
+       cache_addd((Bit32u)imm);
+}
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+       cache_addb(0xb8+dest_reg);                      // mov reg,imm
+       cache_addd(imm);
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword,Bit8u prefix=0) {
+       gen_reg_memaddr(src_reg,dest,0x89,(dword?prefix:0x66));         // mov [data],reg
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       gen_reg_memaddr(dest_reg,data,0xb6,0x0f);       // movzx reg,[data]
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       gen_reg_memaddr(dest_reg,data,0xb6,0x0f);       // movzx reg,[data]
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       cache_addb(0xb8+dest_reg);                      // mov reg,imm
+       cache_addd((Bit32u)imm);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       cache_addb(0xb8+dest_reg);                      // mov reg,imm
+       cache_addd((Bit32u)imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       gen_reg_memaddr(src_reg,dest,0x88);     // mov byte [data],reg
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       cache_addw(0xb60f+(sign?0x800:0));              // movsx/movzx
+       cache_addb(0xc0+(reg<<3)+reg);
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       cache_addw(0xb70f+(sign?0x800:0));              // movsx/movzx
+       cache_addb(0xc0+(reg<<3)+reg);
+}
+
+
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       gen_reg_memaddr(reg,op,0x03);           // add reg,[data]
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       cache_addw(0xc081+(reg<<8));            // add reg,imm
+       cache_addd(imm);
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       cache_addw(0xe081+(reg<<8));            // and reg,imm
+       cache_addd(imm);
+}
+
+
+
+// move a 32bit constant value into memory
+static void gen_mov_direct_dword(void* dest,Bit32u imm) {
+       gen_memaddr(0x4,dest,4,imm,0xc7);       // mov [data],imm
+}
+
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_reg_qword(HOST_EAX,imm);
+       gen_mov_word_from_reg(HOST_EAX,dest,true,0x48);         // 0x48 prefixes full 64-bit mov
+}
+
+
+// add an 8bit constant value to a memory value
+static void gen_add_direct_byte(void* dest,Bit8s imm) {
+       gen_memaddr(0x4,dest,1,imm,0x83);       // add [data],imm
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if ((imm<128) && dword) {
+               gen_add_direct_byte(dest,(Bit8s)imm);
+               return;
+       }
+       gen_memaddr(0x4,dest,(dword?4:2),imm,0x81,(dword?0:0x66));      // add [data],imm
+}
+
+// subtract an 8bit constant value from a memory value
+static void gen_sub_direct_byte(void* dest,Bit8s imm) {
+       gen_memaddr(0x2c,dest,1,imm,0x83);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       if ((imm<128) && dword) {
+               gen_sub_direct_byte(dest,(Bit8s)imm);
+               return;
+       }
+       gen_memaddr(0x2c,dest,(dword?4:2),imm,0x81,(dword?0:0x66));     // sub [data],imm
+}
+
+
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       Bit8u rm_base;
+       Bitu imm_size;
+       if (!imm) {
+               imm_size=0;     rm_base=0x0;                    //no imm
+       } else if ((imm>=-128 && imm<=127)) {
+               imm_size=1;     rm_base=0x40;                   //Signed byte imm
+       } else {
+               imm_size=4;     rm_base=0x80;                   //Signed dword imm
+       }
+
+       // ea_reg := ea_reg+scale_reg*(2^scale)+imm
+       cache_addb(0x48);
+       cache_addb(0x8d);                       //LEA
+       cache_addb(0x04+(dest_reg << 3)+rm_base);       //The sib indicator
+       cache_addb(dest_reg+(scale_reg<<3)+(scale<<6));
+
+       switch (imm_size) {
+       case 0: break;
+       case 1:cache_addb(imm);break;
+       case 4:cache_addd(imm);break;
+       }
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       // ea_reg := ea_reg*(2^scale)+imm
+       // ea_reg :=   op2 *(2^scale)+imm
+       cache_addb(0x48);
+       cache_addb(0x8d);                       //LEA
+       cache_addb(0x04+(dest_reg<<3));
+       cache_addb(0x05+(dest_reg<<3)+(scale<<6));
+
+       cache_addd(imm);                // always add dword immediate
+}
+
+
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+       cache_addb(0x48); 
+       cache_addw(0xec83); 
+       cache_addb(0x08);       // sub rsp,0x08 (align stack to 16 byte boundary)
+
+       cache_addb(0x48);
+       cache_addb(0xb8);       // mov reg,imm64
+       cache_addq((Bit64u)func);
+       cache_addw(0xd0ff);
+
+       cache_addb(0x48); 
+       cache_addw(0xc483); 
+       cache_addb(0x08);       // add rsp,0x08 (reset alignment)
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit64u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       // align the stack
+       cache_addb(0x48);
+       cache_addw(0xc48b);             // mov rax,rsp
+
+       cache_addb(0x48);
+       cache_addw(0xec83);             // sub rsp,0x08
+       cache_addb(0x08);               // 0x08==return address pushed onto stack by call
+
+       cache_addb(0x48);
+       cache_addw(0xe483);             // and esp,0xfffffffffffffff0
+       cache_addb(0xf0);
+
+       cache_addb(0x48);
+       cache_addw(0xc483);             // add rsp,0x08
+       cache_addb(0x08);
+
+       // stack is 16 byte aligned now
+
+
+       cache_addb(0x50);               // push rax (==old rsp)
+
+       // returned address relates to where the address is stored in gen_call_function_raw
+       Bit64u proc_addr=(Bit64u)cache.pos-4;
+
+       // Do the actual call to the procedure
+       cache_addb(0x48);
+       cache_addb(0xb8);               // mov reg,imm64
+       cache_addq((Bit64u)func);
+
+       cache_addw(0xd0ff);
+
+       // restore stack
+       cache_addb(0x5c);               // pop rsp
+
+       return proc_addr;
+}
+
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       // move an immediate 32bit value into a 64bit param reg
+       switch (param) {
+               case 0:                 // mov param1,imm32
+                       gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm);
+                       break;
+               case 1:                 // mov param2,imm32
+                       gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm);
+                       break;
+#if defined (_MSC_VER)
+               case 2:                 // mov r8,imm32
+                       cache_addw(0xb849);
+                       cache_addq((Bit32u)imm);
+                       break;
+               case 3:                 // mov r9,imm32
+                       cache_addw(0xb949);
+                       cache_addq((Bit32u)imm);
+                       break;
+#else
+               case 2:                 // mov rdx,imm32
+                       gen_mov_dword_to_reg_imm(HOST_EDX,(Bit32u)imm);
+                       break;
+               case 3:                 // mov rcx,imm32
+                       gen_mov_dword_to_reg_imm(HOST_ECX,(Bit32u)imm);
+                       break;
+#endif
+               default:
+                       E_Exit("I(mm) >4 params unsupported");
+                       break;
+       }
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(DRC_PTR_SIZE_IM addr,Bitu param) {
+       // move an immediate 64bit value into a 64bit param reg
+       switch (param) {
+               case 0:                 // mov param1,addr64
+                       gen_mov_reg_qword(FC_OP1,addr);
+                       break;
+               case 1:                 // mov param2,addr64
+                       gen_mov_reg_qword(FC_OP2,addr);
+                       break;
+#if defined (_MSC_VER)
+               case 2:                 // mov r8,addr64
+                       cache_addw(0xb849);
+                       cache_addq(addr);
+                       break;
+               case 3:                 // mov r9,addr64
+                       cache_addw(0xb949);
+                       cache_addq(addr);
+                       break;
+#else
+               case 2:                 // mov rdx,addr64
+                       gen_mov_reg_qword(HOST_EDX,addr);
+                       break;
+               case 3:                 // mov rcx,addr64
+                       gen_mov_reg_qword(HOST_ECX,addr);
+                       break;
+#endif
+               default:
+                       E_Exit("A(ddr) >4 params unsupported");
+                       break;
+       }
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       // move a register into a 64bit param reg, {inputregs}!={outputregs}
+       switch (param) {
+               case 0:         // mov param1,reg&7
+                       gen_mov_regs(FC_OP1,reg&7);
+                       break;
+               case 1:         // mov param2,reg&7
+                       gen_mov_regs(FC_OP2,reg&7);
+                       break;
+#if defined (_MSC_VER)
+               case 2:         // mov r8,reg&7
+                       cache_addb(0x49);
+                       gen_mov_regs(0,reg&7);
+                       break;
+               case 3:         // mov r9,reg&7
+                       cache_addb(0x49);
+                       gen_mov_regs(1,reg&7);
+                       break;
+#else
+               case 2:         // mov rdx,reg&7
+                       gen_mov_regs(HOST_EDX,reg&7);
+                       break;
+               case 3:         // mov rcx,reg&7
+                       gen_mov_regs(HOST_ECX,reg&7);
+                       break;
+#endif
+               default:
+                       E_Exit("R(eg) >4 params unsupported");
+                       break;
+       }
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       // move memory content into a 64bit param reg
+       switch (param) {
+               case 0:         // mov param1,[mem]
+                       gen_mov_word_to_reg(FC_OP1,(void*)mem,true);
+                       break;
+               case 1:         // mov param2,[mem]
+                       gen_mov_word_to_reg(FC_OP2,(void*)mem,true);
+                       break;
+#if defined (_MSC_VER)
+               case 2:         // mov r8,[mem]
+                       gen_mov_word_to_reg(0,(void*)mem,true,0x49);    // 0x49, use x64 rX regs
+                       break;
+               case 3:         // mov r9,[mem]
+                       gen_mov_word_to_reg(1,(void*)mem,true,0x49);    // 0x49, use x64 rX regs
+                       break;
+#else
+               case 2:         // mov rdx,[mem]
+                       gen_mov_word_to_reg(HOST_EDX,(void*)mem,true);
+                       break;
+               case 3:         // mov rcx,[mem]
+                       gen_mov_word_to_reg(HOST_ECX,(void*)mem,true);
+                       break;
+#endif
+               default:
+                       E_Exit("R(eg) >4 params unsupported");
+                       break;
+       }
+}
+
+
+
+// jump to an address pointed at by ptr, offset is in imm
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       cache_addw(0xa148);             // mov rax,[data]
+       cache_addq((Bit64u)ptr);
+
+       cache_addb(0xff);               // jmp [rax+imm]
+       if (!imm) {
+               cache_addb(0x20);
+    } else if ((imm>=-128 && imm<=127)) {
+               cache_addb(0x60);
+               cache_addb(imm);
+       } else {
+               cache_addb(0xa0);
+               cache_addd(imm);
+       }
+}
+
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit64u gen_create_branch_on_zero(HostReg reg,bool dword) {
+       if (!dword) cache_addb(0x66);
+       cache_addb(0x0b);                                       // or reg,reg
+       cache_addb(0xc0+reg+(reg<<3));
+
+       cache_addw(0x0074);                                     // jz addr
+       return ((Bit64u)cache.pos-1);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit64u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       if (!dword) cache_addb(0x66);
+       cache_addb(0x0b);                                       // or reg,reg
+       cache_addb(0xc0+reg+(reg<<3));
+
+       cache_addw(0x0075);                                     // jnz addr
+       return ((Bit64u)cache.pos-1);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bit64s len=(Bit64u)cache.pos-data;
+       if (len<0) len=-len;
+       if (len>126) LOG_MSG("Big jump %d",len);
+#endif
+       *(Bit8u*)data=(Bit8u)((Bit64u)cache.pos-data-1);
+}
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit64u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       // isdword: cmp reg32,0
+       // not isdword: cmp reg8,0
+       cache_addb(0x0a+(isdword?1:0));                         // or reg,reg
+       cache_addb(0xc0+reg+(reg<<3));
+
+       cache_addw(0x850f);             // jnz
+       cache_addd(0);
+       return ((Bit64u)cache.pos-4);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit64u gen_create_branch_long_leqzero(HostReg reg) {
+       cache_addw(0xf883+(reg<<8));
+       cache_addb(0x00);               // cmp reg,0
+
+       cache_addw(0x8e0f);             // jle
+       cache_addd(0);
+       return ((Bit64u)cache.pos-4);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void gen_fill_branch_long(Bit64u data) {
+       *(Bit32u*)data=(Bit32u)((Bit64u)cache.pos-data-4);
+}
+
+
+static void gen_run_code(void) {
+       cache_addb(0x53);                                       // push rbx
+       cache_addw(0xd0ff+(FC_OP1<<8));         // call rdi
+       cache_addb(0x5b);                                       // pop  rbx
+}
+
+// return from a function
+static void gen_return_function(void) {
+       cache_addb(0xc3);               // ret
+}
+
+#ifdef DRC_FLAGS_INVALIDATION
+// called when a call to a function can be replaced by a
+// call to a simpler function
+// check gen_call_function_raw and gen_call_function_setup
+// for the targeted code
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       // try to avoid function calls but rather directly fill in code
+       switch (flags_type) {
+               case t_ADDb:
+               case t_ADDw:
+               case t_ADDd:
+                       *(Bit32u*)(pos+0)=0xf001f889;   // mov eax,edi; add eax,esi
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_ORb:
+               case t_ORw:
+               case t_ORd:
+                       *(Bit32u*)(pos+0)=0xf009f889;   // mov eax,edi; or eax,esi
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_ANDb:
+               case t_ANDw:
+               case t_ANDd:
+                       *(Bit32u*)(pos+0)=0xf021f889;   // mov eax,edi; and eax,esi
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_SUBb:
+               case t_SUBw:
+               case t_SUBd:
+                       *(Bit32u*)(pos+0)=0xf029f889;   // mov eax,edi; sub eax,esi
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_XORb:
+               case t_XORw:
+               case t_XORd:
+                       *(Bit32u*)(pos+0)=0xf031f889;   // mov eax,edi; xor eax,esi
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_CMPb:
+               case t_CMPw:
+               case t_CMPd:
+               case t_TESTb:
+               case t_TESTw:
+               case t_TESTd:
+                       *(Bit32u*)(pos+0)=0x909012eb;   // skip
+                       *(Bit32u*)(pos+4)=0x90909090;
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_INCb:
+               case t_INCw:
+               case t_INCd:
+                       *(Bit32u*)(pos+0)=0xc0fff889;   // mov eax,edi; inc eax
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_DECb:
+               case t_DECw:
+               case t_DECd:
+                       *(Bit32u*)(pos+0)=0xc8fff889;   // mov eax,edi; dec eax
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               case t_NEGb:
+               case t_NEGw:
+               case t_NEGd:
+                       *(Bit32u*)(pos+0)=0xd8f7f889;   // mov eax,edi; neg eax
+                       *(Bit32u*)(pos+4)=0x90900eeb;   // skip
+                       *(Bit32u*)(pos+8)=0x90909090;
+                       *(Bit32u*)(pos+12)=0x90909090;
+                       *(Bit32u*)(pos+16)=0x90909090;
+                       break;
+               default:
+                       *(Bit64u*)(pos+6)=(Bit64u)fct_ptr;              // fill function pointer
+                       break;
+       }
+#else
+       *(Bit64u*)(pos+6)=(Bit64u)fct_ptr;              // fill function pointer
+#endif
+}
+#endif
+
+static void cache_block_closing(Bit8u* block_start,Bitu block_size) { }
+
+static void cache_block_before_close(void) { }
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_x86.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_dynrec/risc_x86.h
new file mode 100644 (file)
index 0000000..81cb03b
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+
+// some configuring defines that specify the capabilities of this architecture
+// or aspects of the recompiling
+
+// protect FC_ADDR over function calls if necessaray
+// #define DRC_PROTECT_ADDR_REG
+
+// try to use non-flags generating functions if possible
+#define DRC_FLAGS_INVALIDATION
+// try to replace _simple functions by code
+#define DRC_FLAGS_INVALIDATION_DCODE
+
+// type with the same size as a pointer
+#define DRC_PTR_SIZE_IM Bit32u
+
+// calling convention modifier
+#if defined (WIN32)
+#define DRC_CALL_CONV _fastcall
+#define DRC_FC /* nothing */
+#else
+#define DRC_CALL_CONV /* nothing */
+#define DRC_FC GCC_ATTRIBUTE(fastcall)
+#endif
+
+
+// register mapping
+enum HostReg {
+       HOST_EAX=0,
+       HOST_ECX,
+       HOST_EDX,
+       HOST_EBX,
+       HOST_ESP,
+       HOST_EBP,
+       HOST_ESI,
+       HOST_EDI
+};
+
+
+// register that holds function return values
+#define FC_RETOP HOST_EAX
+
+// register used for address calculations, if the ABI does not
+// state that this register is preserved across function calls
+// then define DRC_PROTECT_ADDR_REG above
+#define FC_ADDR HOST_EBX
+
+// register that holds the first parameter
+#define FC_OP1 HOST_ECX
+
+// register that holds the second parameter
+#define FC_OP2 HOST_EDX
+
+// special register that holds the third parameter for _R3 calls (byte accessible)
+#define FC_OP3 HOST_EAX
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA1 HOST_ECX
+
+// register that holds byte-accessible temporary values
+#define FC_TMP_BA2 HOST_EDX
+
+
+// temporary register for LEA
+#define TEMP_REG_DRC HOST_ESI
+
+
+// move a full register from reg_src to reg_dst
+static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
+       cache_addb(0x8b);                                       // mov reg_dst,reg_src
+       cache_addb(0xc0+(reg_dst<<3)+reg_src);
+}
+
+// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
+// 16bit moves may destroy the upper 16bit of the destination register
+static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
+       if (!dword) cache_addb(0x66);
+       cache_addw(0x058b+(dest_reg<<11));      // mov reg,[data]
+       cache_addd((Bit32u)data);
+}
+
+// move a 16bit constant value into dest_reg
+// the upper 16bit of the destination register may be destroyed
+static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
+       cache_addb(0x66);
+       cache_addb(0xb8+dest_reg);                      // mov reg,imm
+       cache_addw(imm);
+}
+
+// move a 32bit constant value into dest_reg
+static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
+       cache_addb(0xb8+dest_reg);                      // mov reg,imm
+       cache_addd(imm);
+}
+
+// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
+static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
+       if (!dword) cache_addb(0x66);
+       cache_addw(0x0589+(src_reg<<11));       // mov [data],reg
+       cache_addd((Bit32u)dest);
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
+       cache_addw(0x058a+(dest_reg<<11));      // mov reg,[data]
+       cache_addd((Bit32u)data);
+}
+
+// move an 8bit value from memory into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
+       cache_addb(0x66);
+       cache_addw(0x058b+(dest_reg<<11));      // mov reg,[data]
+       cache_addd((Bit32u)data);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function does not use FC_OP1/FC_OP2 as dest_reg as these
+// registers might not be directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
+       cache_addb(0xb0+dest_reg);                      // mov reg,imm
+       cache_addb(imm);
+}
+
+// move an 8bit constant value into dest_reg
+// the upper 24bit of the destination register can be destroyed
+// this function can use FC_OP1/FC_OP2 as dest_reg which are
+// not directly byte-accessible on some architectures
+static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
+       cache_addb(0x66);
+       cache_addb(0xb8+dest_reg);                      // mov reg,imm
+       cache_addw(imm);
+}
+
+// move the lowest 8bit of a register into memory
+static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
+       cache_addw(0x0588+(src_reg<<11));       // mov [data],reg
+       cache_addd((Bit32u)dest);
+}
+
+
+
+// convert an 8bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_byte(bool sign,HostReg reg) {
+       cache_addw(0xb60f+(sign?0x800:0));              // movsx/movzx
+       cache_addb(0xc0+(reg<<3)+reg);
+}
+
+// convert a 16bit word to a 32bit dword
+// the register is zero-extended (sign==false) or sign-extended (sign==true)
+static void gen_extend_word(bool sign,HostReg reg) {
+       cache_addw(0xb70f+(sign?0x800:0));              // movsx/movzx
+       cache_addb(0xc0+(reg<<3)+reg);
+}
+
+
+
+// add a 32bit value from memory to a full register
+static void gen_add(HostReg reg,void* op) {
+       cache_addw(0x0503+(reg<<11));           // add reg,[data]
+       cache_addd((Bit32u)op);
+}
+
+// add a 32bit constant value to a full register
+static void gen_add_imm(HostReg reg,Bit32u imm) {
+       cache_addw(0xc081+(reg<<8));            // add reg,imm
+       cache_addd(imm);
+}
+
+// and a 32bit constant value with a full register
+static void gen_and_imm(HostReg reg,Bit32u imm) {
+       cache_addw(0xe081+(reg<<8));            // and reg,imm
+       cache_addd(imm);
+}
+
+
+
+// move a 32bit constant value into memory
+static void gen_mov_direct_dword(void* dest,Bit32u imm) {
+       cache_addw(0x05c7);                                     // mov [data],imm
+       cache_addd((Bit32u)dest);
+       cache_addd(imm);
+}
+
+// move an address into memory
+static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
+       gen_mov_direct_dword(dest,(Bit32u)imm);
+}
+
+
+// add an 8bit constant value to a memory value
+static void gen_add_direct_byte(void* dest,Bit8s imm) {
+       cache_addw(0x0583);                                     // add [data],imm
+       cache_addd((Bit32u)dest);
+       cache_addb(imm);
+}
+
+// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
+static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
+       if ((imm<128) && dword) {
+               gen_add_direct_byte(dest,(Bit8s)imm);
+               return;
+       }
+       if (!dword) cache_addb(0x66);
+       cache_addw(0x0581);                                     // add [data],imm
+       cache_addd((Bit32u)dest);
+       if (dword) cache_addd((Bit32u)imm);
+       else cache_addw((Bit16u)imm);
+}
+
+// subtract an 8bit constant value from a memory value
+static void gen_sub_direct_byte(void* dest,Bit8s imm) {
+       cache_addw(0x2d83);                                     // sub [data],imm
+       cache_addd((Bit32u)dest);
+       cache_addb(imm);
+}
+
+// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
+static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
+       if ((imm<128) && dword) {
+               gen_sub_direct_byte(dest,(Bit8s)imm);
+               return;
+       }
+       if (!dword) cache_addb(0x66);
+       cache_addw(0x2d81);                                     // sub [data],imm
+       cache_addd((Bit32u)dest);
+       if (dword) cache_addd((Bit32u)imm);
+       else cache_addw((Bit16u)imm);
+}
+
+
+
+// effective address calculation, destination is dest_reg
+// scale_reg is scaled by scale (scale_reg*(2^scale)) and
+// added to dest_reg, then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
+       Bit8u rm_base;
+       Bitu imm_size;
+       if (!imm) {
+               imm_size=0;     rm_base=0x0;                    //no imm
+       } else if ((imm>=-128 && imm<=127)) {
+               imm_size=1;     rm_base=0x40;                   //Signed byte imm
+       } else {
+               imm_size=4;     rm_base=0x80;                   //Signed dword imm
+       }
+
+       // ea_reg := ea_reg+scale_reg*(2^scale)+imm
+       cache_addb(0x8d);                       //LEA
+       cache_addb(0x04+(dest_reg << 3)+rm_base);       //The sib indicator
+       cache_addb(dest_reg+(scale_reg<<3)+(scale<<6));
+
+       switch (imm_size) {
+       case 0: break;
+       case 1:cache_addb(imm);break;
+       case 4:cache_addd(imm);break;
+       }
+}
+
+// effective address calculation, destination is dest_reg
+// dest_reg is scaled by scale (dest_reg*(2^scale)),
+// then the immediate value is added
+static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
+       // ea_reg := ea_reg*(2^scale)+imm
+       // ea_reg :=   op2 *(2^scale)+imm
+       cache_addb(0x8d);                       //LEA
+       cache_addb(0x04+(dest_reg<<3));
+       cache_addb(0x05+(dest_reg<<3)+(scale<<6));
+
+       cache_addd(imm);                // always add dword immediate
+}
+
+
+
+// generate a call to a parameterless function
+static void INLINE gen_call_function_raw(void * func) {
+       cache_addb(0xe8);
+       cache_addd((Bit32u)func - (Bit32u)cache.pos-4);
+}
+
+// generate a call to a function with paramcount parameters
+// note: the parameters are loaded in the architecture specific way
+// using the gen_load_param_ functions below
+static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
+       Bit32u proc_addr=(Bit32u)cache.pos;
+       // Do the actual call to the procedure
+       cache_addb(0xe8);
+       cache_addd((Bit32u)func - (Bit32u)cache.pos-4);
+
+       // Restore the params of the stack
+       if (paramcount) {
+               cache_addw(0xc483);                             //add ESP,imm byte
+               cache_addb((!fastcall)?paramcount*4:0);
+       }
+       return proc_addr;
+}
+
+
+// load an immediate value as param'th function parameter
+static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
+       cache_addb(0x68);                       // push immediate
+       cache_addd(imm);
+}
+
+// load an address as param'th function parameter
+static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
+       cache_addb(0x68);                       // push immediate (address)
+       cache_addd(addr);
+}
+
+// load a host-register as param'th function parameter
+static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
+       cache_addb(0x50+(reg&7));       // push reg
+}
+
+// load a value from memory as param'th function parameter
+static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
+       cache_addw(0x35ff);                     // push []
+       cache_addd(mem);
+}
+
+
+
+// jump to an address pointed at by ptr, offset is in imm
+static void gen_jmp_ptr(void * ptr,Bits imm=0) {
+       gen_mov_word_to_reg(HOST_EAX,ptr,true);
+       cache_addb(0xff);               // jmp [eax+imm]
+       if (!imm) {
+               cache_addb(0x20);
+    } else if ((imm>=-128 && imm<=127)) {
+               cache_addb(0x60);
+               cache_addb(imm);
+       } else {
+               cache_addb(0xa0);
+               cache_addd(imm);
+       }
+}
+
+
+// short conditional jump (+-127 bytes) if register is zero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
+       if (!dword) cache_addb(0x66);
+       cache_addb(0x0b);                                       // or reg,reg
+       cache_addb(0xc0+reg+(reg<<3));
+
+       cache_addw(0x0074);                                     // jz addr
+       return ((Bit32u)cache.pos-1);
+}
+
+// short conditional jump (+-127 bytes) if register is nonzero
+// the destination is set by gen_fill_branch() later
+static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
+       if (!dword) cache_addb(0x66);
+       cache_addb(0x0b);                                       // or reg,reg
+       cache_addb(0xc0+reg+(reg<<3));
+
+       cache_addw(0x0075);                                     // jnz addr
+       return ((Bit32u)cache.pos-1);
+}
+
+// calculate relative offset and fill it into the location pointed to by data
+static void gen_fill_branch(DRC_PTR_SIZE_IM data) {
+#if C_DEBUG
+       Bits len=(Bit32u)cache.pos-data;
+       if (len<0) len=-len;
+       if (len>126) LOG_MSG("Big jump %d",len);
+#endif
+       *(Bit8u*)data=(Bit8u)((Bit32u)cache.pos-data-1);
+}
+
+// conditional jump if register is nonzero
+// for isdword==true the 32bit of the register are tested
+// for isdword==false the lowest 8bit of the register are tested
+static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
+       // isdword: cmp reg32,0
+       // not isdword: cmp reg8,0
+       cache_addb(0x0a+(isdword?1:0));                         // or reg,reg
+       cache_addb(0xc0+reg+(reg<<3));
+
+       cache_addw(0x850f);             // jnz
+       cache_addd(0);
+       return ((Bit32u)cache.pos-4);
+}
+
+// compare 32bit-register against zero and jump if value less/equal than zero
+static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
+       cache_addw(0xf883+(reg<<8));
+       cache_addb(0x00);               // cmp reg,0
+
+       cache_addw(0x8e0f);             // jle
+       cache_addd(0);
+       return ((Bit32u)cache.pos-4);
+}
+
+// calculate long relative offset and fill it into the location pointed to by data
+static void gen_fill_branch_long(Bit32u data) {
+       *(Bit32u*)data=((Bit32u)cache.pos-data-4);
+}
+
+
+static void gen_run_code(void) {
+       cache_addd(0x0424448b);         // mov eax,[esp+4]
+       cache_addb(0x53);                       // push ebx
+       cache_addb(0x56);                       // push esi
+       cache_addw(0xd0ff);                     // call eax
+       cache_addb(0x5e);                       // pop  esi
+       cache_addb(0x5b);                       // pop  ebx
+}
+
+// return from a function
+static void gen_return_function(void) {
+       cache_addb(0xc3);               // ret
+}
+
+#ifdef DRC_FLAGS_INVALIDATION
+// called when a call to a function can be replaced by a
+// call to a simpler function
+static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
+#ifdef DRC_FLAGS_INVALIDATION_DCODE
+       // try to avoid function calls but rather directly fill in code
+       switch (flags_type) {
+               case t_ADDb:
+               case t_ADDw:
+               case t_ADDd:
+                       *(Bit32u*)pos=0xc203c18b;       // mov eax,ecx; add eax,edx
+                       *(pos+4)=0x90;
+                       break;
+               case t_ORb:
+               case t_ORw:
+               case t_ORd:
+                       *(Bit32u*)pos=0xc20bc18b;       // mov eax,ecx; or eax,edx
+                       *(pos+4)=0x90;
+                       break;
+               case t_ANDb:
+               case t_ANDw:
+               case t_ANDd:
+                       *(Bit32u*)pos=0xc223c18b;       // mov eax,ecx; and eax,edx
+                       *(pos+4)=0x90;
+                       break;
+               case t_SUBb:
+               case t_SUBw:
+               case t_SUBd:
+                       *(Bit32u*)pos=0xc22bc18b;       // mov eax,ecx; sub eax,edx
+                       *(pos+4)=0x90;
+                       break;
+               case t_XORb:
+               case t_XORw:
+               case t_XORd:
+                       *(Bit32u*)pos=0xc233c18b;       // mov eax,ecx; xor eax,edx
+                       *(pos+4)=0x90;
+                       break;
+               case t_CMPb:
+               case t_CMPw:
+               case t_CMPd:
+               case t_TESTb:
+               case t_TESTw:
+               case t_TESTd:
+                       *(Bit32u*)pos=0x909003eb;       // skip
+                       *(pos+4)=0x90;
+                       break;
+               case t_INCb:
+               case t_INCw:
+               case t_INCd:
+                       *(Bit32u*)pos=0x9040c18b;       // mov eax,ecx; inc eax
+                       *(pos+4)=0x90;
+                       break;
+               case t_DECb:
+               case t_DECw:
+               case t_DECd:
+                       *(Bit32u*)pos=0x9048c18b;       // mov eax,ecx; dec eax
+                       *(pos+4)=0x90;
+                       break;
+               case t_NEGb:
+               case t_NEGw:
+               case t_NEGd:
+                       *(Bit32u*)pos=0xd8f7c18b;       // mov eax,ecx; neg eax
+                       *(pos+4)=0x90;
+                       break;
+               default:
+                       *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4));        // fill function pointer
+                       break;
+       }
+#else
+       *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4));        // fill function pointer
+#endif
+}
+#endif
+
+static void cache_block_closing(Bit8u* block_start,Bitu block_size) { }
+
+static void cache_block_before_close(void) { }
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/core_full.cpp
new file mode 100644 (file)
index 0000000..7fd1469
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "dosbox.h"
+
+#include "pic.h"
+#include "regs.h"
+#include "cpu.h"
+#include "lazyflags.h"
+#include "paging.h"
+#include "fpu.h"
+#include "debug.h"
+#include "inout.h"
+#include "callback.h"
+
+
+typedef PhysPt EAPoint;
+#define SegBase(c)     SegPhys(c)
+
+#define LoadMb(off) mem_readb_inline(off)
+#define LoadMw(off) mem_readw_inline(off)
+#define LoadMd(off) mem_readd_inline(off)
+
+#define LoadMbs(off) (Bit8s)(LoadMb(off))
+#define LoadMws(off) (Bit16s)(LoadMw(off))
+#define LoadMds(off) (Bit32s)(LoadMd(off))
+
+#define SaveMb(off,val)        mem_writeb_inline(off,val)
+#define SaveMw(off,val)        mem_writew_inline(off,val)
+#define SaveMd(off,val)        mem_writed_inline(off,val)
+
+#define LoadD(reg) reg
+#define SaveD(reg,val) reg=val
+
+
+
+#include "core_full/loadwrite.h"
+#include "core_full/support.h"
+#include "core_full/optable.h"
+#include "instructions.h"
+
+#define EXCEPTION(blah)                                                                                \
+       {                                                                                                               \
+               Bit8u new_num=blah;                                                                     \
+               CPU_Exception(new_num,0);                                                       \
+               continue;                                                                                       \
+       }
+
+Bits CPU_Core_Full_Run(void) {
+       FullData inst;  
+       while (CPU_Cycles-->0) {
+#if C_DEBUG
+               cycle_count++;
+#if C_HEAVY_DEBUG
+               if (DEBUG_HeavyIsBreakpoint()) {
+                       FillFlags();
+                       return debugCallback;
+               };
+#endif
+#endif
+               LoadIP();
+               inst.entry=cpu.code.big*0x200;
+               inst.prefix=cpu.code.big;
+restartopcode:
+               inst.entry=(inst.entry & 0xffffff00) | Fetchb();
+               inst.code=OpCodeTable[inst.entry];
+               #include "core_full/load.h"
+               #include "core_full/op.h"
+               #include "core_full/save.h"
+nextopcode:;
+               SaveIP();
+               continue;
+illegalopcode:
+               LOG(LOG_CPU,LOG_NORMAL)("Illegal opcode");
+               CPU_Exception(0x6,0);
+       }
+       FillFlags();
+       return CBRET_NONE;
+}
+
+
+void CPU_Core_Full_Init(void) {
+
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile
new file mode 100644 (file)
index 0000000..bc83085
--- /dev/null
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# src/cpu/core_full/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/dosbox
+pkgincludedir = $(includedir)/dosbox
+pkglibdir = $(libdir)/dosbox
+pkglibexecdir = $(libexecdir)/dosbox
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-pc-linux-gnu
+host_triplet = x86_64-pc-linux-gnu
+subdir = src/cpu/core_full
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = aclocal-1.16
+ALSA_CFLAGS = 
+ALSA_LIBS =  -lasound -lm -ldl -lpthread
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AUTOCONF = autoconf
+AUTOHEADER = autoheader
+AUTOMAKE = automake-1.16
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =  -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = 
+LIBOBJS = 
+LIBS = -lasound -lm -ldl -lpthread -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpng -lz -lX11 -lGL
+LTLIBOBJS = 
+MAKEINFO = makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = dosbox
+PACKAGE_BUGREPORT = 
+PACKAGE_NAME = dosbox
+PACKAGE_STRING = dosbox 0.74
+PACKAGE_TARNAME = dosbox
+PACKAGE_URL = 
+PACKAGE_VERSION = 0.74
+PATH_SEPARATOR = :
+RANLIB = ranlib
+SDL_CFLAGS = -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+SDL_CONFIG = /usr/local/bin/sdl-config
+SDL_LIBS = -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpthread
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = 
+VERSION = 0.74
+WINDRES = :
+abs_builddir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_full
+abs_srcdir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_full
+abs_top_builddir = /home/whatisthis/src/DOSVAXJ3
+abs_top_srcdir = /home/whatisthis/src/DOSVAXJ3
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-pc-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-pc-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/whatisthis/src/DOSVAXJ3/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+runstatedir = ${localstatedir}/run
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias = 
+top_build_prefix = ../../../
+top_builddir = ../../..
+top_srcdir = ../../..
+noinst_HEADERS = ea_lookup.h load.h loadwrite.h op.h optable.h save.h \
+                string.h support.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_full/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_full/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile.am b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile.am
new file mode 100644 (file)
index 0000000..41fbe6a
--- /dev/null
@@ -0,0 +1,3 @@
+
+noinst_HEADERS = ea_lookup.h load.h loadwrite.h op.h optable.h save.h \
+                string.h support.h
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile.in b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/Makefile.in
new file mode 100644 (file)
index 0000000..450107c
--- /dev/null
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/cpu/core_full
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_HEADERS = ea_lookup.h load.h loadwrite.h op.h optable.h save.h \
+                string.h support.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_full/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_full/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/ea_lookup.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/ea_lookup.h
new file mode 100644 (file)
index 0000000..6048a43
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+{
+       EAPoint seg_base;
+       Bit16u off;
+       switch ((inst.rm_mod<<3)|inst.rm_eai) {
+       case 0x00:
+               off=reg_bx+reg_si;
+               seg_base=SegBase(ds);
+               break;
+       case 0x01:
+               off=reg_bx+reg_di;
+               seg_base=SegBase(ds);
+               break;
+       case 0x02:
+               off=reg_bp+reg_si;
+               seg_base=SegBase(ss);
+               break;
+       case 0x03:
+               off=reg_bp+reg_di;
+               seg_base=SegBase(ss);
+               break;
+       case 0x04:
+               off=reg_si;
+               seg_base=SegBase(ds);
+               break;
+       case 0x05:
+               off=reg_di;
+               seg_base=SegBase(ds);
+               break;
+       case 0x06:
+               off=Fetchw();
+               seg_base=SegBase(ds);
+               break;
+       case 0x07:
+               off=reg_bx;
+               seg_base=SegBase(ds);
+               break;
+
+       case 0x08:
+               off=reg_bx+reg_si+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x09:
+               off=reg_bx+reg_di+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x0a:
+               off=reg_bp+reg_si+Fetchbs();
+               seg_base=SegBase(ss);
+               break;
+       case 0x0b:
+               off=reg_bp+reg_di+Fetchbs();
+               seg_base=SegBase(ss);
+               break;
+       case 0x0c:
+               off=reg_si+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x0d:
+               off=reg_di+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x0e:
+               off=reg_bp+Fetchbs();
+               seg_base=SegBase(ss);
+               break;
+       case 0x0f:
+               off=reg_bx+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       
+       case 0x10:
+               off=reg_bx+reg_si+Fetchws();
+               seg_base=SegBase(ds);
+               break;
+       case 0x11:
+               off=reg_bx+reg_di+Fetchws();
+               seg_base=SegBase(ds);
+               break;
+       case 0x12:
+               off=reg_bp+reg_si+Fetchws();
+               seg_base=SegBase(ss);
+               break;
+       case 0x13:
+               off=reg_bp+reg_di+Fetchws();
+               seg_base=SegBase(ss);
+               break;
+       case 0x14:
+               off=reg_si+Fetchws();
+               seg_base=SegBase(ds);
+               break;
+       case 0x15:
+               off=reg_di+Fetchws();
+               seg_base=SegBase(ds);
+               break;
+       case 0x16:
+               off=reg_bp+Fetchws();
+               seg_base=SegBase(ss);
+               break;
+       case 0x17:
+               off=reg_bx+Fetchws();
+               seg_base=SegBase(ds);
+               break;
+       }
+       inst.rm_off=off;
+       if (inst.prefix & PREFIX_SEG) {
+               inst.rm_eaa=inst.seg.base+off;
+       } else {
+               inst.rm_eaa=seg_base+off;
+       }
+} else  {
+
+
+#define SIB(MODE)      {                                                                                               \
+       Bitu sib=Fetchb();                                                                                              \
+       switch (sib&7) {                                                                                                \
+       case 0:seg_base=SegBase(ds);off=reg_eax;break;                                  \
+       case 1:seg_base=SegBase(ds);off=reg_ecx;break;                                  \
+       case 2:seg_base=SegBase(ds);off=reg_edx;break;                                  \
+       case 3:seg_base=SegBase(ds);off=reg_ebx;break;                                  \
+       case 4:seg_base=SegBase(ss);off=reg_esp;break;                                  \
+       case 5:if (!MODE) {     seg_base=SegBase(ds);off=Fetchd();break;        \
+                  } else { seg_base=SegBase(ss);off=reg_ebp;break;}            \
+       case 6:seg_base=SegBase(ds);off=reg_esi;break;                                  \
+       case 7:seg_base=SegBase(ds);off=reg_edi;break;                                  \
+       }                                                                                                                               \
+       off+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);                                    \
+};                                                                                                                                     
+       static Bit32u SIBZero=0;
+       static Bit32u * SIBIndex[8]= { &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&SIBZero,&reg_ebp,&reg_esi,&reg_edi };
+       EAPoint seg_base;
+       Bit32u off;
+       switch ((inst.rm_mod<<3)|inst.rm_eai) {
+       case 0x00:
+               off=reg_eax;
+               seg_base=SegBase(ds);
+               break;
+       case 0x01:
+               off=reg_ecx;
+               seg_base=SegBase(ds);
+               break;
+       case 0x02:
+               off=reg_edx;
+               seg_base=SegBase(ds);
+               break;
+       case 0x03:
+               off=reg_ebx;
+               seg_base=SegBase(ds);
+               break;
+       case 0x04:
+               SIB(0);
+               break;
+       case 0x05:
+               off=Fetchd();
+               seg_base=SegBase(ds);
+               break;
+       case 0x06:
+               off=reg_esi;
+               seg_base=SegBase(ds);
+               break;
+       case 0x07:
+               off=reg_edi;
+               seg_base=SegBase(ds);
+               break;
+       
+       case 0x08:
+               off=reg_eax+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x09:
+               off=reg_ecx+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x0a:
+               off=reg_edx+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x0b:
+               off=reg_ebx+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x0c:
+               SIB(1);
+               off+=Fetchbs();
+               break;
+       case 0x0d:
+               off=reg_ebp+Fetchbs();
+               seg_base=SegBase(ss);
+               break;
+       case 0x0e:
+               off=reg_esi+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+       case 0x0f:
+               off=reg_edi+Fetchbs();
+               seg_base=SegBase(ds);
+               break;
+
+       case 0x10:
+               off=reg_eax+Fetchds();
+               seg_base=SegBase(ds);
+               break;
+       case 0x11:
+               off=reg_ecx+Fetchds();
+               seg_base=SegBase(ds);
+               break;
+       case 0x12:
+               off=reg_edx+Fetchds();
+               seg_base=SegBase(ds);
+               break;
+       case 0x13:
+               off=reg_ebx+Fetchds();
+               seg_base=SegBase(ds);
+               break;
+       case 0x14:
+               SIB(1);
+               off+=Fetchds();
+               break;
+       case 0x15:
+               off=reg_ebp+Fetchds();
+               seg_base=SegBase(ss);
+               break;
+       case 0x16:
+               off=reg_esi+Fetchds();
+               seg_base=SegBase(ds);
+               break;
+       case 0x17:
+               off=reg_edi+Fetchds();
+               seg_base=SegBase(ds);
+               break;
+       }
+       inst.rm_off=off;
+       if (inst.prefix & PREFIX_SEG) {
+               inst.rm_eaa=inst.seg.base+off;
+       } else {
+               inst.rm_eaa=seg_base+off;
+       }
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/load.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/load.h
new file mode 100644 (file)
index 0000000..699803c
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+switch (inst.code.load) {
+/* General loading */
+       case L_POPwRM:
+               inst_op1_w = Pop_16();
+               goto case_L_MODRM;
+       case L_POPdRM:
+               inst_op1_d = Pop_32();
+               goto case_L_MODRM;
+       case L_MODRM_NVM:
+               if ((reg_flags & FLAG_VM) || !cpu.pmode) goto illegalopcode;
+               goto case_L_MODRM;
+case_L_MODRM:
+       case L_MODRM:
+               inst.rm=Fetchb();
+               inst.rm_index=(inst.rm >> 3) & 7;
+               inst.rm_eai=inst.rm&07;
+               inst.rm_mod=inst.rm>>6;
+               /* Decode address of mod/rm if needed */
+               if (inst.rm<0xc0) {
+                       if (!(inst.prefix & PREFIX_ADDR))
+                       #include "ea_lookup.h"
+               }
+l_MODRMswitch:
+               switch (inst.code.extra) {      
+/* Byte */
+               case M_Ib:
+                       inst_op1_d=Fetchb();
+                       break;
+               case M_Ebx:
+                       if (inst.rm<0xc0) inst_op1_ds=(Bit8s)LoadMb(inst.rm_eaa);
+                       else inst_op1_ds=(Bit8s)reg_8(inst.rm_eai);
+                       break;
+               case M_EbIb:
+                       inst_op2_d=Fetchb();
+               case M_Eb:
+                       if (inst.rm<0xc0) inst_op1_d=LoadMb(inst.rm_eaa);
+                       else inst_op1_d=reg_8(inst.rm_eai);
+                       break;
+               case M_EbGb:
+                       if (inst.rm<0xc0) inst_op1_d=LoadMb(inst.rm_eaa);
+                       else inst_op1_d=reg_8(inst.rm_eai);
+                       inst_op2_d=reg_8(inst.rm_index);
+                       break;
+               case M_GbEb:
+                       if (inst.rm<0xc0) inst_op2_d=LoadMb(inst.rm_eaa);
+                       else inst_op2_d=reg_8(inst.rm_eai);
+               case M_Gb:
+                       inst_op1_d=reg_8(inst.rm_index);;
+                       break;
+/* Word */
+               case M_Iw:
+                       inst_op1_d=Fetchw();
+                       break;
+               case M_EwxGwx:
+                       inst_op2_ds=(Bit16s)reg_16(inst.rm_index);
+                       goto l_M_Ewx;
+               case M_EwxIbx:
+                       inst_op2_ds=Fetchbs();
+                       goto l_M_Ewx;
+               case M_EwxIwx:
+                       inst_op2_ds=Fetchws();
+l_M_Ewx:               
+               case M_Ewx:
+                       if (inst.rm<0xc0) inst_op1_ds=(Bit16s)LoadMw(inst.rm_eaa);
+                       else inst_op1_ds=(Bit16s)reg_16(inst.rm_eai);
+                       break;
+               case M_EwIb:
+                       inst_op2_d=Fetchb();
+                       goto l_M_Ew;
+               case M_EwIbx:
+                       inst_op2_ds=Fetchbs();
+                       goto l_M_Ew;            
+               case M_EwIw:
+                       inst_op2_d=Fetchw();
+                       goto l_M_Ew;
+               case M_EwGwCL:
+                       inst_imm_d=reg_cl;
+                       goto l_M_EwGw;
+               case M_EwGwIb:
+                       inst_imm_d=Fetchb();
+                       goto l_M_EwGw;
+               case M_EwGwt:
+                       inst_op2_d=reg_16(inst.rm_index);
+                       inst.rm_eaa+=((Bit16s)inst_op2_d >> 4) * 2;
+                       goto l_M_Ew;
+l_M_EwGw:                      
+               case M_EwGw:
+                       inst_op2_d=reg_16(inst.rm_index);
+l_M_Ew:
+               case M_Ew:
+                       if (inst.rm<0xc0) inst_op1_d=LoadMw(inst.rm_eaa);
+                       else inst_op1_d=reg_16(inst.rm_eai);
+                       break;
+               case M_GwEw:
+                       if (inst.rm<0xc0) inst_op2_d=LoadMw(inst.rm_eaa);
+                       else inst_op2_d=reg_16(inst.rm_eai);
+               case M_Gw:
+                       inst_op1_d=reg_16(inst.rm_index);;
+                       break;
+/* DWord */
+               case M_Id:
+                       inst_op1_d=Fetchd();
+                       break;
+               case M_EdxGdx:
+                       inst_op2_ds=(Bit32s)reg_32(inst.rm_index);
+               case M_Edx:
+                       if (inst.rm<0xc0) inst_op1_d=(Bit32s)LoadMd(inst.rm_eaa);
+                       else inst_op1_d=(Bit32s)reg_32(inst.rm_eai);
+                       break;
+               case M_EdIb:
+                       inst_op2_d=Fetchb();
+                       goto l_M_Ed;
+               case M_EdIbx:
+                       inst_op2_ds=Fetchbs();
+                       goto l_M_Ed;
+               case M_EdId:
+                       inst_op2_d=Fetchd();
+                       goto l_M_Ed;                    
+               case M_EdGdCL:
+                       inst_imm_d=reg_cl;
+                       goto l_M_EdGd;
+               case M_EdGdt:
+                       inst_op2_d=reg_32(inst.rm_index);
+                       inst.rm_eaa+=((Bit32s)inst_op2_d >> 5) * 4;
+                       goto l_M_Ed;
+               case M_EdGdIb:
+                       inst_imm_d=Fetchb();
+                       goto l_M_EdGd;
+l_M_EdGd:
+               case M_EdGd:
+                       inst_op2_d=reg_32(inst.rm_index);
+l_M_Ed:
+               case M_Ed:
+                       if (inst.rm<0xc0) inst_op1_d=LoadMd(inst.rm_eaa);
+                       else inst_op1_d=reg_32(inst.rm_eai);
+                       break;
+               case M_GdEd:
+                       if (inst.rm<0xc0) inst_op2_d=LoadMd(inst.rm_eaa);
+                       else inst_op2_d=reg_32(inst.rm_eai);
+               case M_Gd:
+                       inst_op1_d=reg_32(inst.rm_index);
+                       break;
+/* Others */           
+
+               case M_SEG:
+                       //TODO Check for limit
+                       inst_op1_d=SegValue((SegNames)inst.rm_index);
+                       break;
+               case M_Efw:
+                       if (inst.rm>=0xc0) goto illegalopcode;
+                       inst_op1_d=LoadMw(inst.rm_eaa);
+                       inst_op2_d=LoadMw(inst.rm_eaa+2);
+                       break;
+               case M_Efd:
+                       if (inst.rm>=0xc0) goto illegalopcode;
+                       inst_op1_d=LoadMd(inst.rm_eaa);
+                       inst_op2_d=LoadMw(inst.rm_eaa+4);
+                       break;
+               case M_EA:
+                       inst_op1_d=inst.rm_off;
+                       break;
+               case M_POPw:
+                       inst_op1_d = Pop_16();
+                       break;
+               case M_POPd:
+                       inst_op1_d = Pop_32();
+                       break;
+               case M_GRP:
+                       inst.code=Groups[inst.code.op][inst.rm_index];
+                       goto l_MODRMswitch;
+               case M_GRP_Ib:
+                       inst_op2_d=Fetchb();
+                       inst.code=Groups[inst.code.op][inst.rm_index];
+                       goto l_MODRMswitch;
+               case M_GRP_CL:
+                       inst_op2_d=reg_cl;
+                       inst.code=Groups[inst.code.op][inst.rm_index];
+                       goto l_MODRMswitch;
+               case M_GRP_1:
+                       inst_op2_d=1;
+                       inst.code=Groups[inst.code.op][inst.rm_index];
+                       goto l_MODRMswitch;
+               case 0:
+                       break;
+               default:
+                       LOG(LOG_CPU,LOG_ERROR)("MODRM:Unhandled load %d entry %x",inst.code.extra,inst.entry);
+                       break;
+               }
+               break;
+       case L_POPw:
+               inst_op1_d = Pop_16();
+               break;
+       case L_POPd:
+               inst_op1_d = Pop_32();
+               break;
+       case L_POPfw:
+               inst_op1_d = Pop_16();
+               inst_op2_d = Pop_16();
+               break;
+       case L_POPfd:
+               inst_op1_d = Pop_32();
+               inst_op2_d = Pop_16();
+               break;
+       case L_Ib:
+               inst_op1_d=Fetchb();
+               break;
+       case L_Ibx:
+               inst_op1_ds=Fetchbs();
+               break;
+       case L_Iw:
+               inst_op1_d=Fetchw();
+               break;
+       case L_Iwx:
+               inst_op1_ds=Fetchws();
+               break;
+       case L_Idx:
+       case L_Id:
+               inst_op1_d=Fetchd();
+               break;
+       case L_Ifw:
+               inst_op1_d=Fetchw();
+               inst_op2_d=Fetchw();
+               break;
+       case L_Ifd:
+               inst_op1_d=Fetchd();
+               inst_op2_d=Fetchw();
+               break;
+/* Direct load of registers */
+       case L_REGbIb:
+               inst_op2_d=Fetchb();
+       case L_REGb:
+               inst_op1_d=reg_8(inst.code.extra);
+               break;
+       case L_REGwIw:
+               inst_op2_d=Fetchw();
+       case L_REGw:
+               inst_op1_d=reg_16(inst.code.extra);
+               break;
+       case L_REGdId:
+               inst_op2_d=Fetchd();
+       case L_REGd:
+               inst_op1_d=reg_32(inst.code.extra);
+               break;
+       case L_SEG:
+               inst_op1_d=SegValue((SegNames)inst.code.extra);
+               break;
+/* Depending on addressize */
+       case L_OP:
+               if (inst.prefix & PREFIX_ADDR) {
+                       inst.rm_eaa=Fetchd();
+               } else {
+                       inst.rm_eaa=Fetchw();
+               }
+               if (inst.prefix & PREFIX_SEG) {
+                       inst.rm_eaa+=inst.seg.base;
+               } else {
+                       inst.rm_eaa+=SegBase(ds);
+               }
+               break;
+       /* Special cases */
+       case L_DOUBLE:
+               inst.entry|=0x100;
+               goto restartopcode;
+       case L_PRESEG:
+               inst.prefix|=PREFIX_SEG;
+               inst.seg.base=SegBase((SegNames)inst.code.extra);
+               goto restartopcode;
+       case L_PREREPNE:
+               inst.prefix|=PREFIX_REP;
+               inst.repz=false;
+               goto restartopcode;
+       case L_PREREP:
+               inst.prefix|=PREFIX_REP;
+               inst.repz=true;
+               goto restartopcode;
+       case L_PREOP:
+               inst.entry=(cpu.code.big ^1) * 0x200;
+               goto restartopcode;
+       case L_PREADD:
+               inst.prefix=(inst.prefix & ~1) | (cpu.code.big ^ 1);
+               goto restartopcode;
+       case L_VAL:
+               inst_op1_d=inst.code.extra;
+               break;
+       case L_INTO:
+               if (!get_OF()) goto nextopcode;
+               inst_op1_d=4;
+               break;
+       case D_IRETw:
+               CPU_IRET(false,GetIP());
+               if (GETFLAG(IF) && PIC_IRQCheck) {
+                       return CBRET_NONE;
+               }
+               continue;
+       case D_IRETd:
+               CPU_IRET(true,GetIP());
+               if (GETFLAG(IF) && PIC_IRQCheck) 
+                       return CBRET_NONE;
+               continue;
+       case D_RETFwIw:
+               {
+                       Bitu words=Fetchw();
+                       FillFlags();    
+                       CPU_RET(false,words,GetIP());
+                       continue;
+               }
+       case D_RETFw:
+               FillFlags();
+               CPU_RET(false,0,GetIP());
+               continue;
+       case D_RETFdIw:
+               {
+                       Bitu words=Fetchw();
+                       FillFlags();    
+                       CPU_RET(true,words,GetIP());
+                       continue;
+               }
+       case D_RETFd:
+               FillFlags();
+               CPU_RET(true,0,GetIP());
+               continue;
+/* Direct operations */
+       case L_STRING:
+               #include "string.h"
+               goto nextopcode;
+       case D_PUSHAw:
+               {
+                       Bit16u old_sp=reg_sp;
+                       Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx);
+                       Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di);
+               }
+               goto nextopcode;
+       case D_PUSHAd:
+               {
+                       Bit32u old_esp=reg_esp;
+                       Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx);
+                       Push_32(old_esp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi);
+               }
+               goto nextopcode;
+       case D_POPAw:
+               reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP
+               reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16();
+               goto nextopcode;
+       case D_POPAd:
+               reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP
+               reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
+               goto nextopcode;
+       case D_POPSEGw:
+               if (CPU_PopSeg((SegNames)inst.code.extra,false)) RunException();
+               goto nextopcode;
+       case D_POPSEGd:
+               if (CPU_PopSeg((SegNames)inst.code.extra,true)) RunException();
+               goto nextopcode;
+       case D_SETALC:
+               reg_al = get_CF() ? 0xFF : 0;
+               goto nextopcode;
+       case D_XLAT:
+               if (inst.prefix & PREFIX_SEG) {
+                       if (inst.prefix & PREFIX_ADDR) {
+                               reg_al=LoadMb(inst.seg.base+(Bit32u)(reg_ebx+reg_al));
+                       } else {
+                               reg_al=LoadMb(inst.seg.base+(Bit16u)(reg_bx+reg_al));
+                       }
+               } else {
+                       if (inst.prefix & PREFIX_ADDR) {
+                               reg_al=LoadMb(SegBase(ds)+(Bit32u)(reg_ebx+reg_al));
+                       } else {
+                               reg_al=LoadMb(SegBase(ds)+(Bit16u)(reg_bx+reg_al));
+                       }
+               }
+               goto nextopcode;
+       case D_CBW:
+               reg_ax=(Bit8s)reg_al;
+               goto nextopcode;
+       case D_CWDE:
+               reg_eax=(Bit16s)reg_ax;
+               goto nextopcode;
+       case D_CWD:
+               if (reg_ax & 0x8000) reg_dx=0xffff;
+               else reg_dx=0;
+               goto nextopcode;
+       case D_CDQ:
+               if (reg_eax & 0x80000000) reg_edx=0xffffffff;
+               else reg_edx=0;
+               goto nextopcode;
+       case D_CLI:
+               if (CPU_CLI()) RunException();
+               goto nextopcode;
+       case D_STI:
+               if (CPU_STI()) RunException();
+               goto nextopcode;
+       case D_STC:
+               FillFlags();SETFLAGBIT(CF,true);
+               goto nextopcode;
+       case D_CLC:
+               FillFlags();SETFLAGBIT(CF,false);
+               goto nextopcode;
+       case D_CMC:
+               FillFlags();
+               SETFLAGBIT(CF,!(reg_flags & FLAG_CF));
+               goto nextopcode;
+       case D_CLD:
+               SETFLAGBIT(DF,false);
+               cpu.direction=1;
+               goto nextopcode;
+       case D_STD:
+               SETFLAGBIT(DF,true);
+               cpu.direction=-1;
+               goto nextopcode;
+       case D_PUSHF:
+               if (CPU_PUSHF(inst.code.extra)) RunException();
+               goto nextopcode;
+       case D_POPF:
+               if (CPU_POPF(inst.code.extra)) RunException();
+               if (GETFLAG(IF) && PIC_IRQCheck) {
+                       SaveIP();
+                       return CBRET_NONE;
+               }
+               goto nextopcode;
+       case D_SAHF:
+               SETFLAGSb(reg_ah);
+               goto nextopcode;
+       case D_LAHF:
+               FillFlags();
+               reg_ah=reg_flags&0xff;
+               goto nextopcode;
+       case D_WAIT:
+       case D_NOP:
+               goto nextopcode;
+       case D_LOCK: /* FIXME: according to intel, LOCK should raise an exception if it's not followed by one of a small set of instructions;
+                       probably doesn't matter for our purposes as it is a pentium prefix anyhow */
+               LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK");
+               goto nextopcode;
+       case D_ENTERw:
+               {
+                       Bitu bytes=Fetchw();
+                       Bitu level=Fetchb();
+                       CPU_ENTER(false,bytes,level);
+                       goto nextopcode;
+               }
+       case D_ENTERd:
+               {
+                       Bitu bytes=Fetchw();
+                       Bitu level=Fetchb();
+                       CPU_ENTER(true,bytes,level);
+                       goto nextopcode;
+               }
+       case D_LEAVEw:
+               reg_esp&=cpu.stack.notmask;
+               reg_esp|=(reg_ebp&cpu.stack.mask);
+               reg_bp=Pop_16();
+               goto nextopcode;
+       case D_LEAVEd:
+               reg_esp&=cpu.stack.notmask;
+               reg_esp|=(reg_ebp&cpu.stack.mask);
+               reg_ebp=Pop_32();
+               goto nextopcode;
+       case D_DAA:
+               DAA();
+               goto nextopcode;
+       case D_DAS:
+               DAS();
+               goto nextopcode;
+       case D_AAA:
+               AAA();
+               goto nextopcode;
+       case D_AAS:
+               AAS();
+               goto nextopcode;
+       case D_CPUID:
+               if (!CPU_CPUID()) goto illegalopcode;
+               goto nextopcode;
+       case D_HLT:
+               if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+               FillFlags();
+               CPU_HLT(GetIP());
+               return CBRET_NONE;
+       case D_CLTS:
+               if (cpu.pmode && cpu.cpl) goto illegalopcode;
+               cpu.cr0&=(~CR0_TASKSWITCH);
+               goto nextopcode;
+       case D_ICEBP:
+               CPU_SW_Interrupt_NoIOPLCheck(1,GetIP());
+               continue;
+       case D_RDTSC: {
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUMSLOW) goto illegalopcode;
+               Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double)(CPU_CycleAutoAdjust?70000:CPU_CycleMax));
+               reg_edx=(Bit32u)(tsc>>32);
+               reg_eax=(Bit32u)(tsc&0xffffffff);
+               break;
+               }
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("LOAD:Unhandled code %d opcode %X",inst.code.load,inst.entry);
+               goto illegalopcode;
+}
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/loadwrite.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/loadwrite.h
new file mode 100644 (file)
index 0000000..b00ffb6
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#define SaveIP() reg_eip=(Bit32u)(inst.cseip-SegBase(cs));
+#define LoadIP() inst.cseip=SegBase(cs)+reg_eip;
+#define GetIP()        (inst.cseip-SegBase(cs))
+
+#define RunException() {                                                                               \
+       CPU_Exception(cpu.exception.which,cpu.exception.error);         \
+       continue;                                                                                                       \
+}
+
+static INLINE Bit8u the_Fetchb(EAPoint & loc) {
+       Bit8u temp=LoadMb(loc);
+       loc+=1;
+       return temp;
+}
+       
+static INLINE Bit16u the_Fetchw(EAPoint & loc) {
+       Bit16u temp=LoadMw(loc);
+       loc+=2;
+       return temp;
+}
+static INLINE Bit32u the_Fetchd(EAPoint & loc) {
+       Bit32u temp=LoadMd(loc);
+       loc+=4;
+       return temp;
+}
+
+#define Fetchb() the_Fetchb(inst.cseip)
+#define Fetchw() the_Fetchw(inst.cseip)
+#define Fetchd() the_Fetchd(inst.cseip)
+
+#define Fetchbs() (Bit8s)the_Fetchb(inst.cseip)
+#define Fetchws() (Bit16s)the_Fetchw(inst.cseip)
+#define Fetchds() (Bit32s)the_Fetchd(inst.cseip)
+
+#define Push_16 CPU_Push16
+#define Push_32 CPU_Push32
+#define Pop_16 CPU_Pop16
+#define Pop_32 CPU_Pop32
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/op.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/op.h
new file mode 100644 (file)
index 0000000..14786b1
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Do the actual opcode */
+switch (inst.code.op) {
+       case t_ADDb:    case t_ADDw:    case t_ADDd:
+               lf_var1d=inst_op1_d;
+               lf_var2d=inst_op2_d;
+               inst_op1_d=lf_resd=lf_var1d + lf_var2d;
+               lflags.type=inst.code.op;
+               break;
+       case t_CMPb:    case t_CMPw:    case t_CMPd:
+       case t_SUBb:    case t_SUBw:    case t_SUBd:
+               lf_var1d=inst_op1_d;
+               lf_var2d=inst_op2_d;
+               inst_op1_d=lf_resd=lf_var1d - lf_var2d;
+               lflags.type=inst.code.op;
+               break;
+       case t_ORb:             case t_ORw:             case t_ORd:
+               lf_var1d=inst_op1_d;
+               lf_var2d=inst_op2_d;
+               inst_op1_d=lf_resd=lf_var1d | lf_var2d;
+               lflags.type=inst.code.op;
+               break;
+       case t_XORb:    case t_XORw:    case t_XORd:
+               lf_var1d=inst_op1_d;
+               lf_var2d=inst_op2_d;
+               inst_op1_d=lf_resd=lf_var1d ^ lf_var2d;
+               lflags.type=inst.code.op;
+               break;
+       case t_TESTb:   case t_TESTw:   case t_TESTd:
+       case t_ANDb:    case t_ANDw:    case t_ANDd:
+               lf_var1d=inst_op1_d;
+               lf_var2d=inst_op2_d;
+               inst_op1_d=lf_resd=lf_var1d & lf_var2d;
+               lflags.type=inst.code.op;
+               break;
+       case t_ADCb:    case t_ADCw:    case t_ADCd:
+               lflags.oldcf=(get_CF()!=0);
+               lf_var1d=inst_op1_d;
+               lf_var2d=inst_op2_d;
+               inst_op1_d=lf_resd=lf_var1d + lf_var2d + lflags.oldcf;
+               lflags.type=inst.code.op;
+               break;
+       case t_SBBb:    case t_SBBw:    case t_SBBd:
+               lflags.oldcf=(get_CF()!=0);
+               lf_var1d=inst_op1_d;
+               lf_var2d=inst_op2_d;
+               inst_op1_d=lf_resd=lf_var1d - lf_var2d - lflags.oldcf;
+               lflags.type=inst.code.op;
+               break;
+       case t_INCb:    case t_INCw:    case t_INCd:
+               LoadCF;
+               lf_var1d=inst_op1_d;
+               inst_op1_d=lf_resd=inst_op1_d+1;
+               lflags.type=inst.code.op;
+               break;
+       case t_DECb:    case t_DECw:    case t_DECd:
+               LoadCF;
+               lf_var1d=inst_op1_d;
+               inst_op1_d=lf_resd=inst_op1_d-1;
+               lflags.type=inst.code.op;
+               break;
+/* Using the instructions.h defines */
+       case t_ROLb:
+               ROLB(inst_op1_b,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_ROLw:
+               ROLW(inst_op1_w,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_ROLd:
+               ROLD(inst_op1_d,inst_op2_b,LoadD,SaveD);
+               break;
+
+       case t_RORb:
+               RORB(inst_op1_b,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_RORw:
+               RORW(inst_op1_w,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_RORd:
+               RORD(inst_op1_d,inst_op2_b,LoadD,SaveD);
+               break;
+
+       case t_RCLb:
+               RCLB(inst_op1_b,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_RCLw:
+               RCLW(inst_op1_w,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_RCLd:
+               RCLD(inst_op1_d,inst_op2_b,LoadD,SaveD);
+               break;
+
+       case t_RCRb:
+               RCRB(inst_op1_b,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_RCRw:
+               RCRW(inst_op1_w,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_RCRd:
+               RCRD(inst_op1_d,inst_op2_b,LoadD,SaveD);
+               break;
+
+       case t_SHLb:
+               SHLB(inst_op1_b,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_SHLw:
+               SHLW(inst_op1_w,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_SHLd:
+               SHLD(inst_op1_d,inst_op2_b,LoadD,SaveD);
+               break;
+
+       case t_SHRb:
+               SHRB(inst_op1_b,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_SHRw:
+               SHRW(inst_op1_w,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_SHRd:
+               SHRD(inst_op1_d,inst_op2_b,LoadD,SaveD);
+               break;
+
+       case t_SARb:
+               SARB(inst_op1_b,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_SARw:
+               SARW(inst_op1_w,inst_op2_b,LoadD,SaveD);
+               break;
+       case t_SARd:
+               SARD(inst_op1_d,inst_op2_b,LoadD,SaveD);
+               break;
+
+       case O_DSHLw:
+               {
+                       DSHLW(inst_op1_w,inst_op2_w,inst_imm_b,LoadD,SaveD);
+                       break;
+               }
+       case O_DSHRw:
+               {
+                       DSHRW(inst_op1_w,inst_op2_w,inst_imm_b,LoadD,SaveD);
+                       break;
+               }
+       case O_DSHLd:
+               {
+                       DSHLD(inst_op1_d,inst_op2_d,inst_imm_b,LoadD,SaveD);
+                       break;
+               }
+       case O_DSHRd:
+               {
+                       DSHRD(inst_op1_d,inst_op2_d,inst_imm_b,LoadD,SaveD);
+                       break;
+               }
+
+       case t_NEGb:
+               lf_var1b=inst_op1_b;
+               inst_op1_b=lf_resb=0-inst_op1_b;
+               lflags.type=t_NEGb;
+               break;
+       case t_NEGw:
+               lf_var1w=inst_op1_w;
+               inst_op1_w=lf_resw=0-inst_op1_w;
+               lflags.type=t_NEGw;
+               break;
+       case t_NEGd:
+               lf_var1d=inst_op1_d;
+               inst_op1_d=lf_resd=0-inst_op1_d;
+               lflags.type=t_NEGd;
+               break;
+       
+       case O_NOT:
+               inst_op1_d=~inst_op1_d;
+               break;  
+               
+       /* Special instructions */
+       case O_IMULRw:
+               DIMULW(inst_op1_ws,inst_op1_ws,inst_op2_ws,LoadD,SaveD);
+               break;
+       case O_IMULRd:
+               DIMULD(inst_op1_ds,inst_op1_ds,inst_op2_ds,LoadD,SaveD);
+               break;
+       case O_MULb:
+               MULB(inst_op1_b,LoadD,0);
+               goto nextopcode;
+       case O_MULw:
+               MULW(inst_op1_w,LoadD,0);
+               goto nextopcode;
+       case O_MULd:
+               MULD(inst_op1_d,LoadD,0);
+               goto nextopcode;
+       case O_IMULb:
+               IMULB(inst_op1_b,LoadD,0);
+               goto nextopcode;
+       case O_IMULw:
+               IMULW(inst_op1_w,LoadD,0);
+               goto nextopcode;
+       case O_IMULd:
+               IMULD(inst_op1_d,LoadD,0);
+               goto nextopcode;
+       case O_DIVb:
+               DIVB(inst_op1_b,LoadD,0);
+               goto nextopcode;
+       case O_DIVw:
+               DIVW(inst_op1_w,LoadD,0);
+               goto nextopcode;
+       case O_DIVd:
+               DIVD(inst_op1_d,LoadD,0);
+               goto nextopcode;
+       case O_IDIVb:
+               IDIVB(inst_op1_b,LoadD,0);
+               goto nextopcode;
+       case O_IDIVw:
+               IDIVW(inst_op1_w,LoadD,0);
+               goto nextopcode;
+       case O_IDIVd:
+               IDIVD(inst_op1_d,LoadD,0);
+               goto nextopcode;
+       case O_AAM:
+               AAM(inst_op1_b);
+               goto nextopcode;
+       case O_AAD:
+               AAD(inst_op1_b);
+               goto nextopcode;
+
+       case O_C_O:             inst.cond=TFLG_O;       break;
+       case O_C_NO:    inst.cond=TFLG_NO;      break;
+       case O_C_B:             inst.cond=TFLG_B;       break;
+       case O_C_NB:    inst.cond=TFLG_NB;      break;
+       case O_C_Z:             inst.cond=TFLG_Z;       break;
+       case O_C_NZ:    inst.cond=TFLG_NZ;      break;
+       case O_C_BE:    inst.cond=TFLG_BE;      break;
+       case O_C_NBE:   inst.cond=TFLG_NBE;     break;
+       case O_C_S:             inst.cond=TFLG_S;       break;
+       case O_C_NS:    inst.cond=TFLG_NS;      break;
+       case O_C_P:             inst.cond=TFLG_P;       break;
+       case O_C_NP:    inst.cond=TFLG_NP;      break;
+       case O_C_L:             inst.cond=TFLG_L;       break;
+       case O_C_NL:    inst.cond=TFLG_NL;      break;
+       case O_C_LE:    inst.cond=TFLG_LE;      break;
+       case O_C_NLE:   inst.cond=TFLG_NLE;     break;
+
+       case O_ALOP:
+               reg_al=LoadMb(inst.rm_eaa);
+               goto nextopcode;
+       case O_AXOP:
+               reg_ax=LoadMw(inst.rm_eaa);
+               goto nextopcode;
+       case O_EAXOP:
+               reg_eax=LoadMd(inst.rm_eaa);
+               goto nextopcode;
+       case O_OPAL:
+               SaveMb(inst.rm_eaa,reg_al);
+               goto nextopcode;
+       case O_OPAX:
+               SaveMw(inst.rm_eaa,reg_ax);
+               goto nextopcode;
+       case O_OPEAX:
+               SaveMd(inst.rm_eaa,reg_eax);
+               goto nextopcode;
+       case O_SEGDS:
+               inst.code.extra=ds;
+               break;
+       case O_SEGES:
+               inst.code.extra=es;
+               break;
+       case O_SEGFS:
+               inst.code.extra=fs;
+               break;
+       case O_SEGGS:
+               inst.code.extra=gs;
+               break;
+       case O_SEGSS:
+               inst.code.extra=ss;
+               break;
+       
+       case O_LOOP:
+               if (inst.prefix & PREFIX_ADDR) {
+                       if (--reg_ecx) break;
+               } else {
+                       if (--reg_cx) break;
+               }
+               goto nextopcode;
+       case O_LOOPZ:
+               if (inst.prefix & PREFIX_ADDR) {
+                       if (--reg_ecx && get_ZF()) break;
+               } else {
+                       if (--reg_cx && get_ZF()) break;
+               }
+               goto nextopcode;
+       case O_LOOPNZ:
+               if (inst.prefix & PREFIX_ADDR) {
+                       if (--reg_ecx && !get_ZF()) break;
+               } else {
+                       if (--reg_cx && !get_ZF()) break;
+               }
+               goto nextopcode;
+       case O_JCXZ:
+               if (inst.prefix & PREFIX_ADDR) {
+                       if (reg_ecx) goto nextopcode;
+               } else {
+                       if (reg_cx) goto nextopcode;
+               }
+               break;
+       case O_XCHG_AX:
+               {
+                       Bit16u temp=reg_ax;
+                       reg_ax=inst_op1_w;
+                       inst_op1_w=temp;
+                       break;
+               }
+       case O_XCHG_EAX:
+               {
+                       Bit32u temp=reg_eax;
+                       reg_eax=inst_op1_d;
+                       inst_op1_d=temp;
+                       break;
+               }
+       case O_CALLNw:
+               SaveIP();
+               Push_16(reg_ip);
+               break;
+       case O_CALLNd:
+               SaveIP();
+               Push_32(reg_eip);
+               break;
+       case O_CALLFw:
+               FillFlags();
+               CPU_CALL(false,inst_op2_d,inst_op1_d,GetIP());
+               continue;
+       case O_CALLFd:
+               FillFlags();
+               CPU_CALL(true,inst_op2_d,inst_op1_d,GetIP());
+               continue;
+       case O_JMPFw:
+               FillFlags();
+               CPU_JMP(false,inst_op2_d,inst_op1_d,GetIP());
+               continue;
+       case O_JMPFd:
+               FillFlags();
+               CPU_JMP(true,inst_op2_d,inst_op1_d,GetIP());
+               continue;
+       case O_INT:
+#if C_DEBUG
+               FillFlags();
+               if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint()) 
+                       return debugCallback;
+               else if (DEBUG_IntBreakpoint(inst_op1_b)) 
+                       return debugCallback;
+#endif
+               CPU_SW_Interrupt(inst_op1_b,GetIP());
+               continue;
+       case O_INb:
+               if (CPU_IO_Exception(inst_op1_d,1)) RunException();
+               reg_al=IO_ReadB(inst_op1_d);
+               goto nextopcode;
+       case O_INw:
+               if (CPU_IO_Exception(inst_op1_d,2)) RunException();
+               reg_ax=IO_ReadW(inst_op1_d);
+               goto nextopcode;
+       case O_INd:
+               if (CPU_IO_Exception(inst_op1_d,4)) RunException();
+               reg_eax=IO_ReadD(inst_op1_d);
+               goto nextopcode;
+       case O_OUTb:
+               if (CPU_IO_Exception(inst_op1_d,1)) RunException();
+               IO_WriteB(inst_op1_d,reg_al);
+               goto nextopcode;
+       case O_OUTw:
+               if (CPU_IO_Exception(inst_op1_d,2)) RunException();
+               IO_WriteW(inst_op1_d,reg_ax);
+               goto nextopcode;
+       case O_OUTd:
+               if (CPU_IO_Exception(inst_op1_d,4)) RunException();
+               IO_WriteD(inst_op1_d,reg_eax);
+               goto nextopcode;
+       case O_CBACK:
+               FillFlags();SaveIP();
+               return inst_op1_d;
+       case O_GRP6w:
+       case O_GRP6d:
+               if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode;
+               switch (inst.rm_index) {
+               case 0x00:      /* SLDT */
+                       inst_op1_d=(Bit32u)CPU_SLDT();
+                       break;
+               case 0x01:      /* STR */
+                       inst_op1_d=(Bit32u)CPU_STR();
+                       break;
+               case 0x02:      /* LLDT */
+                       if (cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                       if (CPU_LLDT(inst_op1_d)) RunException();
+                       goto nextopcode;                /* Else value will saved */
+               case 0x03:      /* LTR */
+                       if (cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                       if (CPU_LTR(inst_op1_d)) RunException();
+                       goto nextopcode;                /* Else value will saved */
+               case 0x04:      /* VERR */
+                       CPU_VERR(inst_op1_d);
+                       goto nextopcode;                /* Else value will saved */
+               case 0x05:      /* VERW */
+                       CPU_VERW(inst_op1_d);
+                       goto nextopcode;                /* Else value will saved */
+               default:
+                       LOG(LOG_CPU,LOG_ERROR)("Group 6 Illegal subfunction %X",inst.rm_index);
+                       goto illegalopcode;
+               }
+               break;
+       case O_GRP7w:
+       case O_GRP7d:
+               switch (inst.rm_index) {
+               case 0:         /* SGDT */
+                       SaveMw(inst.rm_eaa,CPU_SGDT_limit());
+                       SaveMd(inst.rm_eaa+2,CPU_SGDT_base());
+                       goto nextopcode;
+               case 1:         /* SIDT */
+                       SaveMw(inst.rm_eaa,CPU_SIDT_limit());
+                       SaveMd(inst.rm_eaa+2,CPU_SIDT_base());
+                       goto nextopcode;
+               case 2:         /* LGDT */
+                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                       CPU_LGDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF));
+                       goto nextopcode;
+               case 3:         /* LIDT */
+                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                       CPU_LIDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF));
+                       goto nextopcode;
+               case 4:         /* SMSW */
+                       inst_op1_d=CPU_SMSW();
+                       break;
+               case 6:         /* LMSW */
+                       FillFlags();
+                       if (CPU_LMSW(inst_op1_w)) RunException();
+                       goto nextopcode;
+               case 7:         /* INVLPG */
+                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                       FillFlags();
+                       PAGING_ClearTLB();
+                       goto nextopcode;
+               default:
+                       LOG(LOG_CPU,LOG_ERROR)("Group 7 Illegal subfunction %X",inst.rm_index);
+                       goto illegalopcode;
+               }
+               break;
+       case O_M_CRx_Rd:
+               if (CPU_WRITE_CRX(inst.rm_index,inst_op1_d)) RunException();
+               break;
+       case O_M_Rd_CRx:
+               if (CPU_READ_CRX(inst.rm_index,inst_op1_d)) RunException();
+               break;
+       case O_M_DRx_Rd:
+               if (CPU_WRITE_DRX(inst.rm_index,inst_op1_d)) RunException();
+               break;
+       case O_M_Rd_DRx:
+               if (CPU_READ_DRX(inst.rm_index,inst_op1_d)) RunException();
+               break;
+       case O_M_TRx_Rd:
+               if (CPU_WRITE_TRX(inst.rm_index,inst_op1_d)) RunException();
+               break;
+       case O_M_Rd_TRx:
+               if (CPU_READ_TRX(inst.rm_index,inst_op1_d)) RunException();
+               break;
+       case O_LAR:
+               {
+                       Bitu ar=inst_op2_d;
+                       CPU_LAR(inst_op1_w,ar);
+                       inst_op1_d=(Bit32u)ar;
+               }
+               break;
+       case O_LSL:
+               {
+                       Bitu limit=inst_op2_d;
+                       CPU_LSL(inst_op1_w,limit);
+                       inst_op1_d=(Bit32u)limit;
+               }
+               break;
+       case O_ARPL:
+               {
+                       Bitu new_sel=inst_op1_d;
+                       CPU_ARPL(new_sel,inst_op2_d);
+                       inst_op1_d=(Bit32u)new_sel;
+               }
+               break;
+       case O_BSFw:
+               {
+                       FillFlags();
+                       if (!inst_op1_w) {
+                               SETFLAGBIT(ZF,true);
+                               goto nextopcode;
+                       } else {
+                               Bitu count=0;
+                               while (1) {
+                                       if (inst_op1_w & 0x1) break;
+                                       count++;inst_op1_w>>=1;
+                               }
+                               inst_op1_d=count;
+                               SETFLAGBIT(ZF,false);
+                       }
+               }
+               break;
+       case O_BSFd:
+               {
+                       FillFlags();
+                       if (!inst_op1_d) {
+                               SETFLAGBIT(ZF,true);
+                               goto nextopcode;
+                       } else {
+                               Bitu count=0;
+                               while (1) {
+                                       if (inst_op1_d & 0x1) break;
+                                       count++;inst_op1_d>>=1;
+                               }
+                               inst_op1_d=count;
+                               SETFLAGBIT(ZF,false);
+                       }
+               }
+               break;
+       case O_BSRw:
+               {
+                       FillFlags();
+                       if (!inst_op1_w) {
+                               SETFLAGBIT(ZF,true);
+                               goto nextopcode;
+                       } else {
+                               Bitu count=15;
+                               while (1) {
+                                       if (inst_op1_w & 0x8000) break;
+                                       count--;inst_op1_w<<=1;
+                               }
+                               inst_op1_d=count;
+                               SETFLAGBIT(ZF,false);
+                       }
+               }
+               break;
+       case O_BSRd:
+               {
+                       FillFlags();
+                       if (!inst_op1_d) {
+                               SETFLAGBIT(ZF,true);
+                               goto nextopcode;
+                       } else {
+                               Bitu count=31;
+                               while (1) {
+                                       if (inst_op1_d & 0x80000000) break;
+                                       count--;inst_op1_d<<=1;
+                               }
+                               inst_op1_d=count;
+                               SETFLAGBIT(ZF,false);
+                       }
+               }
+               break;
+       case O_BTw:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15))));
+               break;
+       case O_BTSw:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15))));
+               inst_op1_d|=(1 << (inst_op2_d & 15));
+               break;
+       case O_BTCw:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15))));
+               inst_op1_d^=(1 << (inst_op2_d & 15));
+               break;
+       case O_BTRw:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 15))));
+               inst_op1_d&=~(1 << (inst_op2_d & 15));
+               break;
+       case O_BTd:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31))));
+               break;
+       case O_BTSd:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31))));
+               inst_op1_d|=(1 << (inst_op2_d & 31));
+               break;
+       case O_BTCd:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31))));
+               inst_op1_d^=(1 << (inst_op2_d & 31));
+               break;
+       case O_BTRd:
+               FillFlags();
+               SETFLAGBIT(CF,(inst_op1_d & (1 << (inst_op2_d & 31))));
+               inst_op1_d&=~(1 << (inst_op2_d & 31));
+               break;
+       case O_BSWAPw:
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegalopcode;
+               BSWAPW(inst_op1_w);
+               break;
+       case O_BSWAPd:
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegalopcode;
+               BSWAPD(inst_op1_d);
+               break;
+       case O_CMPXCHG:
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486NEWSLOW) goto illegalopcode;
+               FillFlags();
+               if (inst_op1_d==reg_eax) {
+                       inst_op1_d=reg_32(inst.rm_index);
+                       if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst_op1_d);       // early write-pf
+                       SETFLAGBIT(ZF,1);
+               } else {
+                       if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst_op1_d);       // early write-pf
+                       reg_eax=inst_op1_d;
+                       SETFLAGBIT(ZF,0);
+               }
+               break;
+       case O_FPU:
+#if C_FPU
+               switch (((inst.rm>=0xc0) << 3) | inst.code.save) {
+               case 0x00:      FPU_ESC0_EA(inst.rm,inst.rm_eaa);break;
+               case 0x01:      FPU_ESC1_EA(inst.rm,inst.rm_eaa);break;
+               case 0x02:      FPU_ESC2_EA(inst.rm,inst.rm_eaa);break;
+               case 0x03:      FPU_ESC3_EA(inst.rm,inst.rm_eaa);break;
+               case 0x04:      FPU_ESC4_EA(inst.rm,inst.rm_eaa);break;
+               case 0x05:      FPU_ESC5_EA(inst.rm,inst.rm_eaa);break;
+               case 0x06:      FPU_ESC6_EA(inst.rm,inst.rm_eaa);break;
+               case 0x07:      FPU_ESC7_EA(inst.rm,inst.rm_eaa);break;
+
+               case 0x08:      FPU_ESC0_Normal(inst.rm);break;
+               case 0x09:      FPU_ESC1_Normal(inst.rm);break;
+               case 0x0a:      FPU_ESC2_Normal(inst.rm);break;
+               case 0x0b:      FPU_ESC3_Normal(inst.rm);break;
+               case 0x0c:      FPU_ESC4_Normal(inst.rm);break;
+               case 0x0d:      FPU_ESC5_Normal(inst.rm);break;
+               case 0x0e:      FPU_ESC6_Normal(inst.rm);break;
+               case 0x0f:      FPU_ESC7_Normal(inst.rm);break;
+               }
+               goto nextopcode;
+#else
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled FPU ESCAPE %d",inst.code.save);
+               goto nextopcode;
+#endif
+       case O_BOUNDw:
+               {
+                       Bit16s bound_min, bound_max;
+                       bound_min=LoadMw(inst.rm_eaa);
+                       bound_max=LoadMw(inst.rm_eaa+2);
+                       if ( (((Bit16s)inst_op1_w) < bound_min) || (((Bit16s)inst_op1_w) > bound_max) ) {
+                               EXCEPTION(5);
+                       }
+               }
+               break;
+       case 0:
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("OP:Unhandled code %d entry %X",inst.code.op,inst.entry);
+               
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/optable.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/optable.h
new file mode 100644 (file)
index 0000000..b5680e5
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Big ass opcode table normal,double, 66 normal, 66 double */
+static OpCode OpCodeTable[1024]={
+/* 0x00 - 0x07 */
+{L_MODRM       ,t_ADDb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ADDw ,S_Ew   ,M_EwGw         },
+{L_MODRM       ,t_ADDb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ADDw ,S_Gw   ,M_GwEw         },
+{L_REGbIb      ,t_ADDb ,S_REGb ,REGI_AL        },{L_REGwIw     ,t_ADDw ,S_REGw ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHw,es                     },{D_POPSEGw,0          ,0              ,es                     },
+/* 0x08 - 0x0f */
+{L_MODRM       ,t_ORb  ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ORw  ,S_Ew   ,M_EwGw         },
+{L_MODRM       ,t_ORb  ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ORw  ,S_Gw   ,M_GwEw         },
+{L_REGbIb      ,t_ORb  ,S_REGb ,REGI_AL        },{L_REGwIw     ,t_ORw  ,S_REGw ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHw,cs                     },{L_DOUBLE     ,0              ,0              ,0                      },
+
+/* 0x10 - 0x17 */
+{L_MODRM       ,t_ADCb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ADCw ,S_Ew   ,M_EwGw         },
+{L_MODRM       ,t_ADCb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ADCw ,S_Gw   ,M_GwEw         },
+{L_REGbIb      ,t_ADCb ,S_REGb ,REGI_AL        },{L_REGwIw     ,t_ADCw ,S_REGw ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHw,ss                     },{D_POPSEGw,0          ,0              ,ss                     },
+/* 0x18 - 0x1f */
+{L_MODRM       ,t_SBBb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_SBBw ,S_Ew   ,M_EwGw         },
+{L_MODRM       ,t_SBBb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_SBBw ,S_Gw   ,M_GwEw         },
+{L_REGbIb      ,t_SBBb ,S_REGb ,REGI_AL        },{L_REGwIw     ,t_SBBw ,S_REGw ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHw,ds                     },{D_POPSEGw,0          ,0              ,ds                     },
+
+/* 0x20 - 0x27 */
+{L_MODRM       ,t_ANDb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ANDw ,S_Ew   ,M_EwGw         },
+{L_MODRM       ,t_ANDb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ANDw ,S_Gw   ,M_GwEw         },
+{L_REGbIb      ,t_ANDb ,S_REGb ,REGI_AL        },{L_REGwIw     ,t_ANDw ,S_REGw ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,es                     },{D_DAA        ,0              ,0              ,0                      },
+/* 0x28 - 0x2f */
+{L_MODRM       ,t_SUBb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_SUBw ,S_Ew   ,M_EwGw         },
+{L_MODRM       ,t_SUBb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_SUBw ,S_Gw   ,M_GwEw         },
+{L_REGbIb      ,t_SUBb ,S_REGb ,REGI_AL        },{L_REGwIw     ,t_SUBw ,S_REGw ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,cs                     },{D_DAS        ,0              ,0              ,0                      },
+
+/* 0x30 - 0x37 */
+{L_MODRM       ,t_XORb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_XORw ,S_Ew   ,M_EwGw         },
+{L_MODRM       ,t_XORb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_XORw ,S_Gw   ,M_GwEw         },
+{L_REGbIb      ,t_XORb ,S_REGb ,REGI_AL        },{L_REGwIw     ,t_XORw ,S_REGw ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,ss                     },{D_AAA        ,0              ,0              ,0                      },
+/* 0x38 - 0x3f */
+{L_MODRM       ,t_CMPb ,0              ,M_EbGb         },{L_MODRM      ,t_CMPw ,0              ,M_EwGw         },
+{L_MODRM       ,t_CMPb ,0              ,M_GbEb         },{L_MODRM      ,t_CMPw ,0              ,M_GwEw         },
+{L_REGbIb      ,t_CMPb ,0              ,REGI_AL        },{L_REGwIw     ,t_CMPw ,0              ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,ds                     },{D_AAS        ,0              ,0              ,0                      },
+
+/* 0x40 - 0x47 */
+{L_REGw                ,t_INCw ,S_REGw ,REGI_AX},{L_REGw       ,t_INCw ,S_REGw ,REGI_CX},
+{L_REGw                ,t_INCw ,S_REGw ,REGI_DX},{L_REGw       ,t_INCw ,S_REGw ,REGI_BX},
+{L_REGw                ,t_INCw ,S_REGw ,REGI_SP},{L_REGw       ,t_INCw ,S_REGw ,REGI_BP},
+{L_REGw                ,t_INCw ,S_REGw ,REGI_SI},{L_REGw       ,t_INCw ,S_REGw ,REGI_DI},
+/* 0x48 - 0x4f */
+{L_REGw                ,t_DECw ,S_REGw ,REGI_AX},{L_REGw       ,t_DECw ,S_REGw ,REGI_CX},
+{L_REGw                ,t_DECw ,S_REGw ,REGI_DX},{L_REGw       ,t_DECw ,S_REGw ,REGI_BX},
+{L_REGw                ,t_DECw ,S_REGw ,REGI_SP},{L_REGw       ,t_DECw ,S_REGw ,REGI_BP},
+{L_REGw                ,t_DECw ,S_REGw ,REGI_SI},{L_REGw       ,t_DECw ,S_REGw ,REGI_DI},
+
+/* 0x50 - 0x57 */
+{L_REGw                ,0              ,S_PUSHw,REGI_AX},{L_REGw       ,0              ,S_PUSHw,REGI_CX},
+{L_REGw                ,0              ,S_PUSHw,REGI_DX},{L_REGw       ,0              ,S_PUSHw,REGI_BX},
+{L_REGw                ,0              ,S_PUSHw,REGI_SP},{L_REGw       ,0              ,S_PUSHw,REGI_BP},
+{L_REGw                ,0              ,S_PUSHw,REGI_SI},{L_REGw       ,0              ,S_PUSHw,REGI_DI},
+/* 0x58 - 0x5f */
+{L_POPw                ,0              ,S_REGw ,REGI_AX},{L_POPw       ,0              ,S_REGw ,REGI_CX},
+{L_POPw                ,0              ,S_REGw ,REGI_DX},{L_POPw       ,0              ,S_REGw ,REGI_BX},
+{L_POPw                ,0              ,S_REGw ,REGI_SP},{L_POPw       ,0              ,S_REGw ,REGI_BP},
+{L_POPw                ,0              ,S_REGw ,REGI_SI},{L_POPw       ,0              ,S_REGw ,REGI_DI},
+
+
+/* 0x60 - 0x67 */
+{D_PUSHAw      ,0                      ,0              ,0              },{D_POPAw      ,0                      ,0              ,0              },
+{L_MODRM       ,O_BOUNDw       ,0              ,M_Gw   },{L_MODRM_NVM  ,O_ARPL         ,S_Ew   ,M_EwGw },
+{L_PRESEG      ,0                      ,0              ,fs             },{L_PRESEG     ,0                      ,0              ,gs             },
+{L_PREOP       ,0                      ,0              ,0              },{L_PREADD     ,0                      ,0              ,0              },
+/* 0x68 - 0x6f */
+{L_Iw          ,0                      ,S_PUSHw,0              },{L_MODRM      ,O_IMULRw       ,S_Gw   ,M_EwxIwx},
+{L_Ibx         ,0                      ,S_PUSHw,0              },{L_MODRM      ,O_IMULRw       ,S_Gw   ,M_EwxIbx},
+{L_STRING      ,R_INSB         ,0              ,0              },{L_STRING     ,R_INSW         ,0              ,0              },
+{L_STRING      ,R_OUTSB        ,0              ,0              },{L_STRING     ,R_OUTSW        ,0              ,0              },
+
+
+/* 0x70 - 0x77 */
+{L_Ibx         ,O_C_O          ,S_C_AIPw,0             },{L_Ibx        ,O_C_NO         ,S_C_AIPw,0             },
+{L_Ibx         ,O_C_B          ,S_C_AIPw,0             },{L_Ibx        ,O_C_NB         ,S_C_AIPw,0             },
+{L_Ibx         ,O_C_Z          ,S_C_AIPw,0             },{L_Ibx        ,O_C_NZ         ,S_C_AIPw,0             },
+{L_Ibx         ,O_C_BE         ,S_C_AIPw,0             },{L_Ibx        ,O_C_NBE        ,S_C_AIPw,0             },
+/* 0x78 - 0x7f */
+{L_Ibx         ,O_C_S          ,S_C_AIPw,0             },{L_Ibx        ,O_C_NS         ,S_C_AIPw,0             },
+{L_Ibx         ,O_C_P          ,S_C_AIPw,0             },{L_Ibx        ,O_C_NP         ,S_C_AIPw,0             },
+{L_Ibx         ,O_C_L          ,S_C_AIPw,0             },{L_Ibx        ,O_C_NL         ,S_C_AIPw,0             },
+{L_Ibx         ,O_C_LE         ,S_C_AIPw,0             },{L_Ibx        ,O_C_NLE        ,S_C_AIPw,0             },
+
+
+/* 0x80 - 0x87 */
+{L_MODRM       ,0                      ,0              ,M_GRP  },{L_MODRM      ,1                      ,0              ,M_GRP  },
+{L_MODRM       ,0                      ,0              ,M_GRP  },{L_MODRM      ,3                      ,0              ,M_GRP  },
+{L_MODRM       ,t_TESTb        ,0              ,M_EbGb },{L_MODRM      ,t_TESTw        ,0              ,M_EwGw },
+{L_MODRM       ,0                      ,S_EbGb ,M_GbEb },{L_MODRM      ,0                      ,S_EwGw ,M_GwEw },
+/* 0x88 - 0x8f */
+{L_MODRM               ,0              ,S_Eb   ,M_Gb   },{L_MODRM      ,0                      ,S_Ew   ,M_Gw   },
+{L_MODRM               ,0              ,S_Gb   ,M_Eb   },{L_MODRM      ,0                      ,S_Gw   ,M_Ew   },
+{L_MODRM               ,0              ,S_Ew   ,M_SEG  },{L_MODRM      ,0                      ,S_Gw   ,M_EA   },
+{L_MODRM               ,0              ,S_SEGm ,M_Ew   },{L_POPwRM     ,0                      ,S_Ew   ,M_None },
+
+/* 0x90 - 0x97 */
+{D_NOP         ,0                      ,0              ,0              },{L_REGw       ,O_XCHG_AX      ,S_REGw ,REGI_CX},
+{L_REGw                ,O_XCHG_AX      ,S_REGw ,REGI_DX},{L_REGw       ,O_XCHG_AX      ,S_REGw ,REGI_BX},
+{L_REGw                ,O_XCHG_AX      ,S_REGw ,REGI_SP},{L_REGw       ,O_XCHG_AX      ,S_REGw ,REGI_BP},
+{L_REGw                ,O_XCHG_AX      ,S_REGw ,REGI_SI},{L_REGw       ,O_XCHG_AX      ,S_REGw ,REGI_DI},
+/* 0x98 - 0x9f */
+{D_CBW         ,0                      ,0              ,0              },{D_CWD        ,0                      ,0              ,0              },
+{L_Ifw         ,O_CALLFw       ,0              ,0              },{D_WAIT       ,0                      ,0              ,0              },
+{D_PUSHF       ,0                      ,0              ,0              },{D_POPF       ,0                      ,0              ,0              },
+{D_SAHF                ,0                      ,0              ,0              },{D_LAHF       ,0                      ,0              ,0              },
+
+
+/* 0xa0 - 0xa7 */
+{L_OP          ,O_ALOP         ,0              ,0              },{L_OP         ,O_AXOP         ,0              ,0              },
+{L_OP          ,O_OPAL         ,0              ,0              },{L_OP         ,O_OPAX         ,0              ,0              },
+{L_STRING      ,R_MOVSB        ,0              ,0              },{L_STRING     ,R_MOVSW        ,0              ,0              },
+{L_STRING      ,R_CMPSB        ,0              ,0              },{L_STRING     ,R_CMPSW        ,0              ,0              },
+/* 0xa8 - 0xaf */
+{L_REGbIb      ,t_TESTb        ,0              ,REGI_AL},{L_REGwIw     ,t_TESTw        ,0              ,REGI_AX},
+{L_STRING      ,R_STOSB        ,0              ,0              },{L_STRING     ,R_STOSW        ,0              ,0              },
+{L_STRING      ,R_LODSB        ,0              ,0              },{L_STRING     ,R_LODSW        ,0              ,0              },
+{L_STRING      ,R_SCASB        ,0              ,0              },{L_STRING     ,R_SCASW        ,0              ,0              },
+
+/* 0xb0        - 0xb7 */
+{L_Ib          ,0                      ,S_REGb ,REGI_AL},{L_Ib ,0                      ,S_REGb ,REGI_CL},
+{L_Ib          ,0                      ,S_REGb ,REGI_DL},{L_Ib ,0                      ,S_REGb ,REGI_BL},
+{L_Ib          ,0                      ,S_REGb ,REGI_AH},{L_Ib ,0                      ,S_REGb ,REGI_CH},
+{L_Ib          ,0                      ,S_REGb ,REGI_DH},{L_Ib ,0                      ,S_REGb ,REGI_BH},
+/* 0xb8 - 0xbf */
+{L_Iw          ,0                      ,S_REGw ,REGI_AX},{L_Iw ,0                      ,S_REGw ,REGI_CX},
+{L_Iw          ,0                      ,S_REGw ,REGI_DX},{L_Iw ,0                      ,S_REGw ,REGI_BX},
+{L_Iw          ,0                      ,S_REGw ,REGI_SP},{L_Iw ,0                      ,S_REGw ,REGI_BP},
+{L_Iw          ,0                      ,S_REGw ,REGI_SI},{L_Iw ,0                      ,S_REGw ,REGI_DI},
+
+/* 0xc0 - 0xc7 */
+{L_MODRM       ,5                      ,0      ,M_GRP_Ib       },{L_MODRM      ,6                      ,0      ,M_GRP_Ib       },
+{L_POPw                ,0                      ,S_IPIw ,0              },{L_POPw       ,0                      ,S_IP   ,0              },
+{L_MODRM       ,O_SEGES        ,S_SEGGw,M_Efw  },{L_MODRM      ,O_SEGDS        ,S_SEGGw,M_Efw  },
+{L_MODRM       ,0                      ,S_Eb   ,M_Ib   },{L_MODRM      ,0                      ,S_Ew   ,M_Iw   },
+/* 0xc8 - 0xcf */
+{D_ENTERw      ,0                      ,0              ,0              },{D_LEAVEw     ,0                      ,0              ,0              },
+{D_RETFwIw     ,0                      ,0              ,0              },{D_RETFw      ,0                      ,0              ,0              },
+{L_VAL         ,O_INT          ,0              ,3              },{L_Ib         ,O_INT          ,0              ,0              },
+{L_INTO                ,O_INT          ,0              ,0              },{D_IRETw      ,0                      ,0              ,0              },
+
+/* 0xd0 - 0xd7 */
+{L_MODRM       ,5                      ,0      ,M_GRP_1        },{L_MODRM      ,6                      ,0      ,M_GRP_1        },
+{L_MODRM       ,5                      ,0      ,M_GRP_CL       },{L_MODRM      ,6                      ,0      ,M_GRP_CL       },
+{L_Ib          ,O_AAM          ,0              ,0              },{L_Ib         ,O_AAD          ,0              ,0              },
+{D_SETALC      ,0                      ,0              ,0              },{D_XLAT       ,0                      ,0              ,0              },
+//TODO FPU
+/* 0xd8 - 0xdf */
+{L_MODRM       ,O_FPU          ,0              ,0              },{L_MODRM      ,O_FPU          ,1              ,0              },
+{L_MODRM       ,O_FPU          ,2              ,0              },{L_MODRM      ,O_FPU          ,3              ,0              },
+{L_MODRM       ,O_FPU          ,4              ,0              },{L_MODRM      ,O_FPU          ,5              ,0              },
+{L_MODRM       ,O_FPU          ,6              ,0              },{L_MODRM      ,O_FPU          ,7              ,0              },
+
+/* 0xe0 - 0xe7 */
+{L_Ibx         ,O_LOOPNZ       ,S_AIPw ,0              },{L_Ibx        ,O_LOOPZ        ,S_AIPw ,0              },
+{L_Ibx         ,O_LOOP         ,S_AIPw ,0              },{L_Ibx        ,O_JCXZ         ,S_AIPw ,0              },
+{L_Ib          ,O_INb          ,0              ,0              },{L_Ib         ,O_INw          ,0              ,0              },
+{L_Ib          ,O_OUTb         ,0              ,0              },{L_Ib         ,O_OUTw         ,0              ,0              },
+/* 0xe8 - 0xef */
+{L_Iw          ,O_CALLNw       ,S_AIPw ,0              },{L_Iwx        ,0                      ,S_AIPw ,0              },
+{L_Ifw         ,O_JMPFw        ,0              ,0              },{L_Ibx        ,0                      ,S_AIPw ,0              },
+{L_REGw                ,O_INb          ,0              ,REGI_DX},{L_REGw       ,O_INw          ,0              ,REGI_DX},
+{L_REGw                ,O_OUTb         ,0              ,REGI_DX},{L_REGw       ,O_OUTw         ,0              ,REGI_DX},
+
+/* 0xf0 - 0xf7 */
+{D_LOCK                ,0                      ,0              ,0              },{D_ICEBP      ,0                      ,0              ,0              },
+{L_PREREPNE    ,0                      ,0              ,0              },{L_PREREP     ,0                      ,0              ,0              },
+{D_HLT         ,0                      ,0              ,0              },{D_CMC        ,0                      ,0              ,0              },
+{L_MODRM       ,8                      ,0              ,M_GRP  },{L_MODRM      ,9                      ,0              ,M_GRP  },
+/* 0xf8 - 0xff */
+{D_CLC         ,0                      ,0              ,0              },{D_STC        ,0                      ,0              ,0              },
+{D_CLI         ,0                      ,0              ,0              },{D_STI        ,0                      ,0              ,0              },
+{D_CLD         ,0                      ,0              ,0              },{D_STD        ,0                      ,0              ,0              },
+{L_MODRM       ,0xb            ,0              ,M_GRP  },{L_MODRM      ,0xc            ,0              ,M_GRP  },
+
+/* 0x100 - 0x107 */
+{L_MODRM       ,O_GRP6w        ,S_Ew   ,M_Ew   },{L_MODRM      ,O_GRP7w        ,S_Ew   ,M_Ew   },
+{L_MODRM_NVM   ,O_LAR          ,S_Gw   ,M_EwGw },{L_MODRM_NVM  ,O_LSL          ,S_Gw   ,M_EwGw },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{D_CLTS                ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+/* 0x108 - 0x10f */
+{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              },
+
+/* 0x110 - 0x117 */
+{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              },
+/* 0x118 - 0x11f */
+{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              },
+
+/* 0x120 - 0x127 */
+{L_MODRM       ,O_M_Rd_CRx     ,S_Ed   ,0              },{L_MODRM      ,O_M_Rd_DRx     ,S_Ed   ,0              },
+{L_MODRM       ,O_M_CRx_Rd     ,0              ,M_Ed   },{L_MODRM      ,O_M_DRx_Rd     ,0              ,M_Ed   },
+{L_MODRM       ,O_M_Rd_TRx     ,S_Ed   ,0              },{0            ,0                      ,0              ,0              },
+{L_MODRM       ,O_M_TRx_Rd     ,0              ,M_Ed   },{0            ,0                      ,0              ,0              },
+
+/* 0x128 - 0x12f */
+{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              },
+
+/* 0x130 - 0x137 */
+{0                     ,0                      ,0              ,0              },{D_RDTSC      ,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              },
+/* 0x138 - 0x13f */
+{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              },
+
+/* 0x140 - 0x147 */
+{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              },
+/* 0x148 - 0x14f */
+{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              },
+
+/* 0x150 - 0x157 */
+{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              },
+/* 0x158 - 0x15f */
+{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              },
+
+/* 0x160 - 0x167 */
+{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              },
+/* 0x168 - 0x16f */
+{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              },
+
+
+/* 0x170 - 0x177 */
+{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              },
+/* 0x178 - 0x17f */
+{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              },
+
+/* 0x180 - 0x187 */
+{L_Iwx         ,O_C_O          ,S_C_AIPw,0             },{L_Iwx        ,O_C_NO         ,S_C_AIPw,0             },
+{L_Iwx         ,O_C_B          ,S_C_AIPw,0             },{L_Iwx        ,O_C_NB         ,S_C_AIPw,0             },
+{L_Iwx         ,O_C_Z          ,S_C_AIPw,0             },{L_Iwx        ,O_C_NZ         ,S_C_AIPw,0             },
+{L_Iwx         ,O_C_BE         ,S_C_AIPw,0             },{L_Iwx        ,O_C_NBE        ,S_C_AIPw,0             },
+/* 0x188 - 0x18f */
+{L_Iwx         ,O_C_S          ,S_C_AIPw,0             },{L_Iwx        ,O_C_NS         ,S_C_AIPw,0             },
+{L_Iwx         ,O_C_P          ,S_C_AIPw,0             },{L_Iwx        ,O_C_NP         ,S_C_AIPw,0             },
+{L_Iwx         ,O_C_L          ,S_C_AIPw,0             },{L_Iwx        ,O_C_NL         ,S_C_AIPw,0             },
+{L_Iwx         ,O_C_LE         ,S_C_AIPw,0             },{L_Iwx        ,O_C_NLE        ,S_C_AIPw,0             },
+
+/* 0x190 - 0x197 */
+{L_MODRM       ,O_C_O          ,S_C_Eb,0               },{L_MODRM      ,O_C_NO         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_B          ,S_C_Eb,0               },{L_MODRM      ,O_C_NB         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_Z          ,S_C_Eb,0               },{L_MODRM      ,O_C_NZ         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_BE         ,S_C_Eb,0               },{L_MODRM      ,O_C_NBE        ,S_C_Eb,0               },
+/* 0x198 - 0x19f */
+{L_MODRM       ,O_C_S          ,S_C_Eb,0               },{L_MODRM      ,O_C_NS         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_P          ,S_C_Eb,0               },{L_MODRM      ,O_C_NP         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_L          ,S_C_Eb,0               },{L_MODRM      ,O_C_NL         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_LE         ,S_C_Eb,0               },{L_MODRM      ,O_C_NLE        ,S_C_Eb,0               },
+
+/* 0x1a0 - 0x1a7 */
+{L_SEG         ,0              ,S_PUSHw        ,fs             },{D_POPSEGw,0          ,0              ,fs                     },
+{D_CPUID       ,0                      ,0              ,0              },{L_MODRM      ,O_BTw          ,S_Ew   ,M_EwGwt        },
+{L_MODRM       ,O_DSHLw        ,S_Ew,M_EwGwIb  },{L_MODRM      ,O_DSHLw        ,S_Ew   ,M_EwGwCL       },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+/* 0x1a8 - 0x1af */
+{L_SEG         ,0              ,S_PUSHw        ,gs             },{D_POPSEGw,0          ,0              ,gs                     },
+{0                     ,0                      ,0              ,0              },{L_MODRM      ,O_BTSw         ,S_Ew   ,M_EwGwt        },
+{L_MODRM       ,O_DSHRw        ,S_Ew,M_EwGwIb  },{L_MODRM      ,O_DSHRw        ,S_Ew   ,M_EwGwCL       },
+{0                     ,0                      ,0              ,0              },{L_MODRM      ,O_IMULRw       ,S_Gw   ,M_EwxGwx       },
+
+/* 0x1b0 - 0x1b7 */
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{L_MODRM       ,O_SEGSS        ,S_SEGGw,M_Efw  },{L_MODRM      ,O_BTRw         ,S_Ew   ,M_EwGwt        },
+{L_MODRM       ,O_SEGFS        ,S_SEGGw,M_Efw  },{L_MODRM      ,O_SEGGS        ,S_SEGGw,M_Efw  },
+{L_MODRM       ,0                      ,S_Gw   ,M_Eb   },{L_MODRM      ,0                      ,S_Gw   ,M_Ew   },
+/* 0x1b8 - 0x1bf */
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{L_MODRM       ,0xe            ,0              ,M_GRP  },{L_MODRM      ,O_BTCw         ,S_Ew   ,M_EwGwt        },
+{L_MODRM       ,O_BSFw         ,S_Gw   ,M_Ew   },{L_MODRM      ,O_BSRw         ,S_Gw   ,M_Ew   },
+{L_MODRM       ,0                      ,S_Gw   ,M_Ebx  },{L_MODRM      ,0                      ,S_Gw   ,M_Ewx  },
+
+/* 0x1c0 - 0x1cc */
+{L_MODRM               ,t_ADDb                 ,S_EbGb         ,M_GbEb         },{L_MODRM              ,t_ADDw         ,S_EwGw         ,M_GwEw },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+/* 0x1c8 - 0x1cf */
+{L_REGw                ,O_BSWAPw       ,S_REGw ,REGI_AX},{L_REGw       ,O_BSWAPw       ,S_REGw ,REGI_CX},
+{L_REGw                ,O_BSWAPw       ,S_REGw ,REGI_DX},{L_REGw       ,O_BSWAPw       ,S_REGw ,REGI_BX},
+{L_REGw                ,O_BSWAPw       ,S_REGw ,REGI_SP},{L_REGw       ,O_BSWAPw       ,S_REGw ,REGI_BP},
+{L_REGw                ,O_BSWAPw       ,S_REGw ,REGI_SI},{L_REGw       ,O_BSWAPw       ,S_REGw ,REGI_DI},
+
+/* 0x1d0 - 0x1d7 */
+{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              },
+/* 0x1d8 - 0x1df */
+{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              },
+
+/* 0x1e0 - 0x1ee */
+{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              },
+/* 0x1e8 - 0x1ef */
+{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              },
+
+/* 0x1f0 - 0x1fc */
+{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              },
+/* 0x1f8 - 0x1ff */
+{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              },
+
+
+/* 0x200 - 0x207 */
+{L_MODRM       ,t_ADDb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ADDd ,S_Ed   ,M_EdGd         },
+{L_MODRM       ,t_ADDb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ADDd ,S_Gd   ,M_GdEd         },
+{L_REGbIb      ,t_ADDb ,S_REGb ,REGI_AL        },{L_REGdId     ,t_ADDd ,S_REGd ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHd,es                     },{D_POPSEGd,0          ,0              ,es                     },
+/* 0x208 - 0x20f */
+{L_MODRM       ,t_ORb  ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ORd  ,S_Ed   ,M_EdGd         },
+{L_MODRM       ,t_ORb  ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ORd  ,S_Gd   ,M_GdEd         },
+{L_REGbIb      ,t_ORb  ,S_REGb ,REGI_AL        },{L_REGdId     ,t_ORd  ,S_REGd ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHd,cs                     },{L_DOUBLE     ,0              ,0              ,0                      },
+
+/* 0x210 - 0x217 */
+{L_MODRM       ,t_ADCb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ADCd ,S_Ed   ,M_EdGd         },
+{L_MODRM       ,t_ADCb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ADCd ,S_Gd   ,M_GdEd         },
+{L_REGbIb      ,t_ADCb ,S_REGb ,REGI_AL        },{L_REGdId     ,t_ADCd ,S_REGd ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHd,ss                     },{D_POPSEGd,0          ,0              ,ss                     },
+/* 0x218 - 0x21f */
+{L_MODRM       ,t_SBBb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_SBBd ,S_Ed   ,M_EdGd         },
+{L_MODRM       ,t_SBBb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_SBBd ,S_Gd   ,M_GdEd         },
+{L_REGbIb      ,t_SBBb ,S_REGb ,REGI_AL        },{L_REGdId     ,t_SBBd ,S_REGd ,REGI_AX        },
+{L_SEG         ,0              ,S_PUSHd,ds                     },{D_POPSEGd,0          ,0              ,ds                     },
+
+/* 0x220 - 0x227 */
+{L_MODRM       ,t_ANDb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_ANDd ,S_Ed   ,M_EdGd         },
+{L_MODRM       ,t_ANDb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_ANDd ,S_Gd   ,M_GdEd         },
+{L_REGbIb      ,t_ANDb ,S_REGb ,REGI_AL        },{L_REGdId     ,t_ANDd ,S_REGd ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,es                     },{D_DAA        ,0              ,0              ,0                      },
+/* 0x228 - 0x22f */
+{L_MODRM       ,t_SUBb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_SUBd ,S_Ed   ,M_EdGd         },
+{L_MODRM       ,t_SUBb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_SUBd ,S_Gd   ,M_GdEd         },
+{L_REGbIb      ,t_SUBb ,S_REGb ,REGI_AL        },{L_REGdId     ,t_SUBd ,S_REGd ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,cs                     },{D_DAS        ,0              ,0              ,0                      },
+
+/* 0x230 - 0x237 */
+{L_MODRM       ,t_XORb ,S_Eb   ,M_EbGb         },{L_MODRM      ,t_XORd ,S_Ed   ,M_EdGd         },
+{L_MODRM       ,t_XORb ,S_Gb   ,M_GbEb         },{L_MODRM      ,t_XORd ,S_Gd   ,M_GdEd         },
+{L_REGbIb      ,t_XORb ,S_REGb ,REGI_AL        },{L_REGdId     ,t_XORd ,S_REGd ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,ss                     },{D_AAA        ,0              ,0              ,0                      },
+/* 0x238 - 0x23f */
+{L_MODRM       ,t_CMPb ,0              ,M_EbGb         },{L_MODRM      ,t_CMPd ,0              ,M_EdGd         },
+{L_MODRM       ,t_CMPb ,0              ,M_GbEb         },{L_MODRM      ,t_CMPd ,0              ,M_GdEd         },
+{L_REGbIb      ,t_CMPb ,0              ,REGI_AL        },{L_REGdId     ,t_CMPd ,0              ,REGI_AX        },
+{L_PRESEG      ,0              ,0              ,ds                     },{D_AAS        ,0              ,0              ,0                      },
+
+/* 0x240 - 0x247 */
+{L_REGd                ,t_INCd ,S_REGd ,REGI_AX},{L_REGd       ,t_INCd ,S_REGd ,REGI_CX},
+{L_REGd                ,t_INCd ,S_REGd ,REGI_DX},{L_REGd       ,t_INCd ,S_REGd ,REGI_BX},
+{L_REGd                ,t_INCd ,S_REGd ,REGI_SP},{L_REGd       ,t_INCd ,S_REGd ,REGI_BP},
+{L_REGd                ,t_INCd ,S_REGd ,REGI_SI},{L_REGd       ,t_INCd ,S_REGd ,REGI_DI},
+/* 0x248 - 0x24f */
+{L_REGd                ,t_DECd ,S_REGd ,REGI_AX},{L_REGd       ,t_DECd ,S_REGd ,REGI_CX},
+{L_REGd                ,t_DECd ,S_REGd ,REGI_DX},{L_REGd       ,t_DECd ,S_REGd ,REGI_BX},
+{L_REGd                ,t_DECd ,S_REGd ,REGI_SP},{L_REGd       ,t_DECd ,S_REGd ,REGI_BP},
+{L_REGd                ,t_DECd ,S_REGd ,REGI_SI},{L_REGd       ,t_DECd ,S_REGd ,REGI_DI},
+
+/* 0x250 - 0x257 */
+{L_REGd                ,0              ,S_PUSHd,REGI_AX},{L_REGd       ,0              ,S_PUSHd,REGI_CX},
+{L_REGd                ,0              ,S_PUSHd,REGI_DX},{L_REGd       ,0              ,S_PUSHd,REGI_BX},
+{L_REGd                ,0              ,S_PUSHd,REGI_SP},{L_REGd       ,0              ,S_PUSHd,REGI_BP},
+{L_REGd                ,0              ,S_PUSHd,REGI_SI},{L_REGd       ,0              ,S_PUSHd,REGI_DI},
+/* 0x258 - 0x25f */
+{L_POPd                ,0              ,S_REGd ,REGI_AX},{L_POPd       ,0              ,S_REGd ,REGI_CX},
+{L_POPd                ,0              ,S_REGd ,REGI_DX},{L_POPd       ,0              ,S_REGd ,REGI_BX},
+{L_POPd                ,0              ,S_REGd ,REGI_SP},{L_POPd       ,0              ,S_REGd ,REGI_BP},
+{L_POPd                ,0              ,S_REGd ,REGI_SI},{L_POPd       ,0              ,S_REGd ,REGI_DI},
+
+/* 0x260 - 0x267 */
+{D_PUSHAd      ,0                      ,0              ,0              },{D_POPAd      ,0                      ,0              ,0              },
+{L_MODRM       ,O_BOUNDd       ,0              ,0              },{0            ,0                      ,0              ,0              },
+{L_PRESEG      ,0                      ,0              ,fs             },{L_PRESEG     ,0                      ,0              ,gs             },
+{L_PREOP       ,0                      ,0              ,0              },{L_PREADD     ,0                      ,0              ,0              },
+/* 0x268 - 0x26f */
+{L_Id          ,0                      ,S_PUSHd,0              },{L_MODRM      ,O_IMULRd       ,S_Gd   ,M_EdId},
+{L_Ibx         ,0                      ,S_PUSHd,0              },{L_MODRM      ,O_IMULRd       ,S_Gd   ,M_EdIbx},
+{L_STRING      ,R_INSB         ,0              ,0              },{L_STRING     ,R_INSD         ,0              ,0              },
+{L_STRING      ,R_OUTSB        ,0              ,0              },{L_STRING     ,R_OUTSD        ,0              ,0              },
+
+/* 0x270 - 0x277 */
+{L_Ibx         ,O_C_O          ,S_C_AIPd,0             },{L_Ibx        ,O_C_NO         ,S_C_AIPd,0             },
+{L_Ibx         ,O_C_B          ,S_C_AIPd,0             },{L_Ibx        ,O_C_NB         ,S_C_AIPd,0             },
+{L_Ibx         ,O_C_Z          ,S_C_AIPd,0             },{L_Ibx        ,O_C_NZ         ,S_C_AIPd,0             },
+{L_Ibx         ,O_C_BE         ,S_C_AIPd,0             },{L_Ibx        ,O_C_NBE        ,S_C_AIPd,0             },
+/* 0x278 - 0x27f */
+{L_Ibx         ,O_C_S          ,S_C_AIPd,0             },{L_Ibx        ,O_C_NS         ,S_C_AIPd,0             },
+{L_Ibx         ,O_C_P          ,S_C_AIPd,0             },{L_Ibx        ,O_C_NP         ,S_C_AIPd,0             },
+{L_Ibx         ,O_C_L          ,S_C_AIPd,0             },{L_Ibx        ,O_C_NL         ,S_C_AIPd,0             },
+{L_Ibx         ,O_C_LE         ,S_C_AIPd,0             },{L_Ibx        ,O_C_NLE        ,S_C_AIPd,0             },
+
+/* 0x280 - 0x287 */
+{L_MODRM       ,0                      ,0              ,M_GRP  },{L_MODRM      ,2                      ,0              ,M_GRP  },
+{L_MODRM       ,0                      ,0              ,M_GRP  },{L_MODRM      ,4                      ,0              ,M_GRP  },
+{L_MODRM       ,t_TESTb        ,0              ,M_EbGb },{L_MODRM      ,t_TESTd        ,0              ,M_EdGd },
+{L_MODRM       ,0                      ,S_EbGb ,M_GbEb },{L_MODRM      ,0                      ,S_EdGd ,M_GdEd },
+/* 0x288 - 0x28f */
+{L_MODRM               ,0              ,S_Eb   ,M_Gb   },{L_MODRM      ,0                      ,S_Ed   ,M_Gd   },
+{L_MODRM               ,0              ,S_Gb   ,M_Eb   },{L_MODRM      ,0                      ,S_Gd   ,M_Ed   },
+{L_MODRM               ,0              ,S_EdMw ,M_SEG  },{L_MODRM      ,0                      ,S_Gd   ,M_EA   },
+{L_MODRM               ,0              ,S_SEGm ,M_Ew   },{L_POPdRM     ,0                      ,S_Ed   ,M_None },
+
+/* 0x290 - 0x297 */
+{D_NOP         ,0                      ,0              ,0              },{L_REGd       ,O_XCHG_EAX     ,S_REGd ,REGI_CX},
+{L_REGd                ,O_XCHG_EAX     ,S_REGd ,REGI_DX},{L_REGd       ,O_XCHG_EAX     ,S_REGd ,REGI_BX},
+{L_REGd                ,O_XCHG_EAX     ,S_REGd ,REGI_SP},{L_REGd       ,O_XCHG_EAX     ,S_REGd ,REGI_BP},
+{L_REGd                ,O_XCHG_EAX     ,S_REGd ,REGI_SI},{L_REGd       ,O_XCHG_EAX     ,S_REGd ,REGI_DI},
+/* 0x298 - 0x29f */
+{D_CWDE                ,0                      ,0              ,0              },{D_CDQ        ,0                      ,0              ,0              },
+{L_Ifd         ,O_CALLFd       ,0              ,0              },{D_WAIT       ,0                      ,0              ,0              },
+{D_PUSHF       ,0                      ,0              ,true   },{D_POPF       ,0                      ,0              ,true   },
+{D_SAHF                ,0                      ,0              ,0              },{D_LAHF       ,0                      ,0              ,0              },
+
+/* 0x2a0 - 0x2a7 */
+{L_OP          ,O_ALOP         ,0              ,0              },{L_OP         ,O_EAXOP        ,0              ,0              },
+{L_OP          ,O_OPAL         ,0              ,0              },{L_OP         ,O_OPEAX        ,0              ,0              },
+{L_STRING      ,R_MOVSB        ,0              ,0              },{L_STRING     ,R_MOVSD        ,0              ,0              },
+{L_STRING      ,R_CMPSB        ,0              ,0              },{L_STRING     ,R_CMPSD        ,0              ,0              },
+/* 0x2a8 - 0x2af */
+{L_REGbIb      ,t_TESTb        ,0              ,REGI_AL},{L_REGdId     ,t_TESTd        ,0              ,REGI_AX},
+{L_STRING      ,R_STOSB        ,0              ,0              },{L_STRING     ,R_STOSD        ,0              ,0              },
+{L_STRING      ,R_LODSB        ,0              ,0              },{L_STRING     ,R_LODSD        ,0              ,0              },
+{L_STRING      ,R_SCASB        ,0              ,0              },{L_STRING     ,R_SCASD        ,0              ,0              },
+
+/* 0x2b0       - 0x2b7 */
+{L_Ib          ,0                      ,S_REGb ,REGI_AL},{L_Ib ,0                      ,S_REGb ,REGI_CL},
+{L_Ib          ,0                      ,S_REGb ,REGI_DL},{L_Ib ,0                      ,S_REGb ,REGI_BL},
+{L_Ib          ,0                      ,S_REGb ,REGI_AH},{L_Ib ,0                      ,S_REGb ,REGI_CH},
+{L_Ib          ,0                      ,S_REGb ,REGI_DH},{L_Ib ,0                      ,S_REGb ,REGI_BH},
+/* 0x2b8 - 0x2bf */
+{L_Id          ,0                      ,S_REGd ,REGI_AX},{L_Id ,0                      ,S_REGd ,REGI_CX},
+{L_Id          ,0                      ,S_REGd ,REGI_DX},{L_Id ,0                      ,S_REGd ,REGI_BX},
+{L_Id          ,0                      ,S_REGd ,REGI_SP},{L_Id ,0                      ,S_REGd ,REGI_BP},
+{L_Id          ,0                      ,S_REGd ,REGI_SI},{L_Id ,0                      ,S_REGd ,REGI_DI},
+
+/* 0x2c0 - 0x2c7 */
+{L_MODRM       ,5                      ,0      ,M_GRP_Ib       },{L_MODRM      ,7                      ,0      ,M_GRP_Ib       },
+{L_POPd                ,0                      ,S_IPIw ,0              },{L_POPd       ,0                      ,S_IP   ,0              },
+{L_MODRM       ,O_SEGES        ,S_SEGGd,M_Efd  },{L_MODRM      ,O_SEGDS        ,S_SEGGd,M_Efd  },
+{L_MODRM       ,0                      ,S_Eb   ,M_Ib   },{L_MODRM      ,0                      ,S_Ed   ,M_Id   },
+/* 0x2c8 - 0x2cf */
+{D_ENTERd      ,0                      ,0              ,0              },{D_LEAVEd     ,0                      ,0              ,0              },
+{D_RETFdIw     ,0                      ,0              ,0              },{D_RETFd      ,0                      ,0              ,0              },
+{L_VAL         ,O_INT          ,0              ,3              },{L_Ib         ,O_INT          ,0              ,0              },
+{L_INTO                ,O_INT          ,0              ,0              },{D_IRETd      ,0                      ,0              ,0              },
+
+/* 0x2d0 - 0x2d7 */
+{L_MODRM       ,5                      ,0      ,M_GRP_1        },{L_MODRM      ,7                      ,0      ,M_GRP_1        },
+{L_MODRM       ,5                      ,0      ,M_GRP_CL       },{L_MODRM      ,7                      ,0      ,M_GRP_CL       },
+{L_Ib          ,O_AAM          ,0              ,0              },{L_Ib         ,O_AAD          ,0              ,0              },
+{D_SETALC      ,0                      ,0              ,0              },{D_XLAT       ,0                      ,0              ,0              },
+/* 0x2d8 - 0x2df */
+{L_MODRM       ,O_FPU          ,0              ,0              },{L_MODRM      ,O_FPU          ,1              ,0              },
+{L_MODRM       ,O_FPU          ,2              ,0              },{L_MODRM      ,O_FPU          ,3              ,0              },
+{L_MODRM       ,O_FPU          ,4              ,0              },{L_MODRM      ,O_FPU          ,5              ,0              },
+{L_MODRM       ,O_FPU          ,6              ,0              },{L_MODRM      ,O_FPU          ,7              ,0              },
+
+/* 0x2e0 - 0x2e7 */
+{L_Ibx         ,O_LOOPNZ       ,S_AIPd ,0              },{L_Ibx        ,O_LOOPZ        ,S_AIPd ,0              },
+{L_Ibx         ,O_LOOP         ,S_AIPd ,0              },{L_Ibx        ,O_JCXZ         ,S_AIPd ,0              },
+{L_Ib          ,O_INb          ,0              ,0              },{L_Ib         ,O_INd          ,0              ,0              },
+{L_Ib          ,O_OUTb         ,0              ,0              },{L_Ib         ,O_OUTd         ,0              ,0              },
+/* 0x2e8 - 0x2ef */
+{L_Id          ,O_CALLNd       ,S_AIPd ,0              },{L_Idx        ,0                      ,S_AIPd ,0              },
+{L_Ifd         ,O_JMPFd        ,0              ,0              },{L_Ibx        ,0                      ,S_AIPd ,0              },
+{L_REGw                ,O_INb          ,0              ,REGI_DX},{L_REGw       ,O_INd          ,0              ,REGI_DX},
+{L_REGw                ,O_OUTb         ,0              ,REGI_DX},{L_REGw       ,O_OUTd         ,0              ,REGI_DX},
+
+/* 0x2f0 - 0x2f7 */
+{D_LOCK                ,0                      ,0              ,0              },{D_ICEBP      ,0                      ,0              ,0              },
+{L_PREREPNE    ,0                      ,0              ,0              },{L_PREREP     ,0                      ,0              ,0              },
+{D_HLT         ,0                      ,0              ,0              },{D_CMC        ,0                      ,0              ,0              },
+{L_MODRM       ,8                      ,0              ,M_GRP  },{L_MODRM      ,0xa            ,0              ,M_GRP  },
+/* 0x2f8 - 0x2ff */
+{D_CLC         ,0                      ,0              ,0              },{D_STC        ,0                      ,0              ,0              },
+{D_CLI         ,0                      ,0              ,0              },{D_STI        ,0                      ,0              ,0              },
+{D_CLD         ,0                      ,0              ,0              },{D_STD        ,0                      ,0              ,0              },
+{L_MODRM       ,0xb            ,0              ,M_GRP  },{L_MODRM      ,0xd            ,0              ,M_GRP  },
+
+
+/* 0x300 - 0x307 */
+{L_MODRM       ,O_GRP6d        ,S_Ew   ,M_Ew   },{L_MODRM      ,O_GRP7d        ,S_Ew   ,M_Ew   },
+{L_MODRM_NVM   ,O_LAR          ,S_Gd   ,M_EdGd },{L_MODRM_NVM  ,O_LSL          ,S_Gd   ,M_EdGd },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{D_CLTS                ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+/* 0x308 - 0x30f */
+{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              },
+
+/* 0x310 - 0x317 */
+{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              },
+/* 0x318 - 0x31f */
+{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              },
+
+/* 0x320 - 0x327 */
+{L_MODRM       ,O_M_Rd_CRx     ,S_Ed   ,0              },{L_MODRM      ,O_M_Rd_DRx     ,S_Ed   ,0              },
+{L_MODRM       ,O_M_CRx_Rd     ,0              ,M_Ed   },{L_MODRM      ,O_M_DRx_Rd     ,0              ,M_Ed   },
+{L_MODRM       ,O_M_Rd_TRx     ,S_Ed   ,0              },{0            ,0                      ,0              ,0              },
+{L_MODRM       ,O_M_TRx_Rd     ,0              ,M_Ed   },{0            ,0                      ,0              ,0              },
+
+/* 0x328 - 0x32f */
+{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              },
+
+/* 0x330 - 0x337 */
+{0                     ,0                      ,0              ,0              },{D_RDTSC      ,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              },
+/* 0x338 - 0x33f */
+{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              },
+
+/* 0x340 - 0x347 */
+{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              },
+/* 0x348 - 0x34f */
+{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              },
+
+/* 0x350 - 0x357 */
+{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              },
+/* 0x358 - 0x35f */
+{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              },
+
+/* 0x360 - 0x367 */
+{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              },
+/* 0x368 - 0x36f */
+{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              },
+
+
+/* 0x370 - 0x377 */
+{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              },
+/* 0x378 - 0x37f */
+{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              },
+
+/* 0x380 - 0x387 */
+{L_Idx         ,O_C_O          ,S_C_AIPd,0             },{L_Idx        ,O_C_NO         ,S_C_AIPd,0             },
+{L_Idx         ,O_C_B          ,S_C_AIPd,0             },{L_Idx        ,O_C_NB         ,S_C_AIPd,0             },
+{L_Idx         ,O_C_Z          ,S_C_AIPd,0             },{L_Idx        ,O_C_NZ         ,S_C_AIPd,0             },
+{L_Idx         ,O_C_BE         ,S_C_AIPd,0             },{L_Idx        ,O_C_NBE        ,S_C_AIPd,0             },
+/* 0x388 - 0x38f */
+{L_Idx         ,O_C_S          ,S_C_AIPd,0             },{L_Idx        ,O_C_NS         ,S_C_AIPd,0             },
+{L_Idx         ,O_C_P          ,S_C_AIPd,0             },{L_Idx        ,O_C_NP         ,S_C_AIPd,0             },
+{L_Idx         ,O_C_L          ,S_C_AIPd,0             },{L_Idx        ,O_C_NL         ,S_C_AIPd,0             },
+{L_Idx         ,O_C_LE         ,S_C_AIPd,0             },{L_Idx        ,O_C_NLE        ,S_C_AIPd,0             },
+
+/* 0x390 - 0x397 */
+{L_MODRM       ,O_C_O          ,S_C_Eb,0               },{L_MODRM      ,O_C_NO         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_B          ,S_C_Eb,0               },{L_MODRM      ,O_C_NB         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_Z          ,S_C_Eb,0               },{L_MODRM      ,O_C_NZ         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_BE         ,S_C_Eb,0               },{L_MODRM      ,O_C_NBE        ,S_C_Eb,0               },
+/* 0x398 - 0x39f */
+{L_MODRM       ,O_C_S          ,S_C_Eb,0               },{L_MODRM      ,O_C_NS         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_P          ,S_C_Eb,0               },{L_MODRM      ,O_C_NP         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_L          ,S_C_Eb,0               },{L_MODRM      ,O_C_NL         ,S_C_Eb,0               },
+{L_MODRM       ,O_C_LE         ,S_C_Eb,0               },{L_MODRM      ,O_C_NLE        ,S_C_Eb,0               },
+
+/* 0x3a0 - 0x3a7 */
+{L_SEG         ,0              ,S_PUSHd        ,fs             },{D_POPSEGd,0                  ,0              ,fs                     },
+{D_CPUID       ,0                      ,0              ,0              },{L_MODRM      ,O_BTd          ,S_Ed   ,M_EdGdt        },
+{L_MODRM       ,O_DSHLd        ,S_Ed,M_EdGdIb  },{L_MODRM      ,O_DSHLd        ,S_Ed   ,M_EdGdCL       },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+/* 0x3a8 - 0x3af */
+{L_SEG         ,0              ,S_PUSHd        ,gs             },{D_POPSEGd,0                  ,0              ,gs                     },
+{0                     ,0                      ,0              ,0              },{L_MODRM      ,O_BTSd         ,S_Ed   ,M_EdGdt        },
+{L_MODRM       ,O_DSHRd        ,S_Ed,M_EdGdIb  },{L_MODRM      ,O_DSHRd        ,S_Ed   ,M_EdGdCL       },
+{0                     ,0                      ,0              ,0              },{L_MODRM      ,O_IMULRd       ,S_Gd   ,M_EdxGdx       },
+
+/* 0x3b0 - 0x3b7 */
+{0                     ,0                      ,0              ,0              },{L_MODRM      ,O_CMPXCHG      ,S_Ed   ,M_Ed   },
+{L_MODRM       ,O_SEGSS        ,S_SEGGd,M_Efd  },{L_MODRM      ,O_BTRd         ,S_Ed   ,M_EdGdt        },
+{L_MODRM       ,O_SEGFS        ,S_SEGGd,M_Efd  },{L_MODRM      ,O_SEGGS        ,S_SEGGd,M_Efd  },
+{L_MODRM       ,0                      ,S_Gd   ,M_Eb   },{L_MODRM      ,0                      ,S_Gd   ,M_Ew   },
+/* 0x3b8 - 0x3bf */
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{L_MODRM       ,0xf            ,0              ,M_GRP  },{L_MODRM      ,O_BTCd         ,S_Ed   ,M_EdGdt        },
+{L_MODRM       ,O_BSFd         ,S_Gd   ,M_Ed   },{L_MODRM      ,O_BSRd         ,S_Gd   ,M_Ed   },
+{L_MODRM       ,0                      ,S_Gd   ,M_Ebx  },{L_MODRM      ,0                      ,S_Gd   ,M_Ewx  },
+
+/* 0x3c0 - 0x3cc */
+{L_MODRM               ,t_ADDb                 ,S_EbGb         ,M_GbEb         },{L_MODRM              ,t_ADDd         ,S_EdGd         ,M_GdEd },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+{0                     ,0                      ,0              ,0              },{0            ,0                      ,0              ,0              },
+/* 0x3c8 - 0x3cf */
+{L_REGd                ,O_BSWAPd       ,S_REGd ,REGI_AX},{L_REGd       ,O_BSWAPd       ,S_REGd ,REGI_CX},
+{L_REGd                ,O_BSWAPd       ,S_REGd ,REGI_DX},{L_REGd       ,O_BSWAPd       ,S_REGd ,REGI_BX},
+{L_REGd                ,O_BSWAPd       ,S_REGd ,REGI_SP},{L_REGd       ,O_BSWAPd       ,S_REGd ,REGI_BP},
+{L_REGd                ,O_BSWAPd       ,S_REGd ,REGI_SI},{L_REGd       ,O_BSWAPd       ,S_REGd ,REGI_DI},
+
+/* 0x3d0 - 0x3d7 */
+{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              },
+/* 0x3d8 - 0x3df */
+{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              },
+
+/* 0x3e0 - 0x3ee */
+{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              },
+/* 0x3e8 - 0x3ef */
+{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              },
+
+/* 0x3f0 - 0x3fc */
+{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              },
+/* 0x3f8 - 0x3ff */
+{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              },
+
+};
+
+static OpCode Groups[16][8]={
+{      /* 0x00 Group 1 Eb,Ib */
+{0             ,t_ADDb         ,S_Eb   ,M_EbIb         },{0    ,t_ORb          ,S_Eb   ,M_EbIb         },
+{0             ,t_ADCb         ,S_Eb   ,M_EbIb         },{0    ,t_SBBb         ,S_Eb   ,M_EbIb         },
+{0             ,t_ANDb         ,S_Eb   ,M_EbIb         },{0    ,t_SUBb         ,S_Eb   ,M_EbIb         },
+{0             ,t_XORb         ,S_Eb   ,M_EbIb         },{0    ,t_CMPb         ,0              ,M_EbIb         },
+},{    /* 0x01 Group 1 Ew,Iw */
+{0             ,t_ADDw         ,S_Ew   ,M_EwIw         },{0    ,t_ORw          ,S_Ew   ,M_EwIw         },
+{0             ,t_ADCw         ,S_Ew   ,M_EwIw         },{0    ,t_SBBw         ,S_Ew   ,M_EwIw         },
+{0             ,t_ANDw         ,S_Ew   ,M_EwIw         },{0    ,t_SUBw         ,S_Ew   ,M_EwIw         },
+{0             ,t_XORw         ,S_Ew   ,M_EwIw         },{0    ,t_CMPw         ,0              ,M_EwIw         },
+},{    /* 0x02 Group 1 Ed,Id */
+{0             ,t_ADDd         ,S_Ed   ,M_EdId         },{0    ,t_ORd          ,S_Ed   ,M_EdId         },
+{0             ,t_ADCd         ,S_Ed   ,M_EdId         },{0    ,t_SBBd         ,S_Ed   ,M_EdId         },
+{0             ,t_ANDd         ,S_Ed   ,M_EdId         },{0    ,t_SUBd         ,S_Ed   ,M_EdId         },
+{0             ,t_XORd         ,S_Ed   ,M_EdId         },{0    ,t_CMPd         ,0              ,M_EdId         },
+},{    /* 0x03 Group 1 Ew,Ibx */
+{0             ,t_ADDw         ,S_Ew   ,M_EwIbx        },{0    ,t_ORw          ,S_Ew   ,M_EwIbx        },
+{0             ,t_ADCw         ,S_Ew   ,M_EwIbx        },{0    ,t_SBBw         ,S_Ew   ,M_EwIbx        },
+{0             ,t_ANDw         ,S_Ew   ,M_EwIbx        },{0    ,t_SUBw         ,S_Ew   ,M_EwIbx        },
+{0             ,t_XORw         ,S_Ew   ,M_EwIbx        },{0    ,t_CMPw         ,0              ,M_EwIbx        },
+},{    /* 0x04 Group 1 Ed,Ibx */
+{0             ,t_ADDd         ,S_Ed   ,M_EdIbx        },{0    ,t_ORd          ,S_Ed   ,M_EdIbx        },
+{0             ,t_ADCd         ,S_Ed   ,M_EdIbx        },{0    ,t_SBBd         ,S_Ed   ,M_EdIbx        },
+{0             ,t_ANDd         ,S_Ed   ,M_EdIbx        },{0    ,t_SUBd         ,S_Ed   ,M_EdIbx        },
+{0             ,t_XORd         ,S_Ed   ,M_EdIbx        },{0    ,t_CMPd         ,0              ,M_EdIbx        },
+
+},{    /* 0x05 Group 2 Eb,XXX */
+{0             ,t_ROLb         ,S_Eb   ,M_Eb           },{0    ,t_RORb         ,S_Eb   ,M_Eb           },
+{0             ,t_RCLb         ,S_Eb   ,M_Eb           },{0    ,t_RCRb         ,S_Eb   ,M_Eb           },
+{0             ,t_SHLb         ,S_Eb   ,M_Eb           },{0    ,t_SHRb         ,S_Eb   ,M_Eb           },
+{0             ,t_SHLb         ,S_Eb   ,M_Eb           },{0    ,t_SARb         ,S_Eb   ,M_Eb           },
+},{    /* 0x06 Group 2 Ew,XXX */
+{0             ,t_ROLw         ,S_Ew   ,M_Ew           },{0    ,t_RORw         ,S_Ew   ,M_Ew           },
+{0             ,t_RCLw         ,S_Ew   ,M_Ew           },{0    ,t_RCRw         ,S_Ew   ,M_Ew           },
+{0             ,t_SHLw         ,S_Ew   ,M_Ew           },{0    ,t_SHRw         ,S_Ew   ,M_Ew           },
+{0             ,t_SHLw         ,S_Ew   ,M_Ew           },{0    ,t_SARw         ,S_Ew   ,M_Ew           },
+},{    /* 0x07 Group 2 Ed,XXX */
+{0             ,t_ROLd         ,S_Ed   ,M_Ed           },{0    ,t_RORd         ,S_Ed   ,M_Ed           },
+{0             ,t_RCLd         ,S_Ed   ,M_Ed           },{0    ,t_RCRd         ,S_Ed   ,M_Ed           },
+{0             ,t_SHLd         ,S_Ed   ,M_Ed           },{0    ,t_SHRd         ,S_Ed   ,M_Ed           },
+{0             ,t_SHLd         ,S_Ed   ,M_Ed           },{0    ,t_SARd         ,S_Ed   ,M_Ed           },
+
+
+},{    /* 0x08 Group 3 Eb */
+{0             ,t_TESTb        ,0              ,M_EbIb         },{0    ,t_TESTb        ,0              ,M_EbIb         },
+{0             ,O_NOT          ,S_Eb   ,M_Eb           },{0    ,t_NEGb         ,S_Eb   ,M_Eb           },
+{0             ,O_MULb         ,0              ,M_Eb           },{0    ,O_IMULb        ,0              ,M_Eb           },
+{0             ,O_DIVb         ,0              ,M_Eb           },{0    ,O_IDIVb        ,0              ,M_Eb           },
+},{    /* 0x09 Group 3 Ew */
+{0             ,t_TESTw        ,0              ,M_EwIw         },{0    ,t_TESTw        ,0              ,M_EwIw         },
+{0             ,O_NOT          ,S_Ew   ,M_Ew           },{0    ,t_NEGw         ,S_Ew   ,M_Ew           },
+{0             ,O_MULw         ,0              ,M_Ew           },{0    ,O_IMULw        ,0              ,M_Ew           },
+{0             ,O_DIVw         ,0              ,M_Ew           },{0    ,O_IDIVw        ,0              ,M_Ew           },
+},{    /* 0x0a Group 3 Ed */
+{0             ,t_TESTd        ,0              ,M_EdId         },{0    ,t_TESTd        ,0              ,M_EdId         },
+{0             ,O_NOT          ,S_Ed   ,M_Ed           },{0    ,t_NEGd         ,S_Ed   ,M_Ed           },
+{0             ,O_MULd         ,0              ,M_Ed           },{0    ,O_IMULd        ,0              ,M_Ed           },
+{0             ,O_DIVd         ,0              ,M_Ed           },{0    ,O_IDIVd        ,0              ,M_Ed           },
+
+},{    /* 0x0b Group 4 Eb */
+{0             ,t_INCb         ,S_Eb   ,M_Eb           },{0    ,t_DECb         ,S_Eb   ,M_Eb           },
+{0             ,0                      ,0              ,0                      },{0    ,0                      ,0              ,0                      },
+{0             ,0                      ,0              ,0                      },{0    ,0                      ,0              ,0                      },
+{0             ,0                      ,0              ,0                      },{0    ,O_CBACK        ,0              ,M_Iw           },
+},{    /* 0x0c Group 5 Ew */
+{0             ,t_INCw         ,S_Ew   ,M_Ew           },{0    ,t_DECw         ,S_Ew   ,M_Ew           },
+{0             ,O_CALLNw       ,S_IP   ,M_Ew           },{0    ,O_CALLFw       ,0              ,M_Efw          },
+{0             ,0                      ,S_IP   ,M_Ew           },{0    ,O_JMPFw        ,0              ,M_Efw          },
+{0             ,0                      ,S_PUSHw,M_Ew           },{0    ,0                      ,0              ,0                      },
+},{    /* 0x0d Group 5 Ed */
+{0             ,t_INCd         ,S_Ed   ,M_Ed           },{0    ,t_DECd         ,S_Ed   ,M_Ed           },
+{0             ,O_CALLNd       ,S_IP   ,M_Ed           },{0    ,O_CALLFd       ,0              ,M_Efd          },
+{0             ,0                      ,S_IP   ,M_Ed           },{0    ,O_JMPFd        ,0              ,M_Efd          },
+{0             ,0                      ,S_PUSHd,M_Ed           },{0    ,0                      ,0              ,0                      },
+
+
+},{    /* 0x0e Group 8 Ew */
+{0             ,0                      ,0              ,0                      },{0    ,0                      ,0              ,0                      },
+{0             ,0                      ,0              ,0                      },{0    ,0                      ,0              ,0                      },
+{0             ,O_BTw          ,S_Ew   ,M_EwIb         },{0    ,O_BTSw         ,S_Ew   ,M_EwIb         },
+{0             ,O_BTRw         ,S_Ew   ,M_EwIb         },{0    ,O_BTCw         ,S_Ew   ,M_EwIb         },
+},{    /* 0x0f Group 8 Ed */
+{0             ,0                      ,0              ,0                      },{0    ,0                      ,0              ,0                      },
+{0             ,0                      ,0              ,0                      },{0    ,0                      ,0              ,0                      },
+{0             ,O_BTd          ,S_Ed   ,M_EdIb         },{0    ,O_BTSd         ,S_Ed   ,M_EdIb         },
+{0             ,O_BTRd         ,S_Ed   ,M_EdIb         },{0    ,O_BTCd         ,S_Ed   ,M_EdIb         },
+
+
+
+}
+};
+
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/save.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/save.h
new file mode 100644 (file)
index 0000000..408ed6d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Write the data from the opcode */
+switch (inst.code.save) {
+/* Byte */
+       case S_C_Eb:
+               inst_op1_b=inst.cond ? 1 : 0;
+       case S_Eb:
+               if (inst.rm<0xc0) SaveMb(inst.rm_eaa,inst_op1_b);
+               else reg_8(inst.rm_eai)=inst_op1_b;
+               break;  
+       case S_Gb:
+               reg_8(inst.rm_index)=inst_op1_b;
+               break;  
+       case S_EbGb:
+               if (inst.rm<0xc0) SaveMb(inst.rm_eaa,inst_op1_b);
+               else reg_8(inst.rm_eai)=inst_op1_b;
+               reg_8(inst.rm_index)=inst_op2_b;
+               break;  
+/* Word */
+       case S_Ew:
+               if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst_op1_w);
+               else reg_16(inst.rm_eai)=inst_op1_w;
+               break;  
+       case S_Gw:
+               reg_16(inst.rm_index)=inst_op1_w;
+               break;  
+       case S_EwGw:
+               if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst_op1_w);
+               else reg_16(inst.rm_eai)=inst_op1_w;
+               reg_16(inst.rm_index)=inst_op2_w;
+               break;  
+/* Dword */
+       case S_Ed:
+               if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst_op1_d);
+               else reg_32(inst.rm_eai)=inst_op1_d;
+               break;  
+       case S_EdMw:            /* Special one 16 to memory, 32 zero extend to reg */
+               if (inst.rm<0xc0) SaveMw(inst.rm_eaa,inst_op1_w);
+               else reg_32(inst.rm_eai)=inst_op1_d;
+               break;
+       case S_Gd:
+               reg_32(inst.rm_index)=inst_op1_d;
+               break;  
+       case S_EdGd:
+               if (inst.rm<0xc0) SaveMd(inst.rm_eaa,inst_op1_d);
+               else reg_32(inst.rm_eai)=inst_op1_d;
+               reg_32(inst.rm_index)=inst_op2_d;
+               break;  
+
+       case S_REGb:
+               reg_8(inst.code.extra)=inst_op1_b;
+               break;
+       case S_REGw:
+               reg_16(inst.code.extra)=inst_op1_w;
+               break;
+       case S_REGd:
+               reg_32(inst.code.extra)=inst_op1_d;
+               break;  
+       case S_SEGm:
+               if (CPU_SetSegGeneral((SegNames)inst.rm_index,inst_op1_w)) RunException();
+               break;
+       case S_SEGGw:
+               if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst_op2_w)) RunException();
+               reg_16(inst.rm_index)=inst_op1_w;
+               break;
+       case S_SEGGd:
+               if (CPU_SetSegGeneral((SegNames)inst.code.extra,inst_op2_w)) RunException();
+               reg_32(inst.rm_index)=inst_op1_d;
+               break;
+       case S_PUSHw:
+               Push_16(inst_op1_w);
+               break;
+       case S_PUSHd:
+               Push_32(inst_op1_d);
+               break;
+
+       case S_C_AIPw:
+               if (!inst.cond) goto nextopcode;
+       case S_AIPw:
+               SaveIP();
+               reg_eip+=inst_op1_d;
+               reg_eip&=0xffff;
+               continue;
+       case S_C_AIPd:
+               if (!inst.cond) goto nextopcode;
+       case S_AIPd:
+               SaveIP();
+               reg_eip+=inst_op1_d;
+               continue;
+       case S_IPIw:
+               reg_esp+=Fetchw();
+       case S_IP:
+               SaveIP();
+               reg_eip=inst_op1_d;
+               continue;
+       case 0:
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("SAVE:Unhandled code %d entry %X",inst.code.save,inst.entry);
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/string.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/string.h
new file mode 100644 (file)
index 0000000..8cb6ec0
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+{
+       EAPoint si_base,di_base;
+       Bitu    si_index,di_index;
+       Bitu    add_mask;
+       Bitu    count,count_left;
+       Bits    add_index;
+       
+       if (inst.prefix & PREFIX_SEG) si_base=inst.seg.base;
+       else si_base=SegBase(ds);
+       di_base=SegBase(es);
+       if (inst.prefix & PREFIX_ADDR) {
+               add_mask=0xFFFFFFFF;
+               si_index=reg_esi;
+               di_index=reg_edi;
+               count=reg_ecx;
+       } else {
+               add_mask=0xFFFF;
+               si_index=reg_si;
+               di_index=reg_di;
+               count=reg_cx;
+       }
+       if (!(inst.prefix & PREFIX_REP)) {
+               count=1;
+       } else {
+               /* Calculate amount of ops to do before cycles run out */
+               CPU_Cycles++;
+               if ((count>(Bitu)CPU_Cycles) && (inst.code.op<R_SCASB)) {
+                       count_left=count-CPU_Cycles;
+                       count=CPU_Cycles;
+                       CPU_Cycles=0;
+                       LoadIP();
+               } else {
+                       /* Won't interrupt scas and cmps instruction since they can interrupt themselves */
+                       if (inst.code.op<R_SCASB) CPU_Cycles-=count;
+                       count_left=0;
+               }
+       }
+       add_index=cpu.direction;
+       if (count) switch (inst.code.op) {
+       case R_OUTSB:
+               for (;count>0;count--) {
+                       IO_WriteB(reg_dx,LoadMb(si_base+si_index));
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_OUTSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       IO_WriteW(reg_dx,LoadMw(si_base+si_index));
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_OUTSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       IO_WriteD(reg_dx,LoadMd(si_base+si_index));
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_INSB:
+               for (;count>0;count--) {
+                       SaveMb(di_base+di_index,IO_ReadB(reg_dx));
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_INSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       SaveMw(di_base+di_index,IO_ReadW(reg_dx));
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_INSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       SaveMd(di_base+di_index,IO_ReadD(reg_dx));
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_STOSB:
+               for (;count>0;count--) {
+                       SaveMb(di_base+di_index,reg_al);
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_STOSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       SaveMw(di_base+di_index,reg_ax);
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_STOSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       SaveMd(di_base+di_index,reg_eax);
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_MOVSB:
+               for (;count>0;count--) {
+                       SaveMb(di_base+di_index,LoadMb(si_base+si_index));
+                       di_index=(di_index+add_index) & add_mask;
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_MOVSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       SaveMw(di_base+di_index,LoadMw(si_base+si_index));
+                       di_index=(di_index+add_index) & add_mask;
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_MOVSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       SaveMd(di_base+di_index,LoadMd(si_base+si_index));
+                       di_index=(di_index+add_index) & add_mask;
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_LODSB:
+               for (;count>0;count--) {
+                       reg_al=LoadMb(si_base+si_index);
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_LODSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       reg_ax=LoadMw(si_base+si_index);
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_LODSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       reg_eax=LoadMd(si_base+si_index);
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_SCASB:
+               {
+                       Bit8u val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val2=LoadMb(di_base+di_index);
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((reg_al==val2)!=inst.repz) break;
+                       }
+                       CMPB(reg_al,val2,LoadD,0);
+               }
+               break;
+       case R_SCASW:
+               {
+                       add_index<<=1;Bit16u val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val2=LoadMw(di_base+di_index);
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((reg_ax==val2)!=inst.repz) break;
+                       }
+                       CMPW(reg_ax,val2,LoadD,0);
+               }
+               break;
+       case R_SCASD:
+               {
+                       add_index<<=2;Bit32u val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val2=LoadMd(di_base+di_index);
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((reg_eax==val2)!=inst.repz) break;
+                       }
+                       CMPD(reg_eax,val2,LoadD,0);
+               }
+               break;
+       case R_CMPSB:
+               {
+                       Bit8u val1,val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val1=LoadMb(si_base+si_index);
+                               val2=LoadMb(di_base+di_index);
+                               si_index=(si_index+add_index) & add_mask;
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((val1==val2)!=inst.repz) break;
+                       }
+                       CMPB(val1,val2,LoadD,0);
+               }
+               break;
+       case R_CMPSW:
+               {
+                       add_index<<=1;Bit16u val1,val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val1=LoadMw(si_base+si_index);
+                               val2=LoadMw(di_base+di_index);
+                               si_index=(si_index+add_index) & add_mask;
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((val1==val2)!=inst.repz) break;
+                       }
+                       CMPW(val1,val2,LoadD,0);
+               }
+               break;
+       case R_CMPSD:
+               {
+                       add_index<<=2;Bit32u val1,val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val1=LoadMd(si_base+si_index);
+                               val2=LoadMd(di_base+di_index);
+                               si_index=(si_index+add_index) & add_mask;
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((val1==val2)!=inst.repz) break;
+                       }
+                       CMPD(val1,val2,LoadD,0);
+               }
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled string %d entry %X",inst.code.op,inst.entry);
+       }
+       /* Clean up after certain amount of instructions */
+       reg_esi&=(~add_mask);
+       reg_esi|=(si_index & add_mask);
+       reg_edi&=(~add_mask);
+       reg_edi|=(di_index & add_mask);
+       if (inst.prefix & PREFIX_REP) {
+               count+=count_left;
+               reg_ecx&=(~add_mask);
+               reg_ecx|=(count & add_mask);
+       }
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_full/support.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_full/support.h
new file mode 100644 (file)
index 0000000..bdbe452
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+enum {
+       L_N=0,
+       L_SKIP,
+       /* Grouped ones using MOD/RM */
+       L_MODRM,L_MODRM_NVM,L_POPwRM,L_POPdRM,
+       
+       L_Ib,L_Iw,L_Id,
+       L_Ibx,L_Iwx,L_Idx,                              //Sign extend
+       L_Ifw,L_Ifd,
+       L_OP,
+
+       L_REGb,L_REGw,L_REGd,
+       L_REGbIb,L_REGwIw,L_REGdId,
+       L_POPw,L_POPd,
+       L_POPfw,L_POPfd,
+       L_SEG,
+
+       L_INTO,
+
+       L_VAL,
+       L_PRESEG,
+       L_DOUBLE,
+       L_PREOP,L_PREADD,L_PREREP,L_PREREPNE,
+       L_STRING,
+
+/* Direct ones */
+       D_IRETw,D_IRETd,
+       D_PUSHAw,D_PUSHAd,
+       D_POPAw,D_POPAd,
+       D_POPSEGw,D_POPSEGd,
+       D_DAA,D_DAS,
+       D_AAA,D_AAS,
+       D_CBW,D_CWDE,
+       D_CWD,D_CDQ,
+       D_SETALC,
+       D_XLAT,
+       D_CLI,D_STI,D_STC,D_CLC,D_CMC,D_CLD,D_STD,
+       D_NOP,D_WAIT,
+       D_ENTERw,D_ENTERd,
+       D_LEAVEw,D_LEAVEd,
+       
+       D_RETFw,D_RETFd,
+       D_RETFwIw,D_RETFdIw,
+       D_POPF,D_PUSHF,
+       D_SAHF,D_LAHF,
+       D_CPUID,
+       D_HLT,D_CLTS,
+       D_LOCK,D_ICEBP,
+       D_RDTSC,
+       L_ERROR
+};
+
+
+enum {
+       O_N=t_LASTFLAG,
+       O_COND,
+       O_XCHG_AX,O_XCHG_EAX,
+       O_IMULRw,O_IMULRd,
+       O_BOUNDw,O_BOUNDd,
+       O_CALLNw,O_CALLNd,
+       O_CALLFw,O_CALLFd,
+       O_JMPFw,O_JMPFd,
+
+       O_OPAL,O_ALOP,
+       O_OPAX,O_AXOP,
+       O_OPEAX,O_EAXOP,
+       O_INT,
+       O_SEGDS,O_SEGES,O_SEGFS,O_SEGGS,O_SEGSS,
+       O_LOOP,O_LOOPZ,O_LOOPNZ,O_JCXZ,
+       O_INb,O_INw,O_INd,
+       O_OUTb,O_OUTw,O_OUTd,
+
+       O_NOT,O_AAM,O_AAD,
+       O_MULb,O_MULw,O_MULd,
+       O_IMULb,O_IMULw,O_IMULd,
+       O_DIVb,O_DIVw,O_DIVd,
+       O_IDIVb,O_IDIVw,O_IDIVd,
+       O_CBACK,
+
+
+       O_DSHLw,O_DSHLd,
+       O_DSHRw,O_DSHRd,
+       O_C_O   ,O_C_NO ,O_C_B  ,O_C_NB ,O_C_Z  ,O_C_NZ ,O_C_BE ,O_C_NBE,
+       O_C_S   ,O_C_NS ,O_C_P  ,O_C_NP ,O_C_L  ,O_C_NL ,O_C_LE ,O_C_NLE,
+
+       O_GRP6w,O_GRP6d,
+       O_GRP7w,O_GRP7d,
+       O_M_CRx_Rd,O_M_Rd_CRx,
+       O_M_DRx_Rd,O_M_Rd_DRx,
+       O_M_TRx_Rd,O_M_Rd_TRx,
+       O_LAR,O_LSL,
+       O_ARPL,
+       
+       O_BTw,O_BTSw,O_BTRw,O_BTCw,
+       O_BTd,O_BTSd,O_BTRd,O_BTCd,
+       O_BSFw,O_BSRw,O_BSFd,O_BSRd,
+
+       O_BSWAPw, O_BSWAPd,
+       O_CMPXCHG,
+       O_FPU
+
+
+};
+
+enum {
+       S_N=0,
+       S_C_Eb,
+       S_Eb,S_Gb,S_EbGb,
+       S_Ew,S_Gw,S_EwGw,
+       S_Ed,S_Gd,S_EdGd,S_EdMw,
+
+       
+       S_REGb,S_REGw,S_REGd,
+       S_PUSHw,S_PUSHd,
+       S_SEGm,
+       S_SEGGw,S_SEGGd,
+
+       
+       S_AIPw,S_C_AIPw,
+       S_AIPd,S_C_AIPd,
+
+       S_IP,S_IPIw
+};
+
+enum {
+       R_OUTSB,R_OUTSW,R_OUTSD,
+       R_INSB,R_INSW,R_INSD,
+       R_MOVSB,R_MOVSW,R_MOVSD,
+       R_LODSB,R_LODSW,R_LODSD,
+       R_STOSB,R_STOSW,R_STOSD,
+       R_SCASB,R_SCASW,R_SCASD,
+       R_CMPSB,R_CMPSW,R_CMPSD
+};
+
+enum {
+       M_None=0,
+       M_Ebx,M_Eb,M_Gb,M_EbGb,M_GbEb,
+       M_Ewx,M_Ew,M_Gw,M_EwGw,M_GwEw,M_EwxGwx,M_EwGwt,
+       M_Edx,M_Ed,M_Gd,M_EdGd,M_GdEd,M_EdxGdx,M_EdGdt,
+       
+       M_EbIb,M_EwIb,M_EdIb,
+       M_EwIw,M_EwIbx,M_EwxIbx,M_EwxIwx,M_EwGwIb,M_EwGwCL,
+       M_EdId,M_EdIbx,M_EdGdIb,M_EdGdCL,
+       
+       M_Efw,M_Efd,
+       
+       M_Ib,M_Iw,M_Id,
+
+
+       M_SEG,M_EA,
+       M_GRP,
+       M_GRP_Ib,M_GRP_CL,M_GRP_1,
+
+       M_POPw,M_POPd
+};
+
+struct OpCode {
+       Bit8u load,op,save,extra;
+};
+
+struct FullData {
+       Bitu entry;
+       Bitu rm;
+       EAPoint rm_eaa;
+       Bitu rm_off;
+       Bitu rm_eai;
+       Bitu rm_index;
+       Bitu rm_mod;
+       OpCode code;
+       EAPoint cseip;
+#ifdef WORDS_BIGENDIAN
+       union {
+               Bit32u dword[1];
+               Bit32s dwords[1];
+               Bit16u word[2];
+               Bit16s words[2];
+               Bit8u byte[4];
+               Bit8s bytes[4];
+               } blah1,blah2,blah_imm;
+#else
+       union { 
+               Bit8u b;Bit8s bs;
+               Bit16u w;Bit16s ws;
+               Bit32u d;Bit32s ds;
+       } op1,op2,imm;
+#endif
+       Bitu new_flags;
+       struct {
+               EAPoint base;
+       } seg;
+       Bitu cond;
+       bool repz;
+       Bitu prefix;
+};
+
+/* Some defines to get the names correct. */
+#ifdef WORDS_BIGENDIAN
+
+#define inst_op1_b  inst.blah1.byte[3]
+#define inst_op1_bs inst.blah1.bytes[3]
+#define inst_op1_w  inst.blah1.word[1]
+#define inst_op1_ws inst.blah1.words[1]
+#define inst_op1_d  inst.blah1.dword[0]
+#define inst_op1_ds inst.blah1.dwords[0]
+
+#define inst_op2_b  inst.blah2.byte[3]
+#define inst_op2_bs inst.blah2.bytes[3]
+#define inst_op2_w  inst.blah2.word[1]
+#define inst_op2_ws inst.blah2.words[1]
+#define inst_op2_d  inst.blah2.dword[0]
+#define inst_op2_ds inst.blah2.dwords[0]
+
+#define inst_imm_b  inst.blah_imm.byte[3]
+#define inst_imm_bs inst.blah_imm.bytes[3]
+#define inst_imm_w  inst.blah_imm.word[1]
+#define inst_imm_ws inst.blah_imm.words[1]
+#define inst_imm_d  inst.blah_imm.dword[0]
+#define inst_imm_ds inst.blah_imm.dwords[0]
+
+#else
+
+#define inst_op1_b  inst.op1.b
+#define inst_op1_bs inst.op1.bs
+#define inst_op1_w  inst.op1.w
+#define inst_op1_ws inst.op1.ws
+#define inst_op1_d  inst.op1.d
+#define inst_op1_ds inst.op1.ds
+
+#define inst_op2_b  inst.op2.b
+#define inst_op2_bs inst.op2.bs
+#define inst_op2_w  inst.op2.w
+#define inst_op2_ws inst.op2.ws
+#define inst_op2_d  inst.op2.d
+#define inst_op2_ds inst.op2.ds
+
+#define inst_imm_b  inst.imm.b
+#define inst_imm_bs inst.imm.bs
+#define inst_imm_w  inst.imm.w
+#define inst_imm_ws inst.imm.ws
+#define inst_imm_d  inst.imm.d
+#define inst_imm_ds inst.imm.ds
+
+#endif
+
+
+#define PREFIX_NONE            0x0
+#define PREFIX_ADDR            0x1
+#define PREFIX_SEG             0x2
+#define PREFIX_REP             0x4
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal.cpp
new file mode 100644 (file)
index 0000000..1c03474
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+
+#include "dosbox.h"
+#include "mem.h"
+#include "cpu.h"
+#include "lazyflags.h"
+#include "inout.h"
+#include "callback.h"
+#include "pic.h"
+#include "fpu.h"
+#include "paging.h"
+
+#if C_DEBUG
+#include "debug.h"
+#endif
+
+#if (!C_CORE_INLINE)
+#define LoadMb(off) mem_readb(off)
+#define LoadMw(off) mem_readw(off)
+#define LoadMd(off) mem_readd(off)
+#define SaveMb(off,val)        mem_writeb(off,val)
+#define SaveMw(off,val)        mem_writew(off,val)
+#define SaveMd(off,val)        mem_writed(off,val)
+#else 
+#include "paging.h"
+#define LoadMb(off) mem_readb_inline(off)
+#define LoadMw(off) mem_readw_inline(off)
+#define LoadMd(off) mem_readd_inline(off)
+#define SaveMb(off,val)        mem_writeb_inline(off,val)
+#define SaveMw(off,val)        mem_writew_inline(off,val)
+#define SaveMd(off,val)        mem_writed_inline(off,val)
+#endif
+
+extern Bitu cycle_count;
+
+#if C_FPU
+#define CPU_FPU        1                                               //Enable FPU escape instructions
+#endif
+
+#define CPU_PIC_CHECK 1
+#define CPU_TRAP_CHECK 1
+
+#define OPCODE_NONE                    0x000
+#define OPCODE_0F                      0x100
+#define OPCODE_SIZE                    0x200
+
+#define PREFIX_ADDR                    0x1
+#define PREFIX_REP                     0x2
+
+#define TEST_PREFIX_ADDR       (core.prefixes & PREFIX_ADDR)
+#define TEST_PREFIX_REP                (core.prefixes & PREFIX_REP)
+
+#define DO_PREFIX_SEG(_SEG)                                    \
+       BaseDS=SegBase(_SEG);                                   \
+       BaseSS=SegBase(_SEG);                                   \
+       core.base_val_ds=_SEG;                                  \
+       goto restart_opcode;
+
+#define DO_PREFIX_ADDR()                                                               \
+       core.prefixes=(core.prefixes & ~PREFIX_ADDR) |          \
+       (cpu.code.big ^ PREFIX_ADDR);                                           \
+       core.ea_table=&EATable[(core.prefixes&1) * 256];        \
+       goto restart_opcode;
+
+#define DO_PREFIX_REP(_ZERO)                           \
+       core.prefixes|=PREFIX_REP;                              \
+       core.rep_zero=_ZERO;                                    \
+       goto restart_opcode;
+
+typedef PhysPt (*GetEAHandler)(void);
+
+static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
+
+static struct {
+       Bitu opcode_index;
+       PhysPt cseip;
+       PhysPt base_ds,base_ss;
+       SegNames base_val_ds;
+       bool rep_zero;
+       Bitu prefixes;
+       GetEAHandler * ea_table;
+} core;
+
+#define GETIP          (core.cseip-SegBase(cs))
+#define SAVEIP         reg_eip=GETIP;
+#define LOADIP         core.cseip=(SegBase(cs)+reg_eip);
+
+#define SegBase(c)     SegPhys(c)
+#define BaseDS         core.base_ds
+#define BaseSS         core.base_ss
+
+static INLINE Bit8u Fetchb() {
+       Bit8u temp=LoadMb(core.cseip);
+       core.cseip+=1;
+       return temp;
+}
+
+static INLINE Bit16u Fetchw() {
+       Bit16u temp=LoadMw(core.cseip);
+       core.cseip+=2;
+       return temp;
+}
+static INLINE Bit32u Fetchd() {
+       Bit32u temp=LoadMd(core.cseip);
+       core.cseip+=4;
+       return temp;
+}
+
+#define Push_16 CPU_Push16
+#define Push_32 CPU_Push32
+#define Pop_16 CPU_Pop16
+#define Pop_32 CPU_Pop32
+
+#include "instructions.h"
+#include "core_normal/support.h"
+#include "core_normal/string.h"
+
+
+#define EALookupTable (core.ea_table)
+
+Bits CPU_Core_Normal_Run(void) {
+       while (CPU_Cycles-->0) {
+               LOADIP;
+               core.opcode_index=cpu.code.big*0x200;
+               core.prefixes=cpu.code.big;
+               core.ea_table=&EATable[cpu.code.big*256];
+               BaseDS=SegBase(ds);
+               BaseSS=SegBase(ss);
+               core.base_val_ds=ds;
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+               if (DEBUG_HeavyIsBreakpoint()) {
+                       FillFlags();
+                       return debugCallback;
+               };
+#endif
+               cycle_count++;
+#endif
+restart_opcode:
+               switch (core.opcode_index+Fetchb()) {
+               #include "core_normal/prefix_none.h"
+               #include "core_normal/prefix_0f.h"
+               #include "core_normal/prefix_66.h"
+               #include "core_normal/prefix_66_0f.h"
+               default:
+               illegal_opcode:
+#if C_DEBUG    
+                       {
+                               Bitu len=(GETIP-reg_eip);
+                               LOADIP;
+                               if (len>16) len=16;
+                               char tempcode[16*2+1];char * writecode=tempcode;
+                               for (;len>0;len--) {
+                                       sprintf(writecode,"%02X",mem_readb(core.cseip++));
+                                       writecode+=2;
+                               }
+                               LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode);
+                       }
+#endif
+                       CPU_Exception(6,0);
+                       continue;
+               }
+               SAVEIP;
+       }
+       FillFlags();
+       return CBRET_NONE;
+decode_end:
+       SAVEIP;
+       FillFlags();
+       return CBRET_NONE;
+}
+
+Bits CPU_Core_Normal_Trap_Run(void) {
+       Bits oldCycles = CPU_Cycles;
+       CPU_Cycles = 1;
+       cpu.trap_skip = false;
+
+       Bits ret=CPU_Core_Normal_Run();
+       if (!cpu.trap_skip) CPU_HW_Interrupt(1);
+       CPU_Cycles = oldCycles-1;
+       cpudecoder = &CPU_Core_Normal_Run;
+
+       return ret;
+}
+
+
+
+void CPU_Core_Normal_Init(void) {
+
+}
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile
new file mode 100644 (file)
index 0000000..38f1d64
--- /dev/null
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# src/cpu/core_normal/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/dosbox
+pkgincludedir = $(includedir)/dosbox
+pkglibdir = $(libdir)/dosbox
+pkglibexecdir = $(libexecdir)/dosbox
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-pc-linux-gnu
+host_triplet = x86_64-pc-linux-gnu
+subdir = src/cpu/core_normal
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = aclocal-1.16
+ALSA_CFLAGS = 
+ALSA_LIBS =  -lasound -lm -ldl -lpthread
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AUTOCONF = autoconf
+AUTOHEADER = autoheader
+AUTOMAKE = automake-1.16
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =  -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = 
+LIBOBJS = 
+LIBS = -lasound -lm -ldl -lpthread -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpng -lz -lX11 -lGL
+LTLIBOBJS = 
+MAKEINFO = makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = dosbox
+PACKAGE_BUGREPORT = 
+PACKAGE_NAME = dosbox
+PACKAGE_STRING = dosbox 0.74
+PACKAGE_TARNAME = dosbox
+PACKAGE_URL = 
+PACKAGE_VERSION = 0.74
+PATH_SEPARATOR = :
+RANLIB = ranlib
+SDL_CFLAGS = -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+SDL_CONFIG = /usr/local/bin/sdl-config
+SDL_LIBS = -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpthread
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = 
+VERSION = 0.74
+WINDRES = :
+abs_builddir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_normal
+abs_srcdir = /home/whatisthis/src/DOSVAXJ3/src/cpu/core_normal
+abs_top_builddir = /home/whatisthis/src/DOSVAXJ3
+abs_top_srcdir = /home/whatisthis/src/DOSVAXJ3
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-pc-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-pc-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/whatisthis/src/DOSVAXJ3/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+runstatedir = ${localstatedir}/run
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias = 
+top_build_prefix = ../../../
+top_builddir = ../../..
+top_srcdir = ../../..
+noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \
+               prefix_66_0f.h string.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_normal/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_normal/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile.am b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile.am
new file mode 100644 (file)
index 0000000..99f76f3
--- /dev/null
@@ -0,0 +1,3 @@
+
+noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \
+               prefix_66_0f.h string.h
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile.in b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/Makefile.in
new file mode 100644 (file)
index 0000000..7e437c5
--- /dev/null
@@ -0,0 +1,491 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/cpu/core_normal
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_HEADERS = helpers.h prefix_none.h prefix_66.h prefix_0f.h support.h table_ea.h \
+               prefix_66_0f.h string.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/cpu/core_normal/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/cpu/core_normal/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/helpers.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/helpers.h
new file mode 100644 (file)
index 0000000..13526f8
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#define GetEAa                                                                                         \
+       PhysPt eaa=EALookupTable[rm]();                                 
+
+#define GetRMEAa                                                                                       \
+       GetRM;                                                                                                  \
+       GetEAa;                                                                                 
+
+
+#define RMEbGb(inst)                                                                                                           \
+       {                                                                                                                                               \
+               GetRMrb;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArb;inst(*earb,*rmrb,LoadRb,SaveRb);}                     \
+               else {GetEAa;inst(eaa,*rmrb,LoadMb,SaveMb);}                                            \
+       }
+
+#define RMGbEb(inst)                                                                                                           \
+       {                                                                                                                                               \
+               GetRMrb;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArb;inst(*rmrb,*earb,LoadRb,SaveRb);}                     \
+               else {GetEAa;inst(*rmrb,LoadMb(eaa),LoadRb,SaveRb);}                            \
+       }
+
+#define RMEb(inst)                                                                                                                     \
+       {                                                                                                                                               \
+               if (rm >= 0xc0 ) {GetEArb;inst(*earb,LoadRb,SaveRb);}                           \
+               else {GetEAa;inst(eaa,LoadMb,SaveMb);}                                                          \
+       }
+
+#define RMEwGw(inst)                                                                                                           \
+       {                                                                                                                                               \
+               GetRMrw;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,LoadRw,SaveRw);}                     \
+               else {GetEAa;inst(eaa,*rmrw,LoadMw,SaveMw);}                                            \
+       }
+
+#define RMEwGwOp3(inst,op3)                                                                                                    \
+       {                                                                                                                                               \
+               GetRMrw;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArw;inst(*earw,*rmrw,op3,LoadRw,SaveRw);}         \
+               else {GetEAa;inst(eaa,*rmrw,op3,LoadMw,SaveMw);}                                        \
+       }
+
+#define RMGwEw(inst)                                                                                                           \
+       {                                                                                                                                               \
+               GetRMrw;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,LoadRw,SaveRw);}                     \
+               else {GetEAa;inst(*rmrw,LoadMw(eaa),LoadRw,SaveRw);}                            \
+       }                                                                                                                               
+
+#define RMGwEwOp3(inst,op3)                                                                                                    \
+       {                                                                                                                                               \
+               GetRMrw;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArw;inst(*rmrw,*earw,op3,LoadRw,SaveRw);}         \
+               else {GetEAa;inst(*rmrw,LoadMw(eaa),op3,LoadRw,SaveRw);}                        \
+       }                                                                                                                               
+
+#define RMEw(inst)                                                                                                                     \
+       {                                                                                                                                               \
+               if (rm >= 0xc0 ) {GetEArw;inst(*earw,LoadRw,SaveRw);}                           \
+               else {GetEAa;inst(eaa,LoadMw,SaveMw);}                                                          \
+       }
+
+#define RMEdGd(inst)                                                                                                           \
+       {                                                                                                                                               \
+               GetRMrd;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,LoadRd,SaveRd);}                     \
+               else {GetEAa;inst(eaa,*rmrd,LoadMd,SaveMd);}                                            \
+       }
+
+#define RMEdGdOp3(inst,op3)                                                                                                    \
+       {                                                                                                                                               \
+               GetRMrd;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArd;inst(*eard,*rmrd,op3,LoadRd,SaveRd);}         \
+               else {GetEAa;inst(eaa,*rmrd,op3,LoadMd,SaveMd);}                                        \
+       }
+
+
+#define RMGdEd(inst)                                                                                                           \
+       {                                                                                                                                               \
+               GetRMrd;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,LoadRd,SaveRd);}                     \
+               else {GetEAa;inst(*rmrd,LoadMd(eaa),LoadRd,SaveRd);}                            \
+       }                                                                                                                               
+
+#define RMGdEdOp3(inst,op3)                                                                                                    \
+       {                                                                                                                                               \
+               GetRMrd;                                                                                                                        \
+               if (rm >= 0xc0 ) {GetEArd;inst(*rmrd,*eard,op3,LoadRd,SaveRd);}         \
+               else {GetEAa;inst(*rmrd,LoadMd(eaa),op3,LoadRd,SaveRd);}                        \
+       }                                                                                                                               
+
+
+
+
+#define RMEw(inst)                                                                                                                     \
+       {                                                                                                                                               \
+               if (rm >= 0xc0 ) {GetEArw;inst(*earw,LoadRw,SaveRw);}                           \
+               else {GetEAa;inst(eaa,LoadMw,SaveMw);}                                                          \
+       }
+
+#define RMEd(inst)                                                                                                                     \
+       {                                                                                                                                               \
+               if (rm >= 0xc0 ) {GetEArd;inst(*eard,LoadRd,SaveRd);}                           \
+               else {GetEAa;inst(eaa,LoadMd,SaveMd);}                                                          \
+       }
+
+#define ALIb(inst)                                                                                                                     \
+       { inst(reg_al,Fetchb(),LoadRb,SaveRb)}
+
+#define AXIw(inst)                                                                                                                     \
+       { inst(reg_ax,Fetchw(),LoadRw,SaveRw);}
+
+#define EAXId(inst)                                                                                                                    \
+       { inst(reg_eax,Fetchd(),LoadRd,SaveRd);}
+
+#define FPU_ESC(code) {                                                                                                                \
+       Bit8u rm=Fetchb();                                                                                                              \
+       if (rm >= 0xc0) {                                                                                                                       \
+               FPU_ESC ## code ## _Normal(rm);                                                                         \
+       } else {                                                                                                                                \
+               GetEAa;FPU_ESC ## code ## _EA(rm,eaa);                                                          \
+       }                                                                                                                                               \
+}
+
+#define CASE_W(_WHICH)                                                 \
+       case (OPCODE_NONE+_WHICH):
+
+#define CASE_D(_WHICH)                                                 \
+       case (OPCODE_SIZE+_WHICH):
+
+#define CASE_B(_WHICH)                                                 \
+       CASE_W(_WHICH)                                                          \
+       CASE_D(_WHICH)
+
+#define CASE_0F_W(_WHICH)                                              \
+       case ((OPCODE_0F|OPCODE_NONE)+_WHICH):
+
+#define CASE_0F_D(_WHICH)                                              \
+       case ((OPCODE_0F|OPCODE_SIZE)+_WHICH):
+
+#define CASE_0F_B(_WHICH)                                              \
+       CASE_0F_W(_WHICH)                                                       \
+       CASE_0F_D(_WHICH)
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_0f.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_0f.h
new file mode 100644 (file)
index 0000000..0fcf6b6
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+       CASE_0F_W(0x00)                                                                                         /* GRP 6 Exxx */
+               {
+                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:      /* SLDT */
+                       case 0x01:      /* STR */
+                               {
+                                       Bitu saveval;
+                                       if (!which) saveval=CPU_SLDT();
+                                       else saveval=CPU_STR();
+                                       if (rm >= 0xc0) {GetEArw;*earw=saveval;}
+                                       else {GetEAa;SaveMw(eaa,saveval);}
+                               }
+                               break;
+                       case 0x02:case 0x03:case 0x04:case 0x05:
+                               {
+                                       Bitu loadval;
+                                       if (rm >= 0xc0 ) {GetEArw;loadval=*earw;}
+                                       else {GetEAa;loadval=LoadMw(eaa);}
+                                       switch (which) {
+                                       case 0x02:
+                                               if (cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                               if (CPU_LLDT(loadval)) RUNEXCEPTION();
+                                               break;
+                                       case 0x03:
+                                               if (cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                               if (CPU_LTR(loadval)) RUNEXCEPTION();
+                                               break;
+                                       case 0x04:
+                                               CPU_VERR(loadval);
+                                               break;
+                                       case 0x05:
+                                               CPU_VERW(loadval);
+                                               break;
+                                       }
+                               }
+                               break;
+                       default:
+                               goto illegal_opcode;
+                       }
+               }
+               break;
+       CASE_0F_W(0x01)                                                                                         /* Group 7 Ew */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       if (rm < 0xc0)  { //First ones all use EA
+                               GetEAa;Bitu limit;
+                               switch (which) {
+                               case 0x00:                                                                              /* SGDT */
+                                       SaveMw(eaa,CPU_SGDT_limit());
+                                       SaveMd(eaa+2,CPU_SGDT_base());
+                                       break;
+                               case 0x01:                                                                              /* SIDT */
+                                       SaveMw(eaa,CPU_SIDT_limit());
+                                       SaveMd(eaa+2,CPU_SIDT_base());
+                                       break;
+                               case 0x02:                                                                              /* LGDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF);
+                                       break;
+                               case 0x03:                                                                              /* LIDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF);
+                                       break;
+                               case 0x04:                                                                              /* SMSW */
+                                       SaveMw(eaa,CPU_SMSW());
+                                       break;
+                               case 0x06:                                                                              /* LMSW */
+                                       limit=LoadMw(eaa);
+                                       if (CPU_LMSW(limit)) RUNEXCEPTION();
+                                       break;
+                               case 0x07:                                                                              /* INVLPG */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       PAGING_ClearTLB();
+                                       break;
+                               }
+                       } else {
+                               GetEArw;
+                               switch (which) {
+                               case 0x02:                                                                              /* LGDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       goto illegal_opcode;
+                               case 0x03:                                                                              /* LIDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       goto illegal_opcode;
+                               case 0x04:                                                                              /* SMSW */
+                                       *earw=CPU_SMSW();
+                                       break;
+                               case 0x06:                                                                              /* LMSW */
+                                       if (CPU_LMSW(*earw)) RUNEXCEPTION();
+                                       break;
+                               default:
+                                       goto illegal_opcode;
+                               }
+                       }
+               }
+               break;
+       CASE_0F_W(0x02)                                                                                         /* LAR Gw,Ew */
+               {
+                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRMrw;Bitu ar=*rmrw;
+                       if (rm >= 0xc0) {
+                               GetEArw;CPU_LAR(*earw,ar);
+                       } else {
+                               GetEAa;CPU_LAR(LoadMw(eaa),ar);
+                       }
+                       *rmrw=(Bit16u)ar;
+               }
+               break;
+       CASE_0F_W(0x03)                                                                                         /* LSL Gw,Ew */
+               {
+                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRMrw;Bitu limit=*rmrw;
+                       if (rm >= 0xc0) {
+                               GetEArw;CPU_LSL(*earw,limit);
+                       } else {
+                               GetEAa;CPU_LSL(LoadMw(eaa),limit);
+                       }
+                       *rmrw=(Bit16u)limit;
+               }
+               break;
+       CASE_0F_B(0x06)                                                                                         /* CLTS */
+               if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+               cpu.cr0&=(~CR0_TASKSWITCH);
+               break;
+       CASE_0F_B(0x08)                                                                                         /* INVD */
+       CASE_0F_B(0x09)                                                                                         /* WBINVD */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+               break;
+       CASE_0F_B(0x20)                                                                                         /* MOV Rd.CRx */
+               {
+                       GetRM;
+                       Bitu which=(rm >> 3) & 7;
+                       if (rm < 0xc0 ) {
+                               rm |= 0xc0;
+                               LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which);
+                       }
+                       GetEArd;
+                       Bit32u crx_value;
+                       if (CPU_READ_CRX(which,crx_value)) RUNEXCEPTION();
+                       *eard=crx_value;
+               }
+               break;
+       CASE_0F_B(0x21)                                                                                         /* MOV Rd,DRx */
+               {
+                       GetRM;
+                       Bitu which=(rm >> 3) & 7;
+                       if (rm < 0xc0 ) {
+                               rm |= 0xc0;
+                               LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR%u with non-register",which);
+                       }
+                       GetEArd;
+                       Bit32u drx_value;
+                       if (CPU_READ_DRX(which,drx_value)) RUNEXCEPTION();
+                       *eard=drx_value;
+               }
+               break;
+       CASE_0F_B(0x22)                                                                                         /* MOV CRx,Rd */
+               {
+                       GetRM;
+                       Bitu which=(rm >> 3) & 7;
+                       if (rm < 0xc0 ) {
+                               rm |= 0xc0;
+                               LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which);
+                       }
+                       GetEArd;
+                       if (CPU_WRITE_CRX(which,*eard)) RUNEXCEPTION();
+               }
+               break;
+       CASE_0F_B(0x23)                                                                                         /* MOV DRx,Rd */
+               {
+                       GetRM;
+                       Bitu which=(rm >> 3) & 7;
+                       if (rm < 0xc0 ) {
+                               rm |= 0xc0;
+                               LOG(LOG_CPU,LOG_ERROR)("MOV DR%u,XXX with non-register",which);
+                       }
+                       GetEArd;
+                       if (CPU_WRITE_DRX(which,*eard)) RUNEXCEPTION();
+               }
+               break;
+       CASE_0F_B(0x24)                                                                                         /* MOV Rd,TRx */
+               {
+                       GetRM;
+                       Bitu which=(rm >> 3) & 7;
+                       if (rm < 0xc0 ) {
+                               rm |= 0xc0;
+                               LOG(LOG_CPU,LOG_ERROR)("MOV XXX,TR%u with non-register",which);
+                       }
+                       GetEArd;
+                       Bit32u trx_value;
+                       if (CPU_READ_TRX(which,trx_value)) RUNEXCEPTION();
+                       *eard=trx_value;
+               }
+               break;
+       CASE_0F_B(0x26)                                                                                         /* MOV TRx,Rd */
+               {
+                       GetRM;
+                       Bitu which=(rm >> 3) & 7;
+                       if (rm < 0xc0 ) {
+                               rm |= 0xc0;
+                               LOG(LOG_CPU,LOG_ERROR)("MOV TR%u,XXX with non-register",which);
+                       }
+                       GetEArd;
+                       if (CPU_WRITE_TRX(which,*eard)) RUNEXCEPTION();
+               }
+               break;
+       CASE_0F_B(0x31)                                                                                         /* RDTSC */
+               {
+                       if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUMSLOW) goto illegal_opcode;
+                       /* Use a fixed number when in auto cycles mode as else the reported value changes constantly */
+                       Bit64s tsc=(Bit64s)(PIC_FullIndex()*(double) (CPU_CycleAutoAdjust?70000:CPU_CycleMax));
+                       reg_edx=(Bit32u)(tsc>>32);
+                       reg_eax=(Bit32u)(tsc&0xffffffff);
+               }
+               break;
+       CASE_0F_W(0x80)                                                                                         /* JO */
+               JumpCond16_w(TFLG_O);break;
+       CASE_0F_W(0x81)                                                                                         /* JNO */
+               JumpCond16_w(TFLG_NO);break;
+       CASE_0F_W(0x82)                                                                                         /* JB */
+               JumpCond16_w(TFLG_B);break;
+       CASE_0F_W(0x83)                                                                                         /* JNB */
+               JumpCond16_w(TFLG_NB);break;
+       CASE_0F_W(0x84)                                                                                         /* JZ */
+               JumpCond16_w(TFLG_Z);break;
+       CASE_0F_W(0x85)                                                                                         /* JNZ */
+               JumpCond16_w(TFLG_NZ);break;
+       CASE_0F_W(0x86)                                                                                         /* JBE */
+               JumpCond16_w(TFLG_BE);break;
+       CASE_0F_W(0x87)                                                                                         /* JNBE */
+               JumpCond16_w(TFLG_NBE);break;
+       CASE_0F_W(0x88)                                                                                         /* JS */
+               JumpCond16_w(TFLG_S);break;
+       CASE_0F_W(0x89)                                                                                         /* JNS */
+               JumpCond16_w(TFLG_NS);break;
+       CASE_0F_W(0x8a)                                                                                         /* JP */
+               JumpCond16_w(TFLG_P);break;
+       CASE_0F_W(0x8b)                                                                                         /* JNP */
+               JumpCond16_w(TFLG_NP);break;
+       CASE_0F_W(0x8c)                                                                                         /* JL */
+               JumpCond16_w(TFLG_L);break;
+       CASE_0F_W(0x8d)                                                                                         /* JNL */
+               JumpCond16_w(TFLG_NL);break;
+       CASE_0F_W(0x8e)                                                                                         /* JLE */
+               JumpCond16_w(TFLG_LE);break;
+       CASE_0F_W(0x8f)                                                                                         /* JNLE */
+               JumpCond16_w(TFLG_NLE);break;
+       CASE_0F_B(0x90)                                                                                         /* SETO */
+               SETcc(TFLG_O);break;
+       CASE_0F_B(0x91)                                                                                         /* SETNO */
+               SETcc(TFLG_NO);break;
+       CASE_0F_B(0x92)                                                                                         /* SETB */
+               SETcc(TFLG_B);break;
+       CASE_0F_B(0x93)                                                                                         /* SETNB */
+               SETcc(TFLG_NB);break;
+       CASE_0F_B(0x94)                                                                                         /* SETZ */
+               SETcc(TFLG_Z);break;
+       CASE_0F_B(0x95)                                                                                         /* SETNZ */
+               SETcc(TFLG_NZ); break;
+       CASE_0F_B(0x96)                                                                                         /* SETBE */
+               SETcc(TFLG_BE);break;
+       CASE_0F_B(0x97)                                                                                         /* SETNBE */
+               SETcc(TFLG_NBE);break;
+       CASE_0F_B(0x98)                                                                                         /* SETS */
+               SETcc(TFLG_S);break;
+       CASE_0F_B(0x99)                                                                                         /* SETNS */
+               SETcc(TFLG_NS);break;
+       CASE_0F_B(0x9a)                                                                                         /* SETP */
+               SETcc(TFLG_P);break;
+       CASE_0F_B(0x9b)                                                                                         /* SETNP */
+               SETcc(TFLG_NP);break;
+       CASE_0F_B(0x9c)                                                                                         /* SETL */
+               SETcc(TFLG_L);break;
+       CASE_0F_B(0x9d)                                                                                         /* SETNL */
+               SETcc(TFLG_NL);break;
+       CASE_0F_B(0x9e)                                                                                         /* SETLE */
+               SETcc(TFLG_LE);break;
+       CASE_0F_B(0x9f)                                                                                         /* SETNLE */
+               SETcc(TFLG_NLE);break;
+
+       CASE_0F_W(0xa0)                                                                                         /* PUSH FS */           
+               Push_16(SegValue(fs));break;
+       CASE_0F_W(0xa1)                                                                                         /* POP FS */    
+               if (CPU_PopSeg(fs,false)) RUNEXCEPTION();
+               break;
+       CASE_0F_B(0xa2)                                                                                         /* CPUID */
+               if (!CPU_CPUID()) goto illegal_opcode;
+               break;
+       CASE_0F_W(0xa3)                                                                                         /* BT Ew,Gw */
+               {
+                       FillFlags();GetRMrw;
+                       Bit16u mask=1 << (*rmrw & 15);
+                       if (rm >= 0xc0 ) {
+                               GetEArw;
+                               SETFLAGBIT(CF,(*earw & mask));
+                       } else {
+                               GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2;
+                               Bit16u old=LoadMw(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                       }
+                       break;
+               }
+       CASE_0F_W(0xa4)                                                                                         /* SHLD Ew,Gw,Ib */
+               RMEwGwOp3(DSHLW,Fetchb());
+               break;
+       CASE_0F_W(0xa5)                                                                                         /* SHLD Ew,Gw,CL */
+               RMEwGwOp3(DSHLW,reg_cl);
+               break;
+       CASE_0F_W(0xa8)                                                                                         /* PUSH GS */           
+               Push_16(SegValue(gs));break;
+       CASE_0F_W(0xa9)                                                                                         /* POP GS */            
+               if (CPU_PopSeg(gs,false)) RUNEXCEPTION();
+               break;
+       CASE_0F_W(0xab)                                                                                         /* BTS Ew,Gw */
+               {
+                       FillFlags();GetRMrw;
+                       Bit16u mask=1 << (*rmrw & 15);
+                       if (rm >= 0xc0 ) {
+                               GetEArw;
+                               SETFLAGBIT(CF,(*earw & mask));
+                               *earw|=mask;
+                       } else {
+                               GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2;
+                               Bit16u old=LoadMw(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                               SaveMw(eaa,old | mask);
+                       }
+                       break;
+               }
+       CASE_0F_W(0xac)                                                                                         /* SHRD Ew,Gw,Ib */
+               RMEwGwOp3(DSHRW,Fetchb());
+               break;
+       CASE_0F_W(0xad)                                                                                         /* SHRD Ew,Gw,CL */
+               RMEwGwOp3(DSHRW,reg_cl);
+               break;
+       CASE_0F_W(0xaf)                                                                                         /* IMUL Gw,Ew */
+               RMGwEwOp3(DIMULW,*rmrw);
+               break;
+       CASE_0F_B(0xb0)                                                                                 /* cmpxchg Eb,Gb */
+               {
+                       if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+                       FillFlags();
+                       GetRMrb;
+                       if (rm >= 0xc0 ) {
+                               GetEArb;
+                               if (reg_al == *earb) {
+                                       *earb=*rmrb;
+                                       SETFLAGBIT(ZF,1);
+                               } else {
+                                       reg_al = *earb;
+                                       SETFLAGBIT(ZF,0);
+                               }
+                       } else {
+                               GetEAa;
+                               Bit8u val = LoadMb(eaa);
+                               if (reg_al == val) { 
+                                       SaveMb(eaa,*rmrb);
+                                       SETFLAGBIT(ZF,1);
+                               } else {
+                                       SaveMb(eaa,val);        // cmpxchg always issues a write
+                                       reg_al = val;
+                                       SETFLAGBIT(ZF,0);
+                               }
+                       }
+                       break;
+               }
+       CASE_0F_W(0xb1)                                                                         /* cmpxchg Ew,Gw */
+               {
+                       if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+                       FillFlags();
+                       GetRMrw;
+                       if (rm >= 0xc0 ) {
+                               GetEArw;
+                               if(reg_ax == *earw) { 
+                                       *earw = *rmrw;
+                                       SETFLAGBIT(ZF,1);
+                               } else {
+                                       reg_ax = *earw;
+                                       SETFLAGBIT(ZF,0);
+                               }
+                       } else {
+                               GetEAa;
+                               Bit16u val = LoadMw(eaa);
+                               if(reg_ax == val) { 
+                                       SaveMw(eaa,*rmrw);
+                                       SETFLAGBIT(ZF,1);
+                               } else {
+                                       SaveMw(eaa,val);        // cmpxchg always issues a write
+                                       reg_ax = val;
+                                       SETFLAGBIT(ZF,0);
+                               }
+                       }
+                       break;
+               }
+
+       CASE_0F_W(0xb2)                                                                                         /* LSS Ew */
+               {       
+                       GetRMrw;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(ss,LoadMw(eaa+2))) RUNEXCEPTION();
+                       *rmrw=LoadMw(eaa);
+                       break;
+               }
+       CASE_0F_W(0xb3)                                                                                         /* BTR Ew,Gw */
+               {
+                       FillFlags();GetRMrw;
+                       Bit16u mask=1 << (*rmrw & 15);
+                       if (rm >= 0xc0 ) {
+                               GetEArw;
+                               SETFLAGBIT(CF,(*earw & mask));
+                               *earw&= ~mask;
+                       } else {
+                               GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2;
+                               Bit16u old=LoadMw(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                               SaveMw(eaa,old & ~mask);
+                       }
+                       break;
+               }
+       CASE_0F_W(0xb4)                                                                                         /* LFS Ew */
+               {       
+                       GetRMrw;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(fs,LoadMw(eaa+2))) RUNEXCEPTION();
+                       *rmrw=LoadMw(eaa);
+                       break;
+               }
+       CASE_0F_W(0xb5)                                                                                         /* LGS Ew */
+               {       
+                       GetRMrw;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(gs,LoadMw(eaa+2))) RUNEXCEPTION();
+                       *rmrw=LoadMw(eaa);
+                       break;
+               }
+       CASE_0F_W(0xb6)                                                                                         /* MOVZX Gw,Eb */
+               {
+                       GetRMrw;                                                                                                                        
+                       if (rm >= 0xc0 ) {GetEArb;*rmrw=*earb;}
+                       else {GetEAa;*rmrw=LoadMb(eaa);}
+                       break;
+               }
+       CASE_0F_W(0xb7)                                                                                         /* MOVZX Gw,Ew */
+       CASE_0F_W(0xbf)                                                                                         /* MOVSX Gw,Ew */
+               {
+                       GetRMrw;                                                                                                                        
+                       if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;}
+                       else {GetEAa;*rmrw=LoadMw(eaa);}
+                       break;
+               }
+       CASE_0F_W(0xba)                                                                                         /* GRP8 Ew,Ib */
+               {
+                       FillFlags();GetRM;
+                       if (rm >= 0xc0 ) {
+                               GetEArw;
+                               Bit16u mask=1 << (Fetchb() & 15);
+                               SETFLAGBIT(CF,(*earw & mask));
+                               switch (rm & 0x38) {
+                               case 0x20:                                                                              /* BT */
+                                       break;
+                               case 0x28:                                                                              /* BTS */
+                                       *earw|=mask;
+                                       break;
+                               case 0x30:                                                                              /* BTR */
+                                       *earw&= ~mask;
+                                       break;
+                               case 0x38:                                                                              /* BTC */
+                                       *earw^=mask;
+                                       break;
+                               default:
+                                       E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38);
+                               }
+                       } else {
+                               GetEAa;Bit16u old=LoadMw(eaa);
+                               Bit16u mask=1 << (Fetchb() & 15);
+                               SETFLAGBIT(CF,(old & mask));
+                               switch (rm & 0x38) {
+                               case 0x20:                                                                              /* BT */
+                                       break;
+                               case 0x28:                                                                              /* BTS */
+                                       SaveMw(eaa,old|mask);
+                                       break;
+                               case 0x30:                                                                              /* BTR */
+                                       SaveMw(eaa,old & ~mask);
+                                       break;
+                               case 0x38:                                                                              /* BTC */
+                                       SaveMw(eaa,old ^ mask);
+                                       break;
+                               default:
+                                       E_Exit("CPU:0F:BA:Illegal subfunction %X",rm & 0x38);
+                               }
+                       }
+                       break;
+               }
+       CASE_0F_W(0xbb)                                                                                         /* BTC Ew,Gw */
+               {
+                       FillFlags();GetRMrw;
+                       Bit16u mask=1 << (*rmrw & 15);
+                       if (rm >= 0xc0 ) {
+                               GetEArw;
+                               SETFLAGBIT(CF,(*earw & mask));
+                               *earw^=mask;
+                       } else {
+                               GetEAa;eaa+=(((Bit16s)*rmrw)>>4)*2;
+                               Bit16u old=LoadMw(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                               SaveMw(eaa,old ^ mask);
+                       }
+                       break;
+               }
+       CASE_0F_W(0xbc)                                                                                         /* BSF Gw,Ew */
+               {
+                       GetRMrw;
+                       Bit16u result,value;
+                       if (rm >= 0xc0) { GetEArw; value=*earw; } 
+                       else                    { GetEAa; value=LoadMw(eaa); }
+                       if (value==0) {
+                               SETFLAGBIT(ZF,true);
+                       } else {
+                               result = 0;
+                               while ((value & 0x01)==0) { result++; value>>=1; }
+                               SETFLAGBIT(ZF,false);
+                               *rmrw = result;
+                       }
+                       lflags.type=t_UNKNOWN;
+                       break;
+               }
+       CASE_0F_W(0xbd)                                                                                         /* BSR Gw,Ew */
+               {
+                       GetRMrw;
+                       Bit16u result,value;
+                       if (rm >= 0xc0) { GetEArw; value=*earw; } 
+                       else                    { GetEAa; value=LoadMw(eaa); }
+                       if (value==0) {
+                               SETFLAGBIT(ZF,true);
+                       } else {
+                               result = 15;    // Operandsize-1
+                               while ((value & 0x8000)==0) { result--; value<<=1; }
+                               SETFLAGBIT(ZF,false);
+                               *rmrw = result;
+                       }
+                       lflags.type=t_UNKNOWN;
+                       break;
+               }
+       CASE_0F_W(0xbe)                                                                                         /* MOVSX Gw,Eb */
+               {
+                       GetRMrw;                                                                                                                        
+                       if (rm >= 0xc0 ) {GetEArb;*rmrw=*(Bit8s *)earb;}
+                       else {GetEAa;*rmrw=LoadMbs(eaa);}
+                       break;
+               }
+       CASE_0F_B(0xc0)                                                                                         /* XADD Gb,Eb */
+               {
+                       if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+                       GetRMrb;Bit8u oldrmrb=*rmrb;
+                       if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;*earb+=oldrmrb;}
+                       else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,LoadMb(eaa)+oldrmrb);}
+                       break;
+               }
+       CASE_0F_W(0xc1)                                                                                         /* XADD Gw,Ew */
+               {
+                       if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+                       GetRMrw;Bit16u oldrmrw=*rmrw;
+                       if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;*earw+=oldrmrw;}
+                       else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,LoadMw(eaa)+oldrmrw);}
+                       break;
+               }
+       CASE_0F_W(0xc8)                                                                                         /* BSWAP AX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_ax);break;
+       CASE_0F_W(0xc9)                                                                                         /* BSWAP CX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_cx);break;
+       CASE_0F_W(0xca)                                                                                         /* BSWAP DX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_dx);break;
+       CASE_0F_W(0xcb)                                                                                         /* BSWAP BX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_bx);break;
+       CASE_0F_W(0xcc)                                                                                         /* BSWAP SP */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_sp);break;
+       CASE_0F_W(0xcd)                                                                                         /* BSWAP BP */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_bp);break;
+       CASE_0F_W(0xce)                                                                                         /* BSWAP SI */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_si);break;
+       CASE_0F_W(0xcf)                                                                                         /* BSWAP DI */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPW(reg_di);break;
+               
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_66.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_66.h
new file mode 100644 (file)
index 0000000..29f2a18
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+       CASE_D(0x01)                                                                                            /* ADD Ed,Gd */
+               RMEdGd(ADDD);break;     
+       CASE_D(0x03)                                                                                            /* ADD Gd,Ed */
+               RMGdEd(ADDD);break;
+       CASE_D(0x05)                                                                                            /* ADD EAX,Id */
+               EAXId(ADDD);break;
+       CASE_D(0x06)                                                                                            /* PUSH ES */           
+               Push_32(SegValue(es));break;
+       CASE_D(0x07)                                                                                            /* POP ES */
+               if (CPU_PopSeg(es,true)) RUNEXCEPTION();
+               break;
+       CASE_D(0x09)                                                                                            /* OR Ed,Gd */
+               RMEdGd(ORD);break;
+       CASE_D(0x0b)                                                                                            /* OR Gd,Ed */
+               RMGdEd(ORD);break;
+       CASE_D(0x0d)                                                                                            /* OR EAX,Id */
+               EAXId(ORD);break;
+       CASE_D(0x0e)                                                                                            /* PUSH CS */           
+               Push_32(SegValue(cs));break;
+       CASE_D(0x11)                                                                                            /* ADC Ed,Gd */
+               RMEdGd(ADCD);break;     
+       CASE_D(0x13)                                                                                            /* ADC Gd,Ed */
+               RMGdEd(ADCD);break;
+       CASE_D(0x15)                                                                                            /* ADC EAX,Id */
+               EAXId(ADCD);break;
+       CASE_D(0x16)                                                                                            /* PUSH SS */
+               Push_32(SegValue(ss));break;
+       CASE_D(0x17)                                                                                            /* POP SS */
+               if (CPU_PopSeg(ss,true)) RUNEXCEPTION();
+               CPU_Cycles++;
+               break;
+       CASE_D(0x19)                                                                                            /* SBB Ed,Gd */
+               RMEdGd(SBBD);break;
+       CASE_D(0x1b)                                                                                            /* SBB Gd,Ed */
+               RMGdEd(SBBD);break;
+       CASE_D(0x1d)                                                                                            /* SBB EAX,Id */
+               EAXId(SBBD);break;
+       CASE_D(0x1e)                                                                                            /* PUSH DS */           
+               Push_32(SegValue(ds));break;
+       CASE_D(0x1f)                                                                                            /* POP DS */
+               if (CPU_PopSeg(ds,true)) RUNEXCEPTION();
+               break;
+       CASE_D(0x21)                                                                                            /* AND Ed,Gd */
+               RMEdGd(ANDD);break;     
+       CASE_D(0x23)                                                                                            /* AND Gd,Ed */
+               RMGdEd(ANDD);break;
+       CASE_D(0x25)                                                                                            /* AND EAX,Id */
+               EAXId(ANDD);break;
+       CASE_D(0x29)                                                                                            /* SUB Ed,Gd */
+               RMEdGd(SUBD);break;
+       CASE_D(0x2b)                                                                                            /* SUB Gd,Ed */
+               RMGdEd(SUBD);break;
+       CASE_D(0x2d)                                                                                            /* SUB EAX,Id */
+               EAXId(SUBD);break;
+       CASE_D(0x31)                                                                                            /* XOR Ed,Gd */
+               RMEdGd(XORD);break;     
+       CASE_D(0x33)                                                                                            /* XOR Gd,Ed */
+               RMGdEd(XORD);break;
+       CASE_D(0x35)                                                                                            /* XOR EAX,Id */
+               EAXId(XORD);break;
+       CASE_D(0x39)                                                                                            /* CMP Ed,Gd */
+               RMEdGd(CMPD);break;
+       CASE_D(0x3b)                                                                                            /* CMP Gd,Ed */
+               RMGdEd(CMPD);break;
+       CASE_D(0x3d)                                                                                            /* CMP EAX,Id */
+               EAXId(CMPD);break;
+       CASE_D(0x40)                                                                                            /* INC EAX */
+               INCD(reg_eax,LoadRd,SaveRd);break;
+       CASE_D(0x41)                                                                                            /* INC ECX */
+               INCD(reg_ecx,LoadRd,SaveRd);break;
+       CASE_D(0x42)                                                                                            /* INC EDX */
+               INCD(reg_edx,LoadRd,SaveRd);break;
+       CASE_D(0x43)                                                                                            /* INC EBX */
+               INCD(reg_ebx,LoadRd,SaveRd);break;
+       CASE_D(0x44)                                                                                            /* INC ESP */
+               INCD(reg_esp,LoadRd,SaveRd);break;
+       CASE_D(0x45)                                                                                            /* INC EBP */
+               INCD(reg_ebp,LoadRd,SaveRd);break;
+       CASE_D(0x46)                                                                                            /* INC ESI */
+               INCD(reg_esi,LoadRd,SaveRd);break;
+       CASE_D(0x47)                                                                                            /* INC EDI */
+               INCD(reg_edi,LoadRd,SaveRd);break;
+       CASE_D(0x48)                                                                                            /* DEC EAX */
+               DECD(reg_eax,LoadRd,SaveRd);break;
+       CASE_D(0x49)                                                                                            /* DEC ECX */
+               DECD(reg_ecx,LoadRd,SaveRd);break;
+       CASE_D(0x4a)                                                                                            /* DEC EDX */
+               DECD(reg_edx,LoadRd,SaveRd);break;
+       CASE_D(0x4b)                                                                                            /* DEC EBX */
+               DECD(reg_ebx,LoadRd,SaveRd);break;
+       CASE_D(0x4c)                                                                                            /* DEC ESP */
+               DECD(reg_esp,LoadRd,SaveRd);break;
+       CASE_D(0x4d)                                                                                            /* DEC EBP */
+               DECD(reg_ebp,LoadRd,SaveRd);break;
+       CASE_D(0x4e)                                                                                            /* DEC ESI */
+               DECD(reg_esi,LoadRd,SaveRd);break;
+       CASE_D(0x4f)                                                                                            /* DEC EDI */
+               DECD(reg_edi,LoadRd,SaveRd);break;
+       CASE_D(0x50)                                                                                            /* PUSH EAX */
+               Push_32(reg_eax);break;
+       CASE_D(0x51)                                                                                            /* PUSH ECX */
+               Push_32(reg_ecx);break;
+       CASE_D(0x52)                                                                                            /* PUSH EDX */
+               Push_32(reg_edx);break;
+       CASE_D(0x53)                                                                                            /* PUSH EBX */
+               Push_32(reg_ebx);break;
+       CASE_D(0x54)                                                                                            /* PUSH ESP */
+               Push_32(reg_esp);break;
+       CASE_D(0x55)                                                                                            /* PUSH EBP */
+               Push_32(reg_ebp);break;
+       CASE_D(0x56)                                                                                            /* PUSH ESI */
+               Push_32(reg_esi);break;
+       CASE_D(0x57)                                                                                            /* PUSH EDI */
+               Push_32(reg_edi);break;
+       CASE_D(0x58)                                                                                            /* POP EAX */
+               reg_eax=Pop_32();break;
+       CASE_D(0x59)                                                                                            /* POP ECX */
+               reg_ecx=Pop_32();break;
+       CASE_D(0x5a)                                                                                            /* POP EDX */
+               reg_edx=Pop_32();break;
+       CASE_D(0x5b)                                                                                            /* POP EBX */
+               reg_ebx=Pop_32();break;
+       CASE_D(0x5c)                                                                                            /* POP ESP */
+               reg_esp=Pop_32();break;
+       CASE_D(0x5d)                                                                                            /* POP EBP */
+               reg_ebp=Pop_32();break;
+       CASE_D(0x5e)                                                                                            /* POP ESI */
+               reg_esi=Pop_32();break;
+       CASE_D(0x5f)                                                                                            /* POP EDI */
+               reg_edi=Pop_32();break;
+       CASE_D(0x60)                                                                                            /* PUSHAD */
+       {
+               Bitu tmpesp = reg_esp;
+               Push_32(reg_eax);Push_32(reg_ecx);Push_32(reg_edx);Push_32(reg_ebx);
+               Push_32(tmpesp);Push_32(reg_ebp);Push_32(reg_esi);Push_32(reg_edi);
+       }; break;
+       CASE_D(0x61)                                                                                            /* POPAD */
+               reg_edi=Pop_32();reg_esi=Pop_32();reg_ebp=Pop_32();Pop_32();//Don't save ESP
+               reg_ebx=Pop_32();reg_edx=Pop_32();reg_ecx=Pop_32();reg_eax=Pop_32();
+               break;
+       CASE_D(0x62)                                                                                            /* BOUND Ed */
+               {
+                       Bit32s bound_min, bound_max;
+                       GetRMrd;GetEAa;
+                       bound_min=LoadMd(eaa);
+                       bound_max=LoadMd(eaa+4);
+                       if ( (((Bit32s)*rmrd) < bound_min) || (((Bit32s)*rmrd) > bound_max) ) {
+                               EXCEPTION(5);
+                       }
+               }
+               break;
+       CASE_D(0x63)                                                                                            /* ARPL Ed,Rd */
+               {
+                       if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRMrw;
+                       if (rm >= 0xc0 ) {
+                               GetEArd;Bitu new_sel=(Bit16u)*eard;
+                               CPU_ARPL(new_sel,*rmrw);
+                               *eard=(Bit32u)new_sel;
+                       } else {
+                               GetEAa;Bitu new_sel=LoadMw(eaa);
+                               CPU_ARPL(new_sel,*rmrw);
+                               SaveMd(eaa,(Bit32u)new_sel);
+                       }
+               }
+               break;
+       CASE_D(0x68)                                                                                            /* PUSH Id */
+               Push_32(Fetchd());break;
+       CASE_D(0x69)                                                                                            /* IMUL Gd,Ed,Id */
+               RMGdEdOp3(DIMULD,Fetchds());
+               break;
+       CASE_D(0x6a)                                                                                            /* PUSH Ib */
+               Push_32(Fetchbs());break;
+       CASE_D(0x6b)                                                                                            /* IMUL Gd,Ed,Ib */
+               RMGdEdOp3(DIMULD,Fetchbs());
+               break;
+       CASE_D(0x6d)                                                                                            /* INSD */
+               if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
+               DoString(R_INSD);break;
+       CASE_D(0x6f)                                                                                            /* OUTSD */
+               if (CPU_IO_Exception(reg_dx,4)) RUNEXCEPTION();
+               DoString(R_OUTSD);break;
+       CASE_D(0x70)                                                                                            /* JO */
+               JumpCond32_b(TFLG_O);break;
+       CASE_D(0x71)                                                                                            /* JNO */
+               JumpCond32_b(TFLG_NO);break;
+       CASE_D(0x72)                                                                                            /* JB */
+               JumpCond32_b(TFLG_B);break;
+       CASE_D(0x73)                                                                                            /* JNB */
+               JumpCond32_b(TFLG_NB);break;
+       CASE_D(0x74)                                                                                            /* JZ */
+               JumpCond32_b(TFLG_Z);break;
+       CASE_D(0x75)                                                                                            /* JNZ */
+               JumpCond32_b(TFLG_NZ);break;
+       CASE_D(0x76)                                                                                            /* JBE */
+               JumpCond32_b(TFLG_BE);break;
+       CASE_D(0x77)                                                                                            /* JNBE */
+               JumpCond32_b(TFLG_NBE);break;
+       CASE_D(0x78)                                                                                            /* JS */
+               JumpCond32_b(TFLG_S);break;
+       CASE_D(0x79)                                                                                            /* JNS */
+               JumpCond32_b(TFLG_NS);break;
+       CASE_D(0x7a)                                                                                            /* JP */
+               JumpCond32_b(TFLG_P);break;
+       CASE_D(0x7b)                                                                                            /* JNP */
+               JumpCond32_b(TFLG_NP);break;
+       CASE_D(0x7c)                                                                                            /* JL */
+               JumpCond32_b(TFLG_L);break;
+       CASE_D(0x7d)                                                                                            /* JNL */
+               JumpCond32_b(TFLG_NL);break;
+       CASE_D(0x7e)                                                                                            /* JLE */
+               JumpCond32_b(TFLG_LE);break;
+       CASE_D(0x7f)                                                                                            /* JNLE */
+               JumpCond32_b(TFLG_NLE);break;
+       CASE_D(0x81)                                                                                            /* Grpl Ed,Id */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       if (rm >= 0xc0) {
+                               GetEArd;Bit32u id=Fetchd();
+                               switch (which) {
+                               case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x01: ORD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x06:XORD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break;
+                               }
+                       } else {
+                               GetEAa;Bit32u id=Fetchd();
+                               switch (which) {
+                               case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x01: ORD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x06:XORD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break;
+                               }
+                       }
+               }
+               break;
+       CASE_D(0x83)                                                                                            /* Grpl Ed,Ix */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       if (rm >= 0xc0) {
+                               GetEArd;Bit32u id=(Bit32s)Fetchbs();
+                               switch (which) {
+                               case 0x00:ADDD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x01: ORD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x02:ADCD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x03:SBBD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x04:ANDD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x05:SUBD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x06:XORD(*eard,id,LoadRd,SaveRd);break;
+                               case 0x07:CMPD(*eard,id,LoadRd,SaveRd);break;
+                               }
+                       } else {
+                               GetEAa;Bit32u id=(Bit32s)Fetchbs();
+                               switch (which) {
+                               case 0x00:ADDD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x01: ORD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x02:ADCD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x03:SBBD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x04:ANDD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x05:SUBD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x06:XORD(eaa,id,LoadMd,SaveMd);break;
+                               case 0x07:CMPD(eaa,id,LoadMd,SaveMd);break;
+                               }
+                       }
+               }
+               break;
+       CASE_D(0x85)                                                                                            /* TEST Ed,Gd */
+               RMEdGd(TESTD);break;
+       CASE_D(0x87)                                                                                            /* XCHG Ed,Gd */
+               {       
+                       GetRMrd;Bit32u oldrmrd=*rmrd;
+                       if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard=oldrmrd;}
+                       else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,oldrmrd);}
+                       break;
+               }
+       CASE_D(0x89)                                                                                            /* MOV Ed,Gd */
+               {       
+                       GetRMrd;
+                       if (rm >= 0xc0 ) {GetEArd;*eard=*rmrd;}
+                       else {GetEAa;SaveMd(eaa,*rmrd);}
+                       break;
+               }
+       CASE_D(0x8b)                                                                                            /* MOV Gd,Ed */
+               {       
+                       GetRMrd;
+                       if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;}
+                       else {GetEAa;*rmrd=LoadMd(eaa);}
+                       break;
+               }
+       CASE_D(0x8c)                                                                                            /* Mov Ew,Sw */
+                       {
+                               GetRM;Bit16u val;Bitu which=(rm>>3)&7;
+                               switch (which) {
+                               case 0x00:                                      /* MOV Ew,ES */
+                                       val=SegValue(es);break;
+                               case 0x01:                                      /* MOV Ew,CS */
+                                       val=SegValue(cs);break;
+                               case 0x02:                                      /* MOV Ew,SS */
+                                       val=SegValue(ss);break;
+                               case 0x03:                                      /* MOV Ew,DS */
+                                       val=SegValue(ds);break;
+                               case 0x04:                                      /* MOV Ew,FS */
+                                       val=SegValue(fs);break;
+                               case 0x05:                                      /* MOV Ew,GS */
+                                       val=SegValue(gs);break;
+                               default:
+                                       LOG(LOG_CPU,LOG_ERROR)("CPU:8c:Illegal RM Byte");
+                                       goto illegal_opcode;
+                               }
+                               if (rm >= 0xc0 ) {GetEArd;*eard=val;}
+                               else {GetEAa;SaveMw(eaa,val);}
+                               break;
+                       }       
+       CASE_D(0x8d)                                                                                            /* LEA Gd */
+               {
+                       //Little hack to always use segprefixed version
+                       GetRMrd;
+                       BaseDS=BaseSS=0;
+                       if (TEST_PREFIX_ADDR) {
+                               *rmrd=(Bit32u)(*EATable[256+rm])();
+                       } else {
+                               *rmrd=(Bit32u)(*EATable[rm])();
+                       }
+                       break;
+               }
+       CASE_D(0x8f)                                                                                            /* POP Ed */
+               {
+                       Bit32u val=Pop_32();
+                       GetRM;
+                       if (rm >= 0xc0 ) {GetEArd;*eard=val;}
+                       else {GetEAa;SaveMd(eaa,val);}
+                       break;
+               }
+       CASE_D(0x91)                                                                                            /* XCHG ECX,EAX */
+               { Bit32u temp=reg_eax;reg_eax=reg_ecx;reg_ecx=temp;break;}
+       CASE_D(0x92)                                                                                            /* XCHG EDX,EAX */
+               { Bit32u temp=reg_eax;reg_eax=reg_edx;reg_edx=temp;break;}
+               break;
+       CASE_D(0x93)                                                                                            /* XCHG EBX,EAX */
+               { Bit32u temp=reg_eax;reg_eax=reg_ebx;reg_ebx=temp;break;}
+               break;
+       CASE_D(0x94)                                                                                            /* XCHG ESP,EAX */
+               { Bit32u temp=reg_eax;reg_eax=reg_esp;reg_esp=temp;break;}
+               break;
+       CASE_D(0x95)                                                                                            /* XCHG EBP,EAX */
+               { Bit32u temp=reg_eax;reg_eax=reg_ebp;reg_ebp=temp;break;}
+               break;
+       CASE_D(0x96)                                                                                            /* XCHG ESI,EAX */
+               { Bit32u temp=reg_eax;reg_eax=reg_esi;reg_esi=temp;break;}
+               break;
+       CASE_D(0x97)                                                                                            /* XCHG EDI,EAX */
+               { Bit32u temp=reg_eax;reg_eax=reg_edi;reg_edi=temp;break;}
+               break;
+       CASE_D(0x98)                                                                                            /* CWDE */
+               reg_eax=(Bit16s)reg_ax;break;
+       CASE_D(0x99)                                                                                            /* CDQ */
+               if (reg_eax & 0x80000000) reg_edx=0xffffffff;
+               else reg_edx=0;
+               break;
+       CASE_D(0x9a)                                                                                            /* CALL FAR Ad */
+               { 
+                       Bit32u newip=Fetchd();Bit16u newcs=Fetchw();
+                       FillFlags();
+                       CPU_CALL(true,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                       if (GETFLAG(TF)) {      
+                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                               return CBRET_NONE;
+                       }
+#endif
+                       continue;
+               }
+       CASE_D(0x9c)                                                                                            /* PUSHFD */
+               if (CPU_PUSHF(true)) RUNEXCEPTION();
+               break;
+       CASE_D(0x9d)                                                                                            /* POPFD */
+               if (CPU_POPF(true)) RUNEXCEPTION();
+#if CPU_TRAP_CHECK
+               if (GETFLAG(TF)) {      
+                       cpudecoder=CPU_Core_Normal_Trap_Run;
+                       goto decode_end;
+               }
+#endif
+#if CPU_PIC_CHECK
+               if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
+#endif
+               break;
+       CASE_D(0xa1)                                                                                            /* MOV EAX,Od */
+               {
+                       GetEADirect;
+                       reg_eax=LoadMd(eaa);
+               }
+               break;
+       CASE_D(0xa3)                                                                                            /* MOV Od,EAX */
+               {
+                       GetEADirect;
+                       SaveMd(eaa,reg_eax);
+               }
+               break;
+       CASE_D(0xa5)                                                                                            /* MOVSD */
+               DoString(R_MOVSD);break;
+       CASE_D(0xa7)                                                                                            /* CMPSD */
+               DoString(R_CMPSD);break;
+       CASE_D(0xa9)                                                                                            /* TEST EAX,Id */
+               EAXId(TESTD);break;
+       CASE_D(0xab)                                                                                            /* STOSD */
+               DoString(R_STOSD);break;
+       CASE_D(0xad)                                                                                            /* LODSD */
+               DoString(R_LODSD);break;
+       CASE_D(0xaf)                                                                                            /* SCASD */
+               DoString(R_SCASD);break;
+       CASE_D(0xb8)                                                                                            /* MOV EAX,Id */
+               reg_eax=Fetchd();break;
+       CASE_D(0xb9)                                                                                            /* MOV ECX,Id */
+               reg_ecx=Fetchd();break;
+       CASE_D(0xba)                                                                                            /* MOV EDX,Iw */
+               reg_edx=Fetchd();break;
+       CASE_D(0xbb)                                                                                            /* MOV EBX,Id */
+               reg_ebx=Fetchd();break;
+       CASE_D(0xbc)                                                                                            /* MOV ESP,Id */
+               reg_esp=Fetchd();break;
+       CASE_D(0xbd)                                                                                            /* MOV EBP.Id */
+               reg_ebp=Fetchd();break;
+       CASE_D(0xbe)                                                                                            /* MOV ESI,Id */
+               reg_esi=Fetchd();break;
+       CASE_D(0xbf)                                                                                            /* MOV EDI,Id */
+               reg_edi=Fetchd();break;
+       CASE_D(0xc1)                                                                                            /* GRP2 Ed,Ib */
+               GRP2D(Fetchb());break;
+       CASE_D(0xc2)                                                                                            /* RETN Iw */
+               reg_eip=Pop_32();
+               reg_esp+=Fetchw();
+               continue;
+       CASE_D(0xc3)                                                                                            /* RETN */
+               reg_eip=Pop_32();
+               continue;
+       CASE_D(0xc4)                                                                                            /* LES */
+               {       
+                       GetRMrd;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(es,LoadMw(eaa+4))) RUNEXCEPTION();
+                       *rmrd=LoadMd(eaa);
+                       break;
+               }
+       CASE_D(0xc5)                                                                                            /* LDS */
+               {       
+                       GetRMrd;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(ds,LoadMw(eaa+4))) RUNEXCEPTION();
+                       *rmrd=LoadMd(eaa);
+                       break;
+               }
+       CASE_D(0xc7)                                                                                            /* MOV Ed,Id */
+               {
+                       GetRM;
+                       if (rm >= 0xc0) {GetEArd;*eard=Fetchd();}
+                       else {GetEAa;SaveMd(eaa,Fetchd());}
+                       break;
+               }
+       CASE_D(0xc8)                                                                                            /* ENTER Iw,Ib */
+               {
+                       Bitu bytes=Fetchw();
+                       Bitu level=Fetchb();
+                       CPU_ENTER(true,bytes,level);
+               }
+               break;
+       CASE_D(0xc9)                                                                                            /* LEAVE */
+               reg_esp&=cpu.stack.notmask;
+               reg_esp|=(reg_ebp&cpu.stack.mask);
+               reg_ebp=Pop_32();
+               break;
+       CASE_D(0xca)                                                                                            /* RETF Iw */
+               { 
+                       Bitu words=Fetchw();
+                       FillFlags();
+                       CPU_RET(true,words,GETIP);
+                       continue;
+               }
+       CASE_D(0xcb)                                                                                            /* RETF */                      
+               { 
+                       FillFlags();
+            CPU_RET(true,0,GETIP);
+                       continue;
+               }
+       CASE_D(0xcf)                                                                                            /* IRET */
+               {
+                       CPU_IRET(true,GETIP);
+#if CPU_TRAP_CHECK
+                       if (GETFLAG(TF)) {      
+                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                               return CBRET_NONE;
+                       }
+#endif
+#if CPU_PIC_CHECK
+                       if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
+#endif
+                       continue;
+               }
+       CASE_D(0xd1)                                                                                            /* GRP2 Ed,1 */
+               GRP2D(1);break;
+       CASE_D(0xd3)                                                                                            /* GRP2 Ed,CL */
+               GRP2D(reg_cl);break;
+       CASE_D(0xe0)                                                                                            /* LOOPNZ */
+               if (TEST_PREFIX_ADDR) {
+                       JumpCond32_b(--reg_ecx && !get_ZF());
+               } else {
+                       JumpCond32_b(--reg_cx && !get_ZF());
+               }
+               break;
+       CASE_D(0xe1)                                                                                            /* LOOPZ */
+               if (TEST_PREFIX_ADDR) {
+                       JumpCond32_b(--reg_ecx && get_ZF());
+               } else {
+                       JumpCond32_b(--reg_cx && get_ZF());
+               }
+               break;
+       CASE_D(0xe2)                                                                                            /* LOOP */
+               if (TEST_PREFIX_ADDR) { 
+                       JumpCond32_b(--reg_ecx);
+               } else {
+                       JumpCond32_b(--reg_cx);
+               }
+               break;
+       CASE_D(0xe3)                                                                                            /* JCXZ */
+               JumpCond32_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
+               break;
+       CASE_D(0xe5)                                                                                            /* IN EAX,Ib */
+               {
+                       Bitu port=Fetchb();
+                       if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
+                       reg_eax=IO_ReadD(port);
+                       break;
+               }
+       CASE_D(0xe7)                                                                                            /* OUT Ib,EAX */
+               {
+                       Bitu port=Fetchb();
+                       if (CPU_IO_Exception(port,4)) RUNEXCEPTION();
+                       IO_WriteD(port,reg_eax);
+                       break;
+               }
+       CASE_D(0xe8)                                                                                            /* CALL Jd */
+               { 
+                       Bit32s addip=Fetchds();
+                       SAVEIP;
+                       Push_32(reg_eip);
+                       reg_eip+=addip;
+                       continue;
+               }
+       CASE_D(0xe9)                                                                                            /* JMP Jd */
+               { 
+                       Bit32s addip=Fetchds();
+                       SAVEIP;
+                       reg_eip+=addip;
+                       continue;
+               }
+       CASE_D(0xea)                                                                                            /* JMP Ad */
+               { 
+                       Bit32u newip=Fetchd();
+                       Bit16u newcs=Fetchw();
+                       FillFlags();
+                       CPU_JMP(true,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                       if (GETFLAG(TF)) {      
+                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                               return CBRET_NONE;
+                       }
+#endif
+                       continue;
+               }
+       CASE_D(0xeb)                                                                                            /* JMP Jb */
+               { 
+                       Bit32s addip=Fetchbs();
+                       SAVEIP;
+                       reg_eip+=addip;
+                       continue;
+               }
+       CASE_D(0xed)                                                                                            /* IN EAX,DX */
+               reg_eax=IO_ReadD(reg_dx);
+               break;
+       CASE_D(0xef)                                                                                            /* OUT DX,EAX */
+               IO_WriteD(reg_dx,reg_eax);
+               break;
+       CASE_D(0xf7)                                                                                            /* GRP3 Ed(,Id) */
+               { 
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:                                                                                      /* TEST Ed,Id */
+                       case 0x01:                                                                                      /* TEST Ed,Id Undocumented*/
+                               {
+                                       if (rm >= 0xc0 ) {GetEArd;TESTD(*eard,Fetchd(),LoadRd,SaveRd);}
+                                       else {GetEAa;TESTD(eaa,Fetchd(),LoadMd,SaveMd);}
+                                       break;
+                               }
+                       case 0x02:                                                                                      /* NOT Ed */
+                               {
+                                       if (rm >= 0xc0 ) {GetEArd;*eard=~*eard;}
+                                       else {GetEAa;SaveMd(eaa,~LoadMd(eaa));}
+                                       break;
+                               }
+                       case 0x03:                                                                                      /* NEG Ed */
+                               {
+                                       lflags.type=t_NEGd;
+                                       if (rm >= 0xc0 ) {
+                                                       GetEArd;lf_var1d=*eard;lf_resd=0-lf_var1d;
+                                               *eard=lf_resd;
+                                       } else {
+                                               GetEAa;lf_var1d=LoadMd(eaa);lf_resd=0-lf_var1d;
+                                                       SaveMd(eaa,lf_resd);
+                                       }
+                                       break;
+                               }
+                       case 0x04:                                                                                      /* MUL EAX,Ed */
+                               RMEd(MULD);
+                               break;
+                       case 0x05:                                                                                      /* IMUL EAX,Ed */
+                               RMEd(IMULD);
+                               break;
+                       case 0x06:                                                                                      /* DIV Ed */
+                               RMEd(DIVD);
+                               break;
+                       case 0x07:                                                                                      /* IDIV Ed */
+                               RMEd(IDIVD);
+                               break;
+                       }
+                       break;
+               }
+       CASE_D(0xff)                                                                                            /* GRP 5 Ed */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:                                                                                      /* INC Ed */
+                               RMEd(INCD);
+                               break;          
+                       case 0x01:                                                                                      /* DEC Ed */
+                               RMEd(DECD);
+                               break;
+                       case 0x02:                                                                                      /* CALL NEAR Ed */
+                               if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
+                               else {GetEAa;reg_eip=LoadMd(eaa);}
+                               Push_32(GETIP);
+                               continue;
+                       case 0x03:                                                                                      /* CALL FAR Ed */
+                               {
+                                       if (rm >= 0xc0) goto illegal_opcode;
+                                       GetEAa;
+                                       Bit32u newip=LoadMd(eaa);
+                                       Bit16u newcs=LoadMw(eaa+4);
+                                       FillFlags();
+                                       CPU_CALL(true,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                                       if (GETFLAG(TF)) {      
+                                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                                               return CBRET_NONE;
+                                       }
+#endif
+                                       continue;
+                               }
+                       case 0x04:                                                                                      /* JMP NEAR Ed */       
+                               if (rm >= 0xc0 ) {GetEArd;reg_eip=*eard;}
+                               else {GetEAa;reg_eip=LoadMd(eaa);}
+                               continue;
+                       case 0x05:                                                                                      /* JMP FAR Ed */        
+                               {
+                                       if (rm >= 0xc0) goto illegal_opcode;
+                                       GetEAa;
+                                       Bit32u newip=LoadMd(eaa);
+                                       Bit16u newcs=LoadMw(eaa+4);
+                                       FillFlags();
+                                       CPU_JMP(true,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                                       if (GETFLAG(TF)) {      
+                                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                                               return CBRET_NONE;
+                                       }
+#endif
+                                       continue;
+                               }
+                               break;
+                       case 0x06:                                                                                      /* Push Ed */
+                               if (rm >= 0xc0 ) {GetEArd;Push_32(*eard);}
+                               else {GetEAa;Push_32(LoadMd(eaa));}
+                               break;
+                       default:
+                               LOG(LOG_CPU,LOG_ERROR)("CPU:66:GRP5:Illegal call %2X",which);
+                               goto illegal_opcode;
+                       }
+                       break;
+               }
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_66_0f.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_66_0f.h
new file mode 100644 (file)
index 0000000..8f41f9a
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+       CASE_0F_D(0x00)                                                                                         /* GRP 6 Exxx */
+               {
+                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:      /* SLDT */
+                       case 0x01:      /* STR */
+                               {
+                                       Bitu saveval;
+                                       if (!which) saveval=CPU_SLDT();
+                                       else saveval=CPU_STR();
+                                       if (rm >= 0xc0) {GetEArw;*earw=(Bit16u)saveval;}
+                                       else {GetEAa;SaveMw(eaa,saveval);}
+                               }
+                               break;
+                       case 0x02:case 0x03:case 0x04:case 0x05:
+                               {
+                                       /* Just use 16-bit loads since were only using selectors */
+                                       Bitu loadval;
+                                       if (rm >= 0xc0 ) {GetEArw;loadval=*earw;}
+                                       else {GetEAa;loadval=LoadMw(eaa);}
+                                       switch (which) {
+                                       case 0x02:
+                                               if (cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                               if (CPU_LLDT(loadval)) RUNEXCEPTION();
+                                               break;
+                                       case 0x03:
+                                               if (cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                               if (CPU_LTR(loadval)) RUNEXCEPTION();
+                                               break;
+                                       case 0x04:
+                                               CPU_VERR(loadval);
+                                               break;
+                                       case 0x05:
+                                               CPU_VERW(loadval);
+                                               break;
+                                       }
+                               }
+                               break;
+                       default:
+                               LOG(LOG_CPU,LOG_ERROR)("GRP6:Illegal call %2X",which);
+                               goto illegal_opcode;
+                       }
+               }
+               break;
+       CASE_0F_D(0x01)                                                                                         /* Group 7 Ed */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       if (rm < 0xc0)  { //First ones all use EA
+                               GetEAa;Bitu limit;
+                               switch (which) {
+                               case 0x00:                                                                              /* SGDT */
+                                       SaveMw(eaa,(Bit16u)CPU_SGDT_limit());
+                                       SaveMd(eaa+2,(Bit32u)CPU_SGDT_base());
+                                       break;
+                               case 0x01:                                                                              /* SIDT */
+                                       SaveMw(eaa,(Bit16u)CPU_SIDT_limit());
+                                       SaveMd(eaa+2,(Bit32u)CPU_SIDT_base());
+                                       break;
+                               case 0x02:                                                                              /* LGDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       CPU_LGDT(LoadMw(eaa),LoadMd(eaa+2));
+                                       break;
+                               case 0x03:                                                                              /* LIDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2));
+                                       break;
+                               case 0x04:                                                                              /* SMSW */
+                                       SaveMw(eaa,(Bit16u)CPU_SMSW());
+                                       break;
+                               case 0x06:                                                                              /* LMSW */
+                                       limit=LoadMw(eaa);
+                                       if (CPU_LMSW((Bit16u)limit)) RUNEXCEPTION();
+                                       break;
+                               case 0x07:                                                                              /* INVLPG */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       PAGING_ClearTLB();
+                                       break;
+                               }
+                       } else {
+                               GetEArd;
+                               switch (which) {
+                               case 0x02:                                                                              /* LGDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       goto illegal_opcode;
+                               case 0x03:                                                                              /* LIDT */
+                                       if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+                                       goto illegal_opcode;
+                               case 0x04:                                                                              /* SMSW */
+                                       *eard=(Bit32u)CPU_SMSW();
+                                       break;
+                               case 0x06:                                                                              /* LMSW */
+                                       if (CPU_LMSW(*eard)) RUNEXCEPTION();
+                                       break;
+                               default:
+                                       LOG(LOG_CPU,LOG_ERROR)("Illegal group 7 RM subfunction %d",which);
+                                       goto illegal_opcode;
+                                       break;
+                               }
+
+                       }
+               }
+               break;
+       CASE_0F_D(0x02)                                                                                         /* LAR Gd,Ed */
+               {
+                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRMrd;Bitu ar=*rmrd;
+                       if (rm >= 0xc0) {
+                               GetEArw;CPU_LAR(*earw,ar);
+                       } else {
+                               GetEAa;CPU_LAR(LoadMw(eaa),ar);
+                       }
+                       *rmrd=(Bit32u)ar;
+               }
+               break;
+       CASE_0F_D(0x03)                                                                                         /* LSL Gd,Ew */
+               {
+                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRMrd;Bitu limit=*rmrd;
+                       /* Just load 16-bit values for selectors */
+                       if (rm >= 0xc0) {
+                               GetEArw;CPU_LSL(*earw,limit);
+                       } else {
+                               GetEAa;CPU_LSL(LoadMw(eaa),limit);
+                       }
+                       *rmrd=(Bit32u)limit;
+               }
+               break;
+       CASE_0F_D(0x80)                                                                                         /* JO */
+               JumpCond32_d(TFLG_O);break;
+       CASE_0F_D(0x81)                                                                                         /* JNO */
+               JumpCond32_d(TFLG_NO);break;
+       CASE_0F_D(0x82)                                                                                         /* JB */
+               JumpCond32_d(TFLG_B);break;
+       CASE_0F_D(0x83)                                                                                         /* JNB */
+               JumpCond32_d(TFLG_NB);break;
+       CASE_0F_D(0x84)                                                                                         /* JZ */
+               JumpCond32_d(TFLG_Z);break;
+       CASE_0F_D(0x85)                                                                                         /* JNZ */
+               JumpCond32_d(TFLG_NZ);break;
+       CASE_0F_D(0x86)                                                                                         /* JBE */
+               JumpCond32_d(TFLG_BE);break;
+       CASE_0F_D(0x87)                                                                                         /* JNBE */
+               JumpCond32_d(TFLG_NBE);break;
+       CASE_0F_D(0x88)                                                                                         /* JS */
+               JumpCond32_d(TFLG_S);break;
+       CASE_0F_D(0x89)                                                                                         /* JNS */
+               JumpCond32_d(TFLG_NS);break;
+       CASE_0F_D(0x8a)                                                                                         /* JP */
+               JumpCond32_d(TFLG_P);break;
+       CASE_0F_D(0x8b)                                                                                         /* JNP */
+               JumpCond32_d(TFLG_NP);break;
+       CASE_0F_D(0x8c)                                                                                         /* JL */
+               JumpCond32_d(TFLG_L);break;
+       CASE_0F_D(0x8d)                                                                                         /* JNL */
+               JumpCond32_d(TFLG_NL);break;
+       CASE_0F_D(0x8e)                                                                                         /* JLE */
+               JumpCond32_d(TFLG_LE);break;
+       CASE_0F_D(0x8f)                                                                                         /* JNLE */
+               JumpCond32_d(TFLG_NLE);break;
+       
+       CASE_0F_D(0xa0)                                                                                         /* PUSH FS */           
+               Push_32(SegValue(fs));break;
+       CASE_0F_D(0xa1)                                                                                         /* POP FS */            
+               if (CPU_PopSeg(fs,true)) RUNEXCEPTION();
+               break;
+       CASE_0F_D(0xa3)                                                                                         /* BT Ed,Gd */
+               {
+                       FillFlags();GetRMrd;
+                       Bit32u mask=1 << (*rmrd & 31);
+                       if (rm >= 0xc0 ) {
+                               GetEArd;
+                               SETFLAGBIT(CF,(*eard & mask));
+                       } else {
+                               GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4;
+                               Bit32u old=LoadMd(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                       }
+                       break;
+               }
+       CASE_0F_D(0xa4)                                                                                         /* SHLD Ed,Gd,Ib */
+               RMEdGdOp3(DSHLD,Fetchb());
+               break;
+       CASE_0F_D(0xa5)                                                                                         /* SHLD Ed,Gd,CL */
+               RMEdGdOp3(DSHLD,reg_cl);
+               break;
+       CASE_0F_D(0xa8)                                                                                         /* PUSH GS */           
+               Push_32(SegValue(gs));break;
+       CASE_0F_D(0xa9)                                                                                         /* POP GS */            
+               if (CPU_PopSeg(gs,true)) RUNEXCEPTION();
+               break;
+       CASE_0F_D(0xab)                                                                                         /* BTS Ed,Gd */
+               {
+                       FillFlags();GetRMrd;
+                       Bit32u mask=1 << (*rmrd & 31);
+                       if (rm >= 0xc0 ) {
+                               GetEArd;
+                               SETFLAGBIT(CF,(*eard & mask));
+                               *eard|=mask;
+                       } else {
+                               GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4;
+                               Bit32u old=LoadMd(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                               SaveMd(eaa,old | mask);
+                       }
+                       break;
+               }
+       
+       CASE_0F_D(0xac)                                                                                         /* SHRD Ed,Gd,Ib */
+               RMEdGdOp3(DSHRD,Fetchb());
+               break;
+       CASE_0F_D(0xad)                                                                                         /* SHRD Ed,Gd,CL */
+               RMEdGdOp3(DSHRD,reg_cl);
+               break;
+       CASE_0F_D(0xaf)                                                                                         /* IMUL Gd,Ed */
+               {
+                       RMGdEdOp3(DIMULD,*rmrd);
+                       break;
+               }
+       CASE_0F_D(0xb1)                                                                                         /* CMPXCHG Ed,Gd */
+               {       
+                       if (CPU_ArchitectureType<CPU_ARCHTYPE_486NEWSLOW) goto illegal_opcode;
+                       FillFlags();
+                       GetRMrd;
+                       if (rm >= 0xc0) {
+                               GetEArd;
+                               if (*eard==reg_eax) {
+                                       *eard=*rmrd;
+                                       SETFLAGBIT(ZF,1);
+                               } else {
+                                       reg_eax=*eard;
+                                       SETFLAGBIT(ZF,0);
+                               }
+                       } else {
+                               GetEAa;
+                               Bit32u val=LoadMd(eaa);
+                               if (val==reg_eax) {
+                                       SaveMd(eaa,*rmrd);
+                                       SETFLAGBIT(ZF,1);
+                               } else {
+                                       SaveMd(eaa,val);        // cmpxchg always issues a write
+                                       reg_eax=val;
+                                       SETFLAGBIT(ZF,0);
+                               }
+                       }
+                       break;
+               }
+       CASE_0F_D(0xb2)                                                                                         /* LSS Ed */
+               {       
+                       GetRMrd;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(ss,LoadMw(eaa+4))) RUNEXCEPTION();
+                       *rmrd=LoadMd(eaa);
+                       break;
+               }
+       CASE_0F_D(0xb3)                                                                                         /* BTR Ed,Gd */
+               {
+                       FillFlags();GetRMrd;
+                       Bit32u mask=1 << (*rmrd & 31);
+                       if (rm >= 0xc0 ) {
+                               GetEArd;
+                               SETFLAGBIT(CF,(*eard & mask));
+                               *eard&= ~mask;
+                       } else {
+                               GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4;
+                               Bit32u old=LoadMd(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                               SaveMd(eaa,old & ~mask);
+                       }
+                       break;
+               }
+       CASE_0F_D(0xb4)                                                                                         /* LFS Ed */
+               {       
+                       GetRMrd;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(fs,LoadMw(eaa+4))) RUNEXCEPTION();
+                       *rmrd=LoadMd(eaa);
+                       break;
+               }
+       CASE_0F_D(0xb5)                                                                                         /* LGS Ed */
+               {       
+                       GetRMrd;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(gs,LoadMw(eaa+4))) RUNEXCEPTION();
+                       *rmrd=LoadMd(eaa);
+                       break;
+               }
+       CASE_0F_D(0xb6)                                                                                         /* MOVZX Gd,Eb */
+               {
+                       GetRMrd;                                                                                                                        
+                       if (rm >= 0xc0 ) {GetEArb;*rmrd=*earb;}
+                       else {GetEAa;*rmrd=LoadMb(eaa);}
+                       break;
+               }
+       CASE_0F_D(0xb7)                                                                                         /* MOVXZ Gd,Ew */
+               {
+                       GetRMrd;
+                       if (rm >= 0xc0 ) {GetEArw;*rmrd=*earw;}
+                       else {GetEAa;*rmrd=LoadMw(eaa);}
+                       break;
+               }
+       CASE_0F_D(0xba)                                                                                         /* GRP8 Ed,Ib */
+               {
+                       FillFlags();GetRM;
+                       if (rm >= 0xc0 ) {
+                               GetEArd;
+                               Bit32u mask=1 << (Fetchb() & 31);
+                               SETFLAGBIT(CF,(*eard & mask));
+                               switch (rm & 0x38) {
+                               case 0x20:                                                                                      /* BT */
+                                       break;
+                               case 0x28:                                                                                      /* BTS */
+                                       *eard|=mask;
+                                       break;
+                               case 0x30:                                                                                      /* BTR */
+                                       *eard&=~mask;
+                                       break;
+                               case 0x38:                                                                                      /* BTC */
+                                       if (GETFLAG(CF)) *eard&=~mask;
+                                       else *eard|=mask;
+                                       break;
+                               default:
+                                       E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38);
+                               }
+                       } else {
+                               GetEAa;Bit32u old=LoadMd(eaa);
+                               Bit32u mask=1 << (Fetchb() & 31);
+                               SETFLAGBIT(CF,(old & mask));
+                               switch (rm & 0x38) {
+                               case 0x20:                                                                                      /* BT */
+                                       break;
+                               case 0x28:                                                                                      /* BTS */
+                                       SaveMd(eaa,old|mask);
+                                       break;
+                               case 0x30:                                                                                      /* BTR */
+                                       SaveMd(eaa,old & ~mask);
+                                       break;
+                               case 0x38:                                                                                      /* BTC */
+                                       if (GETFLAG(CF)) old&=~mask;
+                                       else old|=mask;
+                                       SaveMd(eaa,old);
+                                       break;
+                               default:
+                                       E_Exit("CPU:66:0F:BA:Illegal subfunction %X",rm & 0x38);
+                               }
+                       }
+                       break;
+               }
+       CASE_0F_D(0xbb)                                                                                         /* BTC Ed,Gd */
+               {
+                       FillFlags();GetRMrd;
+                       Bit32u mask=1 << (*rmrd & 31);
+                       if (rm >= 0xc0 ) {
+                               GetEArd;
+                               SETFLAGBIT(CF,(*eard & mask));
+                               *eard^=mask;
+                       } else {
+                               GetEAa;eaa+=(((Bit32s)*rmrd)>>5)*4;
+                               Bit32u old=LoadMd(eaa);
+                               SETFLAGBIT(CF,(old & mask));
+                               SaveMd(eaa,old ^ mask);
+                       }
+                       break;
+               }
+       CASE_0F_D(0xbc)                                                                                         /* BSF Gd,Ed */
+               {
+                       GetRMrd;
+                       Bit32u result,value;
+                       if (rm >= 0xc0) { GetEArd; value=*eard; } 
+                       else                    { GetEAa; value=LoadMd(eaa); }
+                       if (value==0) {
+                               SETFLAGBIT(ZF,true);
+                       } else {
+                               result = 0;
+                               while ((value & 0x01)==0) { result++; value>>=1; }
+                               SETFLAGBIT(ZF,false);
+                               *rmrd = result;
+                       }
+                       lflags.type=t_UNKNOWN;
+                       break;
+               }
+       CASE_0F_D(0xbd)                                                                                         /*  BSR Gd,Ed */
+               {
+                       GetRMrd;
+                       Bit32u result,value;
+                       if (rm >= 0xc0) { GetEArd; value=*eard; } 
+                       else                    { GetEAa; value=LoadMd(eaa); }
+                       if (value==0) {
+                               SETFLAGBIT(ZF,true);
+                       } else {
+                               result = 31;    // Operandsize-1
+                               while ((value & 0x80000000)==0) { result--; value<<=1; }
+                               SETFLAGBIT(ZF,false);
+                               *rmrd = result;
+                       }
+                       lflags.type=t_UNKNOWN;
+                       break;
+               }
+       CASE_0F_D(0xbe)                                                                                         /* MOVSX Gd,Eb */
+               {
+                       GetRMrd;                                                                                                                        
+                       if (rm >= 0xc0 ) {GetEArb;*rmrd=*(Bit8s *)earb;}
+                       else {GetEAa;*rmrd=LoadMbs(eaa);}
+                       break;
+               }
+       CASE_0F_D(0xbf)                                                                                         /* MOVSX Gd,Ew */
+               {
+                       GetRMrd;                                                                                                                        
+                       if (rm >= 0xc0 ) {GetEArw;*rmrd=*(Bit16s *)earw;}
+                       else {GetEAa;*rmrd=LoadMws(eaa);}
+                       break;
+               }
+       CASE_0F_D(0xc1)                                                                                         /* XADD Gd,Ed */
+               {
+                       if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+                       GetRMrd;Bit32u oldrmrd=*rmrd;
+                       if (rm >= 0xc0 ) {GetEArd;*rmrd=*eard;*eard+=oldrmrd;}
+                       else {GetEAa;*rmrd=LoadMd(eaa);SaveMd(eaa,LoadMd(eaa)+oldrmrd);}
+                       break;
+               }
+       CASE_0F_D(0xc8)                                                                                         /* BSWAP EAX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_eax);break;
+       CASE_0F_D(0xc9)                                                                                         /* BSWAP ECX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_ecx);break;
+       CASE_0F_D(0xca)                                                                                         /* BSWAP EDX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_edx);break;
+       CASE_0F_D(0xcb)                                                                                         /* BSWAP EBX */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_ebx);break;
+       CASE_0F_D(0xcc)                                                                                         /* BSWAP ESP */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_esp);break;
+       CASE_0F_D(0xcd)                                                                                         /* BSWAP EBP */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_ebp);break;
+       CASE_0F_D(0xce)                                                                                         /* BSWAP ESI */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_esi);break;
+       CASE_0F_D(0xcf)                                                                                         /* BSWAP EDI */
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) goto illegal_opcode;
+               BSWAPD(reg_edi);break;
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_none.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/prefix_none.h
new file mode 100644 (file)
index 0000000..63f81ff
--- /dev/null
@@ -0,0 +1,1176 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+       CASE_B(0x00)                                                                                            /* ADD Eb,Gb */
+               RMEbGb(ADDB);break;
+       CASE_W(0x01)                                                                                            /* ADD Ew,Gw */
+               RMEwGw(ADDW);break;     
+       CASE_B(0x02)                                                                                            /* ADD Gb,Eb */
+               RMGbEb(ADDB);break;
+       CASE_W(0x03)                                                                                            /* ADD Gw,Ew */
+               RMGwEw(ADDW);break;
+       CASE_B(0x04)                                                                                            /* ADD AL,Ib */
+               ALIb(ADDB);break;
+       CASE_W(0x05)                                                                                            /* ADD AX,Iw */
+               AXIw(ADDW);break;
+       CASE_W(0x06)                                                                                            /* PUSH ES */           
+               Push_16(SegValue(es));break;
+       CASE_W(0x07)                                                                                            /* POP ES */
+               if (CPU_PopSeg(es,false)) RUNEXCEPTION();
+               break;
+       CASE_B(0x08)                                                                                            /* OR Eb,Gb */
+               RMEbGb(ORB);break;
+       CASE_W(0x09)                                                                                            /* OR Ew,Gw */
+               RMEwGw(ORW);break;
+       CASE_B(0x0a)                                                                                            /* OR Gb,Eb */
+               RMGbEb(ORB);break;
+       CASE_W(0x0b)                                                                                            /* OR Gw,Ew */
+               RMGwEw(ORW);break;
+       CASE_B(0x0c)                                                                                            /* OR AL,Ib */
+               ALIb(ORB);break;
+       CASE_W(0x0d)                                                                                            /* OR AX,Iw */
+               AXIw(ORW);break;
+       CASE_W(0x0e)                                                                                            /* PUSH CS */           
+               Push_16(SegValue(cs));break;
+       CASE_B(0x0f)                                                                                            /* 2 byte opcodes*/             
+               core.opcode_index|=OPCODE_0F;
+               goto restart_opcode;
+               break;
+       CASE_B(0x10)                                                                                            /* ADC Eb,Gb */
+               RMEbGb(ADCB);break;
+       CASE_W(0x11)                                                                                            /* ADC Ew,Gw */
+               RMEwGw(ADCW);break;     
+       CASE_B(0x12)                                                                                            /* ADC Gb,Eb */
+               RMGbEb(ADCB);break;
+       CASE_W(0x13)                                                                                            /* ADC Gw,Ew */
+               RMGwEw(ADCW);break;
+       CASE_B(0x14)                                                                                            /* ADC AL,Ib */
+               ALIb(ADCB);break;
+       CASE_W(0x15)                                                                                            /* ADC AX,Iw */
+               AXIw(ADCW);break;
+       CASE_W(0x16)                                                                                            /* PUSH SS */           
+               Push_16(SegValue(ss));break;
+       CASE_W(0x17)                                                                                            /* POP SS */            
+               if (CPU_PopSeg(ss,false)) RUNEXCEPTION();
+               CPU_Cycles++; //Always do another instruction
+               break;
+       CASE_B(0x18)                                                                                            /* SBB Eb,Gb */
+               RMEbGb(SBBB);break;
+       CASE_W(0x19)                                                                                            /* SBB Ew,Gw */
+               RMEwGw(SBBW);break;
+       CASE_B(0x1a)                                                                                            /* SBB Gb,Eb */
+               RMGbEb(SBBB);break;
+       CASE_W(0x1b)                                                                                            /* SBB Gw,Ew */
+               RMGwEw(SBBW);break;
+       CASE_B(0x1c)                                                                                            /* SBB AL,Ib */
+               ALIb(SBBB);break;
+       CASE_W(0x1d)                                                                                            /* SBB AX,Iw */
+               AXIw(SBBW);break;
+       CASE_W(0x1e)                                                                                            /* PUSH DS */           
+               Push_16(SegValue(ds));break;
+       CASE_W(0x1f)                                                                                            /* POP DS */
+               if (CPU_PopSeg(ds,false)) RUNEXCEPTION();
+               break;
+       CASE_B(0x20)                                                                                            /* AND Eb,Gb */
+               RMEbGb(ANDB);break;
+       CASE_W(0x21)                                                                                            /* AND Ew,Gw */
+               RMEwGw(ANDW);break;     
+       CASE_B(0x22)                                                                                            /* AND Gb,Eb */
+               RMGbEb(ANDB);break;
+       CASE_W(0x23)                                                                                            /* AND Gw,Ew */
+               RMGwEw(ANDW);break;
+       CASE_B(0x24)                                                                                            /* AND AL,Ib */
+               ALIb(ANDB);break;
+       CASE_W(0x25)                                                                                            /* AND AX,Iw */
+               AXIw(ANDW);break;
+       CASE_B(0x26)                                                                                            /* SEG ES: */
+               DO_PREFIX_SEG(es);break;
+       CASE_B(0x27)                                                                                            /* DAA */
+               DAA();break;
+       CASE_B(0x28)                                                                                            /* SUB Eb,Gb */
+               RMEbGb(SUBB);break;
+       CASE_W(0x29)                                                                                            /* SUB Ew,Gw */
+               RMEwGw(SUBW);break;
+       CASE_B(0x2a)                                                                                            /* SUB Gb,Eb */
+               RMGbEb(SUBB);break;
+       CASE_W(0x2b)                                                                                            /* SUB Gw,Ew */
+               RMGwEw(SUBW);break;
+       CASE_B(0x2c)                                                                                            /* SUB AL,Ib */
+               ALIb(SUBB);break;
+       CASE_W(0x2d)                                                                                            /* SUB AX,Iw */
+               AXIw(SUBW);break;
+       CASE_B(0x2e)                                                                                            /* SEG CS: */
+               DO_PREFIX_SEG(cs);break;
+       CASE_B(0x2f)                                                                                            /* DAS */
+               DAS();break;  
+       CASE_B(0x30)                                                                                            /* XOR Eb,Gb */
+               RMEbGb(XORB);break;
+       CASE_W(0x31)                                                                                            /* XOR Ew,Gw */
+               RMEwGw(XORW);break;     
+       CASE_B(0x32)                                                                                            /* XOR Gb,Eb */
+               RMGbEb(XORB);break;
+       CASE_W(0x33)                                                                                            /* XOR Gw,Ew */
+               RMGwEw(XORW);break;
+       CASE_B(0x34)                                                                                            /* XOR AL,Ib */
+               ALIb(XORB);break;
+       CASE_W(0x35)                                                                                            /* XOR AX,Iw */
+               AXIw(XORW);break;
+       CASE_B(0x36)                                                                                            /* SEG SS: */
+               DO_PREFIX_SEG(ss);break;
+       CASE_B(0x37)                                                                                            /* AAA */
+               AAA();break;  
+       CASE_B(0x38)                                                                                            /* CMP Eb,Gb */
+               RMEbGb(CMPB);break;
+       CASE_W(0x39)                                                                                            /* CMP Ew,Gw */
+               RMEwGw(CMPW);break;
+       CASE_B(0x3a)                                                                                            /* CMP Gb,Eb */
+               RMGbEb(CMPB);break;
+       CASE_W(0x3b)                                                                                            /* CMP Gw,Ew */
+               RMGwEw(CMPW);break;
+       CASE_B(0x3c)                                                                                            /* CMP AL,Ib */
+               ALIb(CMPB);break;
+       CASE_W(0x3d)                                                                                            /* CMP AX,Iw */
+               AXIw(CMPW);break;
+       CASE_B(0x3e)                                                                                            /* SEG DS: */
+               DO_PREFIX_SEG(ds);break;
+       CASE_B(0x3f)                                                                                            /* AAS */
+               AAS();break;
+       CASE_W(0x40)                                                                                            /* INC AX */
+               INCW(reg_ax,LoadRw,SaveRw);break;
+       CASE_W(0x41)                                                                                            /* INC CX */
+               INCW(reg_cx,LoadRw,SaveRw);break;
+       CASE_W(0x42)                                                                                            /* INC DX */
+               INCW(reg_dx,LoadRw,SaveRw);break;
+       CASE_W(0x43)                                                                                            /* INC BX */
+               INCW(reg_bx,LoadRw,SaveRw);break;
+       CASE_W(0x44)                                                                                            /* INC SP */
+               INCW(reg_sp,LoadRw,SaveRw);break;
+       CASE_W(0x45)                                                                                            /* INC BP */
+               INCW(reg_bp,LoadRw,SaveRw);break;
+       CASE_W(0x46)                                                                                            /* INC SI */
+               INCW(reg_si,LoadRw,SaveRw);break;
+       CASE_W(0x47)                                                                                            /* INC DI */
+               INCW(reg_di,LoadRw,SaveRw);break;
+       CASE_W(0x48)                                                                                            /* DEC AX */
+               DECW(reg_ax,LoadRw,SaveRw);break;
+       CASE_W(0x49)                                                                                            /* DEC CX */
+               DECW(reg_cx,LoadRw,SaveRw);break;
+       CASE_W(0x4a)                                                                                            /* DEC DX */
+               DECW(reg_dx,LoadRw,SaveRw);break;
+       CASE_W(0x4b)                                                                                            /* DEC BX */
+               DECW(reg_bx,LoadRw,SaveRw);break;
+       CASE_W(0x4c)                                                                                            /* DEC SP */
+               DECW(reg_sp,LoadRw,SaveRw);break;
+       CASE_W(0x4d)                                                                                            /* DEC BP */
+               DECW(reg_bp,LoadRw,SaveRw);break;
+       CASE_W(0x4e)                                                                                            /* DEC SI */
+               DECW(reg_si,LoadRw,SaveRw);break;
+       CASE_W(0x4f)                                                                                            /* DEC DI */
+               DECW(reg_di,LoadRw,SaveRw);break;
+       CASE_W(0x50)                                                                                            /* PUSH AX */
+               Push_16(reg_ax);break;
+       CASE_W(0x51)                                                                                            /* PUSH CX */
+               Push_16(reg_cx);break;
+       CASE_W(0x52)                                                                                            /* PUSH DX */
+               Push_16(reg_dx);break;
+       CASE_W(0x53)                                                                                            /* PUSH BX */
+               Push_16(reg_bx);break;
+       CASE_W(0x54)                                                                                            /* PUSH SP */
+               Push_16(reg_sp);break;
+       CASE_W(0x55)                                                                                            /* PUSH BP */
+               Push_16(reg_bp);break;
+       CASE_W(0x56)                                                                                            /* PUSH SI */
+               Push_16(reg_si);break;
+       CASE_W(0x57)                                                                                            /* PUSH DI */
+               Push_16(reg_di);break;
+       CASE_W(0x58)                                                                                            /* POP AX */
+               reg_ax=Pop_16();break;
+       CASE_W(0x59)                                                                                            /* POP CX */
+               reg_cx=Pop_16();break;
+       CASE_W(0x5a)                                                                                            /* POP DX */
+               reg_dx=Pop_16();break;
+       CASE_W(0x5b)                                                                                            /* POP BX */
+               reg_bx=Pop_16();break;
+       CASE_W(0x5c)                                                                                            /* POP SP */
+               reg_sp=Pop_16();break;
+       CASE_W(0x5d)                                                                                            /* POP BP */
+               reg_bp=Pop_16();break;
+       CASE_W(0x5e)                                                                                            /* POP SI */
+               reg_si=Pop_16();break;
+       CASE_W(0x5f)                                                                                            /* POP DI */
+               reg_di=Pop_16();break;
+       CASE_W(0x60)                                                                                            /* PUSHA */
+               {
+                       Bit16u old_sp=reg_sp;
+                       Push_16(reg_ax);Push_16(reg_cx);Push_16(reg_dx);Push_16(reg_bx);
+                       Push_16(old_sp);Push_16(reg_bp);Push_16(reg_si);Push_16(reg_di);
+               }
+               break;
+       CASE_W(0x61)                                                                                            /* POPA */
+               reg_di=Pop_16();reg_si=Pop_16();reg_bp=Pop_16();Pop_16();//Don't save SP
+               reg_bx=Pop_16();reg_dx=Pop_16();reg_cx=Pop_16();reg_ax=Pop_16();
+               break;
+       CASE_W(0x62)                                                                                            /* BOUND */
+               {
+                       Bit16s bound_min, bound_max;
+                       GetRMrw;GetEAa;
+                       bound_min=LoadMw(eaa);
+                       bound_max=LoadMw(eaa+2);
+                       if ( (((Bit16s)*rmrw) < bound_min) || (((Bit16s)*rmrw) > bound_max) ) {
+                               EXCEPTION(5);
+                       }
+               }
+               break;
+       CASE_W(0x63)                                                                                            /* ARPL Ew,Rw */
+               {
+                       if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode;
+                       GetRMrw;
+                       if (rm >= 0xc0 ) {
+                               GetEArw;Bitu new_sel=*earw;
+                               CPU_ARPL(new_sel,*rmrw);
+                               *earw=(Bit16u)new_sel;
+                       } else {
+                               GetEAa;Bitu new_sel=LoadMw(eaa);
+                               CPU_ARPL(new_sel,*rmrw);
+                               SaveMw(eaa,(Bit16u)new_sel);
+                       }
+               }
+               break;
+       CASE_B(0x64)                                                                                            /* SEG FS: */
+               DO_PREFIX_SEG(fs);break;
+       CASE_B(0x65)                                                                                            /* SEG GS: */
+               DO_PREFIX_SEG(gs);break;
+       CASE_B(0x66)                                                                                            /* Operand Size Prefix */
+               core.opcode_index=(cpu.code.big^0x1)*0x200;
+               goto restart_opcode;
+       CASE_B(0x67)                                                                                            /* Address Size Prefix */
+               DO_PREFIX_ADDR();
+       CASE_W(0x68)                                                                                            /* PUSH Iw */
+               Push_16(Fetchw());break;
+       CASE_W(0x69)                                                                                            /* IMUL Gw,Ew,Iw */
+               RMGwEwOp3(DIMULW,Fetchws());
+               break;
+       CASE_W(0x6a)                                                                                            /* PUSH Ib */
+               Push_16(Fetchbs());
+               break;
+       CASE_W(0x6b)                                                                                            /* IMUL Gw,Ew,Ib */
+               RMGwEwOp3(DIMULW,Fetchbs());
+               break;
+       CASE_B(0x6c)                                                                                            /* INSB */
+               if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
+               DoString(R_INSB);break;
+       CASE_W(0x6d)                                                                                            /* INSW */
+               if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
+               DoString(R_INSW);break;
+       CASE_B(0x6e)                                                                                            /* OUTSB */
+               if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
+               DoString(R_OUTSB);break;
+       CASE_W(0x6f)                                                                                            /* OUTSW */
+               if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
+               DoString(R_OUTSW);break;
+       CASE_W(0x70)                                                                                            /* JO */
+               JumpCond16_b(TFLG_O);break;
+       CASE_W(0x71)                                                                                            /* JNO */
+               JumpCond16_b(TFLG_NO);break;
+       CASE_W(0x72)                                                                                            /* JB */
+               JumpCond16_b(TFLG_B);break;
+       CASE_W(0x73)                                                                                            /* JNB */
+               JumpCond16_b(TFLG_NB);break;
+       CASE_W(0x74)                                                                                            /* JZ */
+               JumpCond16_b(TFLG_Z);break;
+       CASE_W(0x75)                                                                                            /* JNZ */
+               JumpCond16_b(TFLG_NZ);break;
+       CASE_W(0x76)                                                                                            /* JBE */
+               JumpCond16_b(TFLG_BE);break;
+       CASE_W(0x77)                                                                                            /* JNBE */
+               JumpCond16_b(TFLG_NBE);break;
+       CASE_W(0x78)                                                                                            /* JS */
+               JumpCond16_b(TFLG_S);break;
+       CASE_W(0x79)                                                                                            /* JNS */
+               JumpCond16_b(TFLG_NS);break;
+       CASE_W(0x7a)                                                                                            /* JP */
+               JumpCond16_b(TFLG_P);break;
+       CASE_W(0x7b)                                                                                            /* JNP */
+               JumpCond16_b(TFLG_NP);break;
+       CASE_W(0x7c)                                                                                            /* JL */
+               JumpCond16_b(TFLG_L);break;
+       CASE_W(0x7d)                                                                                            /* JNL */
+               JumpCond16_b(TFLG_NL);break;
+       CASE_W(0x7e)                                                                                            /* JLE */
+               JumpCond16_b(TFLG_LE);break;
+       CASE_W(0x7f)                                                                                            /* JNLE */
+               JumpCond16_b(TFLG_NLE);break;
+       CASE_B(0x80)                                                                                            /* Grpl Eb,Ib */
+       CASE_B(0x82)                                                                                            /* Grpl Eb,Ib Mirror instruction*/
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       if (rm>= 0xc0) {
+                               GetEArb;Bit8u ib=Fetchb();
+                               switch (which) {
+                               case 0x00:ADDB(*earb,ib,LoadRb,SaveRb);break;
+                               case 0x01: ORB(*earb,ib,LoadRb,SaveRb);break;
+                               case 0x02:ADCB(*earb,ib,LoadRb,SaveRb);break;
+                               case 0x03:SBBB(*earb,ib,LoadRb,SaveRb);break;
+                               case 0x04:ANDB(*earb,ib,LoadRb,SaveRb);break;
+                               case 0x05:SUBB(*earb,ib,LoadRb,SaveRb);break;
+                               case 0x06:XORB(*earb,ib,LoadRb,SaveRb);break;
+                               case 0x07:CMPB(*earb,ib,LoadRb,SaveRb);break;
+                               }
+                       } else {
+                               GetEAa;Bit8u ib=Fetchb();
+                               switch (which) {
+                               case 0x00:ADDB(eaa,ib,LoadMb,SaveMb);break;
+                               case 0x01: ORB(eaa,ib,LoadMb,SaveMb);break;
+                               case 0x02:ADCB(eaa,ib,LoadMb,SaveMb);break;
+                               case 0x03:SBBB(eaa,ib,LoadMb,SaveMb);break;
+                               case 0x04:ANDB(eaa,ib,LoadMb,SaveMb);break;
+                               case 0x05:SUBB(eaa,ib,LoadMb,SaveMb);break;
+                               case 0x06:XORB(eaa,ib,LoadMb,SaveMb);break;
+                               case 0x07:CMPB(eaa,ib,LoadMb,SaveMb);break;
+                               }
+                       }
+                       break;
+               }
+       CASE_W(0x81)                                                                                            /* Grpl Ew,Iw */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       if (rm>= 0xc0) {
+                               GetEArw;Bit16u iw=Fetchw();
+                               switch (which) {
+                               case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break;
+                               }
+                       } else {
+                               GetEAa;Bit16u iw=Fetchw();
+                               switch (which) {
+                               case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break;
+                               }
+                       }
+                       break;
+               }
+       CASE_W(0x83)                                                                                            /* Grpl Ew,Ix */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       if (rm>= 0xc0) {
+                               GetEArw;Bit16u iw=(Bit16s)Fetchbs();
+                               switch (which) {
+                               case 0x00:ADDW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x01: ORW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x02:ADCW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x03:SBBW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x04:ANDW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x05:SUBW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x06:XORW(*earw,iw,LoadRw,SaveRw);break;
+                               case 0x07:CMPW(*earw,iw,LoadRw,SaveRw);break;
+                               }
+                       } else {
+                               GetEAa;Bit16u iw=(Bit16s)Fetchbs();
+                               switch (which) {
+                               case 0x00:ADDW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x01: ORW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x02:ADCW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x03:SBBW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x04:ANDW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x05:SUBW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x06:XORW(eaa,iw,LoadMw,SaveMw);break;
+                               case 0x07:CMPW(eaa,iw,LoadMw,SaveMw);break;
+                               }
+                       }
+                       break;
+               }
+       CASE_B(0x84)                                                                                            /* TEST Eb,Gb */
+               RMEbGb(TESTB);
+               break;
+       CASE_W(0x85)                                                                                            /* TEST Ew,Gw */
+               RMEwGw(TESTW);
+               break;
+       CASE_B(0x86)                                                                                            /* XCHG Eb,Gb */
+               {       
+                       GetRMrb;Bit8u oldrmrb=*rmrb;
+                       if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;*earb=oldrmrb;}
+                       else {GetEAa;*rmrb=LoadMb(eaa);SaveMb(eaa,oldrmrb);}
+                       break;
+               }
+       CASE_W(0x87)                                                                                            /* XCHG Ew,Gw */
+               {       
+                       GetRMrw;Bit16u oldrmrw=*rmrw;
+                       if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;*earw=oldrmrw;}
+                       else {GetEAa;*rmrw=LoadMw(eaa);SaveMw(eaa,oldrmrw);}
+                       break;
+               }
+       CASE_B(0x88)                                                                                            /* MOV Eb,Gb */
+               {       
+                       GetRMrb;
+                       if (rm >= 0xc0 ) {GetEArb;*earb=*rmrb;}
+                       else {
+                               if (cpu.pmode) {
+                                       if (GCC_UNLIKELY((rm==0x05) && (!cpu.code.big))) {
+                                               Descriptor desc;
+                                               cpu.gdt.GetDescriptor(SegValue(core.base_val_ds),desc);
+                                               if ((desc.Type()==DESC_CODE_R_NC_A) || (desc.Type()==DESC_CODE_R_NC_NA)) {
+                                                       CPU_Exception(EXCEPTION_GP,SegValue(core.base_val_ds) & 0xfffc);
+                                                       continue;
+                                               }
+                                       }
+                               }
+                               GetEAa;SaveMb(eaa,*rmrb);
+                       }
+                       break;
+               }
+       CASE_W(0x89)                                                                                            /* MOV Ew,Gw */
+               {       
+                       GetRMrw;
+                       if (rm >= 0xc0 ) {GetEArw;*earw=*rmrw;}
+                       else {GetEAa;SaveMw(eaa,*rmrw);}
+                       break;
+               }
+       CASE_B(0x8a)                                                                                            /* MOV Gb,Eb */
+               {       
+                       GetRMrb;
+                       if (rm >= 0xc0 ) {GetEArb;*rmrb=*earb;}
+                       else {GetEAa;*rmrb=LoadMb(eaa);}
+                       break;
+               }
+       CASE_W(0x8b)                                                                                            /* MOV Gw,Ew */
+               {       
+                       GetRMrw;
+                       if (rm >= 0xc0 ) {GetEArw;*rmrw=*earw;}
+                       else {GetEAa;*rmrw=LoadMw(eaa);}
+                       break;
+               }
+       CASE_W(0x8c)                                                                                            /* Mov Ew,Sw */
+               {
+                       GetRM;Bit16u val;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:                                      /* MOV Ew,ES */
+                               val=SegValue(es);break;
+                       case 0x01:                                      /* MOV Ew,CS */
+                               val=SegValue(cs);break;
+                       case 0x02:                                      /* MOV Ew,SS */
+                               val=SegValue(ss);break;
+                       case 0x03:                                      /* MOV Ew,DS */
+                               val=SegValue(ds);break;
+                       case 0x04:                                      /* MOV Ew,FS */
+                               val=SegValue(fs);break;
+                       case 0x05:                                      /* MOV Ew,GS */
+                               val=SegValue(gs);break;
+                       default:
+                               LOG(LOG_CPU,LOG_ERROR)("CPU:8c:Illegal RM Byte");
+                               goto illegal_opcode;
+                       }
+                       if (rm >= 0xc0 ) {GetEArw;*earw=val;}
+                       else {GetEAa;SaveMw(eaa,val);}
+                       break;
+               }
+       CASE_W(0x8d)                                                                                            /* LEA Gw */
+               {
+                       //Little hack to always use segprefixed version
+                       BaseDS=BaseSS=0;
+                       GetRMrw;
+                       if (TEST_PREFIX_ADDR) {
+                               *rmrw=(Bit16u)(*EATable[256+rm])();
+                       } else {
+                               *rmrw=(Bit16u)(*EATable[rm])();
+                       }
+                       break;
+               }
+       CASE_B(0x8e)                                                                                            /* MOV Sw,Ew */
+               {
+                       GetRM;Bit16u val;Bitu which=(rm>>3)&7;
+                       if (rm >= 0xc0 ) {GetEArw;val=*earw;}
+                       else {GetEAa;val=LoadMw(eaa);}
+                       switch (which) {
+                       case 0x02:                                      /* MOV SS,Ew */
+                               CPU_Cycles++; //Always do another instruction
+                       case 0x00:                                      /* MOV ES,Ew */
+                       case 0x03:                                      /* MOV DS,Ew */
+                       case 0x05:                                      /* MOV GS,Ew */
+                       case 0x04:                                      /* MOV FS,Ew */
+                               if (CPU_SetSegGeneral((SegNames)which,val)) RUNEXCEPTION();
+                               break;
+                       default:
+                               goto illegal_opcode;
+                       }
+                       break;
+               }                                                       
+       CASE_W(0x8f)                                                                                            /* POP Ew */
+               {
+                       Bit16u val=Pop_16();
+                       GetRM;
+                       if (rm >= 0xc0 ) {GetEArw;*earw=val;}
+                       else {GetEAa;SaveMw(eaa,val);}
+                       break;
+               }
+       CASE_B(0x90)                                                                                            /* NOP */
+               break;
+       CASE_W(0x91)                                                                                            /* XCHG CX,AX */
+               { Bit16u temp=reg_ax;reg_ax=reg_cx;reg_cx=temp; }
+               break;
+       CASE_W(0x92)                                                                                            /* XCHG DX,AX */
+               { Bit16u temp=reg_ax;reg_ax=reg_dx;reg_dx=temp; }
+               break;
+       CASE_W(0x93)                                                                                            /* XCHG BX,AX */
+               { Bit16u temp=reg_ax;reg_ax=reg_bx;reg_bx=temp; }
+               break;
+       CASE_W(0x94)                                                                                            /* XCHG SP,AX */
+               { Bit16u temp=reg_ax;reg_ax=reg_sp;reg_sp=temp; }
+               break;
+       CASE_W(0x95)                                                                                            /* XCHG BP,AX */
+               { Bit16u temp=reg_ax;reg_ax=reg_bp;reg_bp=temp; }
+               break;
+       CASE_W(0x96)                                                                                            /* XCHG SI,AX */
+               { Bit16u temp=reg_ax;reg_ax=reg_si;reg_si=temp; }
+               break;
+       CASE_W(0x97)                                                                                            /* XCHG DI,AX */
+               { Bit16u temp=reg_ax;reg_ax=reg_di;reg_di=temp; }
+               break;
+       CASE_W(0x98)                                                                                            /* CBW */
+               reg_ax=(Bit8s)reg_al;break;
+       CASE_W(0x99)                                                                                            /* CWD */
+               if (reg_ax & 0x8000) reg_dx=0xffff;else reg_dx=0;
+               break;
+       CASE_W(0x9a)                                                                                            /* CALL Ap */
+               { 
+                       FillFlags();
+                       Bit16u newip=Fetchw();Bit16u newcs=Fetchw();
+                       CPU_CALL(false,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                       if (GETFLAG(TF)) {      
+                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                               return CBRET_NONE;
+                       }
+#endif
+                       continue;
+               }
+       CASE_B(0x9b)                                                                                            /* WAIT */
+               break; /* No waiting here */
+       CASE_W(0x9c)                                                                                            /* PUSHF */
+               if (CPU_PUSHF(false)) RUNEXCEPTION();
+               break;
+       CASE_W(0x9d)                                                                                            /* POPF */
+               if (CPU_POPF(false)) RUNEXCEPTION();
+#if CPU_TRAP_CHECK
+               if (GETFLAG(TF)) {      
+                       cpudecoder=CPU_Core_Normal_Trap_Run;
+                       goto decode_end;
+               }
+#endif
+#if    CPU_PIC_CHECK
+               if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
+#endif
+               break;
+       CASE_B(0x9e)                                                                                            /* SAHF */
+               SETFLAGSb(reg_ah);
+               break;
+       CASE_B(0x9f)                                                                                            /* LAHF */
+               FillFlags();
+               reg_ah=reg_flags&0xff;
+               break;
+       CASE_B(0xa0)                                                                                            /* MOV AL,Ob */
+               {
+                       GetEADirect;
+                       reg_al=LoadMb(eaa);
+               }
+               break;
+       CASE_W(0xa1)                                                                                            /* MOV AX,Ow */
+               {
+                       GetEADirect;
+                       reg_ax=LoadMw(eaa);
+               }
+               break;
+       CASE_B(0xa2)                                                                                            /* MOV Ob,AL */
+               {
+                       GetEADirect;
+                       SaveMb(eaa,reg_al);
+               }
+               break;
+       CASE_W(0xa3)                                                                                            /* MOV Ow,AX */
+               {
+                       GetEADirect;
+                       SaveMw(eaa,reg_ax);
+               }
+               break;
+       CASE_B(0xa4)                                                                                            /* MOVSB */
+               DoString(R_MOVSB);break;
+       CASE_W(0xa5)                                                                                            /* MOVSW */
+               DoString(R_MOVSW);break;
+       CASE_B(0xa6)                                                                                            /* CMPSB */
+               DoString(R_CMPSB);break;
+       CASE_W(0xa7)                                                                                            /* CMPSW */
+               DoString(R_CMPSW);break;
+       CASE_B(0xa8)                                                                                            /* TEST AL,Ib */
+               ALIb(TESTB);break;
+       CASE_W(0xa9)                                                                                            /* TEST AX,Iw */
+               AXIw(TESTW);break;
+       CASE_B(0xaa)                                                                                            /* STOSB */
+               DoString(R_STOSB);break;
+       CASE_W(0xab)                                                                                            /* STOSW */
+               DoString(R_STOSW);break;
+       CASE_B(0xac)                                                                                            /* LODSB */
+               DoString(R_LODSB);break;
+       CASE_W(0xad)                                                                                            /* LODSW */
+               DoString(R_LODSW);break;
+       CASE_B(0xae)                                                                                            /* SCASB */
+               DoString(R_SCASB);break;
+       CASE_W(0xaf)                                                                                            /* SCASW */
+               DoString(R_SCASW);break;
+       CASE_B(0xb0)                                                                                            /* MOV AL,Ib */
+               reg_al=Fetchb();break;
+       CASE_B(0xb1)                                                                                            /* MOV CL,Ib */
+               reg_cl=Fetchb();break;
+       CASE_B(0xb2)                                                                                            /* MOV DL,Ib */
+               reg_dl=Fetchb();break;
+       CASE_B(0xb3)                                                                                            /* MOV BL,Ib */
+               reg_bl=Fetchb();break;
+       CASE_B(0xb4)                                                                                            /* MOV AH,Ib */
+               reg_ah=Fetchb();break;
+       CASE_B(0xb5)                                                                                            /* MOV CH,Ib */
+               reg_ch=Fetchb();break;
+       CASE_B(0xb6)                                                                                            /* MOV DH,Ib */
+               reg_dh=Fetchb();break;
+       CASE_B(0xb7)                                                                                            /* MOV BH,Ib */
+               reg_bh=Fetchb();break;
+       CASE_W(0xb8)                                                                                            /* MOV AX,Iw */
+               reg_ax=Fetchw();break;
+       CASE_W(0xb9)                                                                                            /* MOV CX,Iw */
+               reg_cx=Fetchw();break;
+       CASE_W(0xba)                                                                                            /* MOV DX,Iw */
+               reg_dx=Fetchw();break;
+       CASE_W(0xbb)                                                                                            /* MOV BX,Iw */
+               reg_bx=Fetchw();break;
+       CASE_W(0xbc)                                                                                            /* MOV SP,Iw */
+               reg_sp=Fetchw();break;
+       CASE_W(0xbd)                                                                                            /* MOV BP.Iw */
+               reg_bp=Fetchw();break;
+       CASE_W(0xbe)                                                                                            /* MOV SI,Iw */
+               reg_si=Fetchw();break;
+       CASE_W(0xbf)                                                                                            /* MOV DI,Iw */
+               reg_di=Fetchw();break;
+       CASE_B(0xc0)                                                                                            /* GRP2 Eb,Ib */
+               GRP2B(Fetchb());break;
+       CASE_W(0xc1)                                                                                            /* GRP2 Ew,Ib */
+               GRP2W(Fetchb());break;
+       CASE_W(0xc2)                                                                                            /* RETN Iw */
+               reg_eip=Pop_16();
+               reg_esp+=Fetchw();
+               continue;
+       CASE_W(0xc3)                                                                                            /* RETN */
+               reg_eip=Pop_16();
+               continue;
+       CASE_W(0xc4)                                                                                            /* LES */
+               {       
+                       GetRMrw;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(es,LoadMw(eaa+2))) RUNEXCEPTION();
+                       *rmrw=LoadMw(eaa);
+                       break;
+               }
+       CASE_W(0xc5)                                                                                            /* LDS */
+               {       
+                       GetRMrw;
+                       if (rm >= 0xc0) goto illegal_opcode;
+                       GetEAa;
+                       if (CPU_SetSegGeneral(ds,LoadMw(eaa+2))) RUNEXCEPTION();
+                       *rmrw=LoadMw(eaa);
+                       break;
+               }
+       CASE_B(0xc6)                                                                                            /* MOV Eb,Ib */
+               {
+                       GetRM;
+                       if (rm >= 0xc0) {GetEArb;*earb=Fetchb();}
+                       else {GetEAa;SaveMb(eaa,Fetchb());}
+                       break;
+               }
+       CASE_W(0xc7)                                                                                            /* MOV EW,Iw */
+               {
+                       GetRM;
+                       if (rm >= 0xc0) {GetEArw;*earw=Fetchw();}
+                       else {GetEAa;SaveMw(eaa,Fetchw());}
+                       break;
+               }
+       CASE_W(0xc8)                                                                                            /* ENTER Iw,Ib */
+               {
+                       Bitu bytes=Fetchw();
+                       Bitu level=Fetchb();
+                       CPU_ENTER(false,bytes,level);
+               }
+               break;
+       CASE_W(0xc9)                                                                                            /* LEAVE */
+               reg_esp&=cpu.stack.notmask;
+               reg_esp|=(reg_ebp&cpu.stack.mask);
+               reg_bp=Pop_16();
+               break;
+       CASE_W(0xca)                                                                                            /* RETF Iw */
+               {
+                       Bitu words=Fetchw();
+                       FillFlags();
+                       CPU_RET(false,words,GETIP);
+                       continue;
+               }
+       CASE_W(0xcb)                                                                                            /* RETF */                      
+               FillFlags();
+               CPU_RET(false,0,GETIP);
+               continue;
+       CASE_B(0xcc)                                                                                            /* INT3 */
+#if C_DEBUG    
+               FillFlags();
+               if (DEBUG_Breakpoint())
+                       return debugCallback;
+#endif                 
+               CPU_SW_Interrupt_NoIOPLCheck(3,GETIP);
+#if CPU_TRAP_CHECK
+               cpu.trap_skip=true;
+#endif
+               continue;
+       CASE_B(0xcd)                                                                                            /* INT Ib */    
+               {
+                       Bit8u num=Fetchb();
+#if C_DEBUG
+                       FillFlags();
+                       if (DEBUG_IntBreakpoint(num)) {
+                               return debugCallback;
+                       }
+#endif
+                       CPU_SW_Interrupt(num,GETIP);
+#if CPU_TRAP_CHECK
+                       cpu.trap_skip=true;
+#endif
+                       continue;
+               }
+       CASE_B(0xce)                                                                                            /* INTO */
+               if (get_OF()) {
+                       CPU_SW_Interrupt(4,GETIP);
+#if CPU_TRAP_CHECK
+                       cpu.trap_skip=true;
+#endif
+                       continue;
+               }
+               break;
+       CASE_W(0xcf)                                                                                            /* IRET */
+               {
+                       CPU_IRET(false,GETIP);
+#if CPU_TRAP_CHECK
+                       if (GETFLAG(TF)) {      
+                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                               return CBRET_NONE;
+                       }
+#endif
+#if CPU_PIC_CHECK
+                       if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
+#endif
+                       continue;
+               }
+       CASE_B(0xd0)                                                                                            /* GRP2 Eb,1 */
+               GRP2B(1);break;
+       CASE_W(0xd1)                                                                                            /* GRP2 Ew,1 */
+               GRP2W(1);break;
+       CASE_B(0xd2)                                                                                            /* GRP2 Eb,CL */
+               GRP2B(reg_cl);break;
+       CASE_W(0xd3)                                                                                            /* GRP2 Ew,CL */
+               GRP2W(reg_cl);break;
+       CASE_B(0xd4)                                                                                            /* AAM Ib */
+               AAM(Fetchb());break;
+       CASE_B(0xd5)                                                                                            /* AAD Ib */
+               AAD(Fetchb());break;
+       CASE_B(0xd6)                                                                                            /* SALC */
+               reg_al = get_CF() ? 0xFF : 0;
+               break;
+       CASE_B(0xd7)                                                                                            /* XLAT */
+               if (TEST_PREFIX_ADDR) {
+                       reg_al=LoadMb(BaseDS+(Bit32u)(reg_ebx+reg_al));
+               } else {
+                       reg_al=LoadMb(BaseDS+(Bit16u)(reg_bx+reg_al));
+               }
+               break;
+#ifdef CPU_FPU
+       CASE_B(0xd8)                                                                                            /* FPU ESC 0 */
+                FPU_ESC(0);break;
+       CASE_B(0xd9)                                                                                            /* FPU ESC 1 */
+                FPU_ESC(1);break;
+       CASE_B(0xda)                                                                                            /* FPU ESC 2 */
+                FPU_ESC(2);break;
+       CASE_B(0xdb)                                                                                            /* FPU ESC 3 */
+                FPU_ESC(3);break;
+       CASE_B(0xdc)                                                                                            /* FPU ESC 4 */
+                FPU_ESC(4);break;
+       CASE_B(0xdd)                                                                                            /* FPU ESC 5 */
+                FPU_ESC(5);break;
+       CASE_B(0xde)                                                                                            /* FPU ESC 6 */
+                FPU_ESC(6);break;
+       CASE_B(0xdf)                                                                                            /* FPU ESC 7 */
+                FPU_ESC(7);break;
+#else 
+       CASE_B(0xd8)                                                                                            /* FPU ESC 0 */
+       CASE_B(0xd9)                                                                                            /* FPU ESC 1 */
+       CASE_B(0xda)                                                                                            /* FPU ESC 2 */
+       CASE_B(0xdb)                                                                                            /* FPU ESC 3 */
+       CASE_B(0xdc)                                                                                            /* FPU ESC 4 */
+       CASE_B(0xdd)                                                                                            /* FPU ESC 5 */
+       CASE_B(0xde)                                                                                            /* FPU ESC 6 */
+       CASE_B(0xdf)                                                                                            /* FPU ESC 7 */
+               {
+                       LOG(LOG_CPU,LOG_NORMAL)("FPU used");
+                       Bit8u rm=Fetchb();
+                       if (rm<0xc0) GetEAa;
+               }
+               break;
+#endif
+       CASE_W(0xe0)                                                                                            /* LOOPNZ */
+               if (TEST_PREFIX_ADDR) {
+                       JumpCond16_b(--reg_ecx && !get_ZF());
+               } else {
+                       JumpCond16_b(--reg_cx && !get_ZF());
+               }
+               break;
+       CASE_W(0xe1)                                                                                            /* LOOPZ */
+               if (TEST_PREFIX_ADDR) {
+                       JumpCond16_b(--reg_ecx && get_ZF());
+               } else {
+                       JumpCond16_b(--reg_cx && get_ZF());
+               }
+               break;
+       CASE_W(0xe2)                                                                                            /* LOOP */
+               if (TEST_PREFIX_ADDR) { 
+                       JumpCond16_b(--reg_ecx);
+               } else {
+                       JumpCond16_b(--reg_cx);
+               }
+               break;
+       CASE_W(0xe3)                                                                                            /* JCXZ */
+               JumpCond16_b(!(reg_ecx & AddrMaskTable[core.prefixes& PREFIX_ADDR]));
+               break;
+       CASE_B(0xe4)                                                                                            /* IN AL,Ib */
+               {       
+                       Bitu port=Fetchb();
+                       if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
+                       reg_al=IO_ReadB(port);
+                       break;
+               }
+       CASE_W(0xe5)                                                                                            /* IN AX,Ib */
+               {       
+                       Bitu port=Fetchb();
+                       if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
+                       reg_ax=IO_ReadW(port);
+                       break;
+               }
+       CASE_B(0xe6)                                                                                            /* OUT Ib,AL */
+               {
+                       Bitu port=Fetchb();
+                       if (CPU_IO_Exception(port,1)) RUNEXCEPTION();
+                       IO_WriteB(port,reg_al);
+                       break;
+               }               
+       CASE_W(0xe7)                                                                                            /* OUT Ib,AX */
+               {
+                       Bitu port=Fetchb();
+                       if (CPU_IO_Exception(port,2)) RUNEXCEPTION();
+                       IO_WriteW(port,reg_ax);
+                       break;
+               }
+       CASE_W(0xe8)                                                                                            /* CALL Jw */
+               { 
+                       Bit16u addip=Fetchws();
+                       SAVEIP;
+                       Push_16(reg_eip);
+                       reg_eip=(Bit16u)(reg_eip+addip);
+                       continue;
+               }
+       CASE_W(0xe9)                                                                                            /* JMP Jw */
+               { 
+                       Bit16u addip=Fetchws();
+                       SAVEIP;
+                       reg_eip=(Bit16u)(reg_eip+addip);
+                       continue;
+               }
+       CASE_W(0xea)                                                                                            /* JMP Ap */
+               { 
+                       Bit16u newip=Fetchw();
+                       Bit16u newcs=Fetchw();
+                       FillFlags();
+                       CPU_JMP(false,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                       if (GETFLAG(TF)) {      
+                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                               return CBRET_NONE;
+                       }
+#endif
+                       continue;
+               }
+       CASE_W(0xeb)                                                                                            /* JMP Jb */
+               { 
+                       Bit16s addip=Fetchbs();
+                       SAVEIP;
+                       reg_eip=(Bit16u)(reg_eip+addip);
+                       continue;
+               }
+       CASE_B(0xec)                                                                                            /* IN AL,DX */
+               if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
+               reg_al=IO_ReadB(reg_dx);
+               break;
+       CASE_W(0xed)                                                                                            /* IN AX,DX */
+               if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
+               reg_ax=IO_ReadW(reg_dx);
+               break;
+       CASE_B(0xee)                                                                                            /* OUT DX,AL */
+               if (CPU_IO_Exception(reg_dx,1)) RUNEXCEPTION();
+               IO_WriteB(reg_dx,reg_al);
+               break;
+       CASE_W(0xef)                                                                                            /* OUT DX,AX */
+               if (CPU_IO_Exception(reg_dx,2)) RUNEXCEPTION();
+               IO_WriteW(reg_dx,reg_ax);
+               break;
+       CASE_B(0xf0)                                                                                            /* LOCK */
+               LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); /* FIXME: see case D_LOCK in core_full/load.h */
+               break;
+       CASE_B(0xf1)                                                                                            /* ICEBP */
+               CPU_SW_Interrupt_NoIOPLCheck(1,GETIP);
+#if CPU_TRAP_CHECK
+               cpu.trap_skip=true;
+#endif
+               continue;
+       CASE_B(0xf2)                                                                                            /* REPNZ */
+               DO_PREFIX_REP(false);   
+               break;          
+       CASE_B(0xf3)                                                                                            /* REPZ */
+               DO_PREFIX_REP(true);    
+               break;          
+       CASE_B(0xf4)                                                                                            /* HLT */
+               if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP);
+               FillFlags();
+               CPU_HLT(GETIP);
+               return CBRET_NONE;              //Needs to return for hlt cpu core
+       CASE_B(0xf5)                                                                                            /* CMC */
+               FillFlags();
+               SETFLAGBIT(CF,!(reg_flags & FLAG_CF));
+               break;
+       CASE_B(0xf6)                                                                                            /* GRP3 Eb(,Ib) */
+               {       
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:                                                                                      /* TEST Eb,Ib */
+                       case 0x01:                                                                                      /* TEST Eb,Ib Undocumented*/
+                               {
+                                       if (rm >= 0xc0 ) {GetEArb;TESTB(*earb,Fetchb(),LoadRb,0)}
+                                       else {GetEAa;TESTB(eaa,Fetchb(),LoadMb,0);}
+                                       break;
+                               }
+                       case 0x02:                                                                                      /* NOT Eb */
+                               {
+                                       if (rm >= 0xc0 ) {GetEArb;*earb=~*earb;}
+                                       else {GetEAa;SaveMb(eaa,~LoadMb(eaa));}
+                                       break;
+                               }
+                       case 0x03:                                                                                      /* NEG Eb */
+                               {
+                                       lflags.type=t_NEGb;
+                                       if (rm >= 0xc0 ) {
+                                               GetEArb;lf_var1b=*earb;lf_resb=0-lf_var1b;
+                                               *earb=lf_resb;
+                                       } else {
+                                               GetEAa;lf_var1b=LoadMb(eaa);lf_resb=0-lf_var1b;
+                                               SaveMb(eaa,lf_resb);
+                                       }
+                                       break;
+                               }
+                       case 0x04:                                                                                      /* MUL AL,Eb */
+                               RMEb(MULB);
+                               break;
+                       case 0x05:                                                                                      /* IMUL AL,Eb */
+                               RMEb(IMULB);
+                               break;
+                       case 0x06:                                                                                      /* DIV Eb */
+                               RMEb(DIVB);
+                               break;
+                       case 0x07:                                                                                      /* IDIV Eb */
+                               RMEb(IDIVB);
+                               break;
+                       }
+                       break;
+               }
+       CASE_W(0xf7)                                                                                            /* GRP3 Ew(,Iw) */
+               { 
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:                                                                                      /* TEST Ew,Iw */
+                       case 0x01:                                                                                      /* TEST Ew,Iw Undocumented*/
+                               {
+                                       if (rm >= 0xc0 ) {GetEArw;TESTW(*earw,Fetchw(),LoadRw,SaveRw);}
+                                       else {GetEAa;TESTW(eaa,Fetchw(),LoadMw,SaveMw);}
+                                       break;
+                               }
+                       case 0x02:                                                                                      /* NOT Ew */
+                               {
+                                       if (rm >= 0xc0 ) {GetEArw;*earw=~*earw;}
+                                       else {GetEAa;SaveMw(eaa,~LoadMw(eaa));}
+                                       break;
+                               }
+                       case 0x03:                                                                                      /* NEG Ew */
+                               {
+                                       lflags.type=t_NEGw;
+                                       if (rm >= 0xc0 ) {
+                                               GetEArw;lf_var1w=*earw;lf_resw=0-lf_var1w;
+                                               *earw=lf_resw;
+                                       } else {
+                                               GetEAa;lf_var1w=LoadMw(eaa);lf_resw=0-lf_var1w;
+                                               SaveMw(eaa,lf_resw);
+                                       }
+                                       break;
+                               }
+                       case 0x04:                                                                                      /* MUL AX,Ew */
+                               RMEw(MULW);
+                               break;
+                       case 0x05:                                                                                      /* IMUL AX,Ew */
+                               RMEw(IMULW)
+                               break;
+                       case 0x06:                                                                                      /* DIV Ew */
+                               RMEw(DIVW)
+                               break;
+                       case 0x07:                                                                                      /* IDIV Ew */
+                               RMEw(IDIVW)
+                               break;
+                       }
+                       break;
+               }
+       CASE_B(0xf8)                                                                                            /* CLC */
+               FillFlags();
+               SETFLAGBIT(CF,false);
+               break;
+       CASE_B(0xf9)                                                                                            /* STC */
+               FillFlags();
+               SETFLAGBIT(CF,true);
+               break;
+       CASE_B(0xfa)                                                                                            /* CLI */
+               if (CPU_CLI()) RUNEXCEPTION();
+               break;
+       CASE_B(0xfb)                                                                                            /* STI */
+               if (CPU_STI()) RUNEXCEPTION();
+#if CPU_PIC_CHECK
+               if (GETFLAG(IF) && PIC_IRQCheck) goto decode_end;
+#endif
+               break;
+       CASE_B(0xfc)                                                                                            /* CLD */
+               SETFLAGBIT(DF,false);
+               cpu.direction=1;
+               break;
+       CASE_B(0xfd)                                                                                            /* STD */
+               SETFLAGBIT(DF,true);
+               cpu.direction=-1;
+               break;
+       CASE_B(0xfe)                                                                                            /* GRP4 Eb */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:                                                                              /* INC Eb */
+                               RMEb(INCB);
+                               break;          
+                       case 0x01:                                                                              /* DEC Eb */
+                               RMEb(DECB);
+                               break;
+                       case 0x07:                                                                              /* CallBack */
+                               {
+                                       Bitu cb=Fetchw();
+                                       FillFlags();SAVEIP;
+                                       return cb;
+                               }
+                       default:
+                               E_Exit("Illegal GRP4 Call %d",(rm>>3) & 7);
+                               break;
+                       }
+                       break;
+               }
+       CASE_W(0xff)                                                                                            /* GRP5 Ew */
+               {
+                       GetRM;Bitu which=(rm>>3)&7;
+                       switch (which) {
+                       case 0x00:                                                                              /* INC Ew */
+                               RMEw(INCW);
+                               break;          
+                       case 0x01:                                                                              /* DEC Ew */
+                               RMEw(DECW);
+                               break;          
+                       case 0x02:                                                                              /* CALL Ev */
+                               if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
+                               else {GetEAa;reg_eip=LoadMw(eaa);}
+                               Push_16(GETIP);
+                               continue;
+                       case 0x03:                                                                              /* CALL Ep */
+                               {
+                                       if (rm >= 0xc0) goto illegal_opcode;
+                                       GetEAa;
+                                       Bit16u newip=LoadMw(eaa);
+                                       Bit16u newcs=LoadMw(eaa+2);
+                                       FillFlags();
+                                       CPU_CALL(false,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                                       if (GETFLAG(TF)) {      
+                                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                                               return CBRET_NONE;
+                                       }
+#endif
+                                       continue;
+                               }
+                               break;
+                       case 0x04:                                                                              /* JMP Ev */    
+                               if (rm >= 0xc0 ) {GetEArw;reg_eip=*earw;}
+                               else {GetEAa;reg_eip=LoadMw(eaa);}
+                               continue;
+                       case 0x05:                                                                              /* JMP Ep */    
+                               {
+                                       if (rm >= 0xc0) goto illegal_opcode;
+                                       GetEAa;
+                                       Bit16u newip=LoadMw(eaa);
+                                       Bit16u newcs=LoadMw(eaa+2);
+                                       FillFlags();
+                                       CPU_JMP(false,newcs,newip,GETIP);
+#if CPU_TRAP_CHECK
+                                       if (GETFLAG(TF)) {      
+                                               cpudecoder=CPU_Core_Normal_Trap_Run;
+                                               return CBRET_NONE;
+                                       }
+#endif
+                                       continue;
+                               }
+                               break;
+                       case 0x06:                                                                              /* PUSH Ev */
+                               if (rm >= 0xc0 ) {GetEArw;Push_16(*earw);}
+                               else {GetEAa;Push_16(LoadMw(eaa));}
+                               break;
+                       default:
+                               LOG(LOG_CPU,LOG_ERROR)("CPU:GRP5:Illegal Call %2X",which);
+                               goto illegal_opcode;
+                       }
+                       break;
+               }
+                       
+
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/string.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/string.h
new file mode 100644 (file)
index 0000000..992ed42
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+enum STRING_OP {
+       R_OUTSB,R_OUTSW,R_OUTSD,
+       R_INSB,R_INSW,R_INSD,
+       R_MOVSB,R_MOVSW,R_MOVSD,
+       R_LODSB,R_LODSW,R_LODSD,
+       R_STOSB,R_STOSW,R_STOSD,
+       R_SCASB,R_SCASW,R_SCASD,
+       R_CMPSB,R_CMPSW,R_CMPSD
+};
+
+#define LoadD(_BLAH) _BLAH
+
+static void DoString(STRING_OP type) {
+       PhysPt  si_base,di_base;
+       Bitu    si_index,di_index;
+       Bitu    add_mask;
+       Bitu    count,count_left;
+       Bits    add_index;
+       
+       si_base=BaseDS;
+       di_base=SegBase(es);
+       add_mask=AddrMaskTable[core.prefixes & PREFIX_ADDR];
+       si_index=reg_esi & add_mask;
+       di_index=reg_edi & add_mask;
+       count=reg_ecx & add_mask;
+       if (!TEST_PREFIX_REP) {
+               count=1;
+       } else {
+               CPU_Cycles++;
+               /* Calculate amount of ops to do before cycles run out */
+               if ((count>(Bitu)CPU_Cycles) && (type<R_SCASB)) {
+                       count_left=count-CPU_Cycles;
+                       count=CPU_Cycles;
+                       CPU_Cycles=0;
+                       LOADIP;         //RESET IP to the start
+               } else {
+                       /* Won't interrupt scas and cmps instruction since they can interrupt themselves */
+                       if ((count<=1) && (CPU_Cycles<=1)) CPU_Cycles--;
+                       else if (type<R_SCASB) CPU_Cycles-=count;
+                       count_left=0;
+               }
+       }
+       add_index=cpu.direction;
+       if (count) switch (type) {
+       case R_OUTSB:
+               for (;count>0;count--) {
+                       IO_WriteB(reg_dx,LoadMb(si_base+si_index));
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_OUTSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       IO_WriteW(reg_dx,LoadMw(si_base+si_index));
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_OUTSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       IO_WriteD(reg_dx,LoadMd(si_base+si_index));
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_INSB:
+               for (;count>0;count--) {
+                       SaveMb(di_base+di_index,IO_ReadB(reg_dx));
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_INSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       SaveMw(di_base+di_index,IO_ReadW(reg_dx));
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_INSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       SaveMd(di_base+di_index,IO_ReadD(reg_dx));
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_STOSB:
+               for (;count>0;count--) {
+                       SaveMb(di_base+di_index,reg_al);
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_STOSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       SaveMw(di_base+di_index,reg_ax);
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_STOSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       SaveMd(di_base+di_index,reg_eax);
+                       di_index=(di_index+add_index) & add_mask;
+               }
+               break;
+       case R_MOVSB:
+               for (;count>0;count--) {
+                       SaveMb(di_base+di_index,LoadMb(si_base+si_index));
+                       di_index=(di_index+add_index) & add_mask;
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_MOVSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       SaveMw(di_base+di_index,LoadMw(si_base+si_index));
+                       di_index=(di_index+add_index) & add_mask;
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_MOVSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       SaveMd(di_base+di_index,LoadMd(si_base+si_index));
+                       di_index=(di_index+add_index) & add_mask;
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_LODSB:
+               for (;count>0;count--) {
+                       reg_al=LoadMb(si_base+si_index);
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_LODSW:
+               add_index<<=1;
+               for (;count>0;count--) {
+                       reg_ax=LoadMw(si_base+si_index);
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_LODSD:
+               add_index<<=2;
+               for (;count>0;count--) {
+                       reg_eax=LoadMd(si_base+si_index);
+                       si_index=(si_index+add_index) & add_mask;
+               }
+               break;
+       case R_SCASB:
+               {
+                       Bit8u val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val2=LoadMb(di_base+di_index);
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((reg_al==val2)!=core.rep_zero) break;
+                       }
+                       CMPB(reg_al,val2,LoadD,0);
+               }
+               break;
+       case R_SCASW:
+               {
+                       add_index<<=1;Bit16u val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val2=LoadMw(di_base+di_index);
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((reg_ax==val2)!=core.rep_zero) break;
+                       }
+                       CMPW(reg_ax,val2,LoadD,0);
+               }
+               break;
+       case R_SCASD:
+               {
+                       add_index<<=2;Bit32u val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val2=LoadMd(di_base+di_index);
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((reg_eax==val2)!=core.rep_zero) break;
+                       }
+                       CMPD(reg_eax,val2,LoadD,0);
+               }
+               break;
+       case R_CMPSB:
+               {
+                       Bit8u val1,val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val1=LoadMb(si_base+si_index);
+                               val2=LoadMb(di_base+di_index);
+                               si_index=(si_index+add_index) & add_mask;
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((val1==val2)!=core.rep_zero) break;
+                       }
+                       CMPB(val1,val2,LoadD,0);
+               }
+               break;
+       case R_CMPSW:
+               {
+                       add_index<<=1;Bit16u val1,val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val1=LoadMw(si_base+si_index);
+                               val2=LoadMw(di_base+di_index);
+                               si_index=(si_index+add_index) & add_mask;
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((val1==val2)!=core.rep_zero) break;
+                       }
+                       CMPW(val1,val2,LoadD,0);
+               }
+               break;
+       case R_CMPSD:
+               {
+                       add_index<<=2;Bit32u val1,val2;
+                       for (;count>0;) {
+                               count--;CPU_Cycles--;
+                               val1=LoadMd(si_base+si_index);
+                               val2=LoadMd(di_base+di_index);
+                               si_index=(si_index+add_index) & add_mask;
+                               di_index=(di_index+add_index) & add_mask;
+                               if ((val1==val2)!=core.rep_zero) break;
+                       }
+                       CMPD(val1,val2,LoadD,0);
+               }
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled string op %d",type);
+       }
+       /* Clean up after certain amount of instructions */
+       reg_esi&=(~add_mask);
+       reg_esi|=(si_index & add_mask);
+       reg_edi&=(~add_mask);
+       reg_edi|=(di_index & add_mask);
+       if (TEST_PREFIX_REP) {
+               count+=count_left;
+               reg_ecx&=(~add_mask);
+               reg_ecx|=(count & add_mask);
+       }
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/support.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/support.h
new file mode 100644 (file)
index 0000000..6fe9a17
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#define LoadMbs(off) (Bit8s)(LoadMb(off))
+#define LoadMws(off) (Bit16s)(LoadMw(off))
+#define LoadMds(off) (Bit32s)(LoadMd(off))
+
+#define LoadRb(reg) reg
+#define LoadRw(reg) reg
+#define LoadRd(reg) reg
+
+#define SaveRb(reg,val)        reg=val
+#define SaveRw(reg,val)        reg=val
+#define SaveRd(reg,val)        reg=val
+
+static INLINE Bit8s Fetchbs() {
+       return Fetchb();
+}
+static INLINE Bit16s Fetchws() {
+       return Fetchw();
+}
+
+static INLINE Bit32s Fetchds() {
+       return Fetchd();
+}
+
+
+#define RUNEXCEPTION() {                                                                               \
+       CPU_Exception(cpu.exception.which,cpu.exception.error);         \
+       continue;                                                                                                       \
+}
+
+#define EXCEPTION(blah)                                                                                \
+       {                                                                                                               \
+               CPU_Exception(blah);                                                            \
+               continue;                                                                                       \
+       }
+
+//TODO Could probably make all byte operands fast?
+#define JumpCond16_b(COND) {                                           \
+       SAVEIP;                                                                                 \
+       if (COND) reg_ip+=Fetchbs();                                    \
+       reg_ip+=1;                                                                              \
+       continue;                                                                               \
+}
+
+#define JumpCond16_w(COND) {                                           \
+       SAVEIP;                                                                                 \
+       if (COND) reg_ip+=Fetchws();                                    \
+       reg_ip+=2;                                                                              \
+       continue;                                                                               \
+}
+
+#define JumpCond32_b(COND) {                                           \
+       SAVEIP;                                                                                 \
+       if (COND) reg_eip+=Fetchbs();                                   \
+       reg_eip+=1;                                                                             \
+       continue;                                                                               \
+}
+
+#define JumpCond32_d(COND) {                                           \
+       SAVEIP;                                                                                 \
+       if (COND) reg_eip+=Fetchds();                                   \
+       reg_eip+=4;                                                                             \
+       continue;                                                                               \
+}
+
+
+#define SETcc(cc)                                                                                      \
+       {                                                                                                               \
+               GetRM;                                                                                          \
+               if (rm >= 0xc0 ) {GetEArb;*earb=(cc) ? 1 : 0;}          \
+               else {GetEAa;SaveMb(eaa,(cc) ? 1 : 0);}                         \
+       }
+
+#include "helpers.h"
+#include "table_ea.h"
+#include "../modrm.h"
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/table_ea.h b/source/src/vm/libcpu_newdev/dosbox-i386/core_normal/table_ea.h
new file mode 100644 (file)
index 0000000..920f5ce
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+typedef PhysPt (*EA_LookupHandler)(void);
+
+/* The MOD/RM Decoder for EA for this decoder's addressing modes */
+static PhysPt EA_16_00_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si); }
+static PhysPt EA_16_01_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di); }
+static PhysPt EA_16_02_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si); }
+static PhysPt EA_16_03_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di); }
+static PhysPt EA_16_04_n(void) { return BaseDS+(Bit16u)(reg_si); }
+static PhysPt EA_16_05_n(void) { return BaseDS+(Bit16u)(reg_di); }
+static PhysPt EA_16_06_n(void) { return BaseDS+(Bit16u)(Fetchw());}
+static PhysPt EA_16_07_n(void) { return BaseDS+(Bit16u)(reg_bx); }
+
+static PhysPt EA_16_40_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchbs()); }
+static PhysPt EA_16_41_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchbs()); }
+static PhysPt EA_16_42_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchbs()); }
+static PhysPt EA_16_43_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchbs()); }
+static PhysPt EA_16_44_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchbs()); }
+static PhysPt EA_16_45_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchbs()); }
+static PhysPt EA_16_46_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchbs()); }
+static PhysPt EA_16_47_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchbs()); }
+
+static PhysPt EA_16_80_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_si+Fetchws()); }
+static PhysPt EA_16_81_n(void) { return BaseDS+(Bit16u)(reg_bx+(Bit16s)reg_di+Fetchws()); }
+static PhysPt EA_16_82_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_si+Fetchws()); }
+static PhysPt EA_16_83_n(void) { return BaseSS+(Bit16u)(reg_bp+(Bit16s)reg_di+Fetchws()); }
+static PhysPt EA_16_84_n(void) { return BaseDS+(Bit16u)(reg_si+Fetchws()); }
+static PhysPt EA_16_85_n(void) { return BaseDS+(Bit16u)(reg_di+Fetchws()); }
+static PhysPt EA_16_86_n(void) { return BaseSS+(Bit16u)(reg_bp+Fetchws()); }
+static PhysPt EA_16_87_n(void) { return BaseDS+(Bit16u)(reg_bx+Fetchws()); }
+
+static Bit32u SIBZero=0;
+static Bit32u * SIBIndex[8]= { &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&SIBZero,&reg_ebp,&reg_esi,&reg_edi };
+
+static INLINE PhysPt Sib(Bitu mode) {
+       Bit8u sib=Fetchb();
+       PhysPt base;
+       switch (sib&7) {
+       case 0: /* EAX Base */
+               base=BaseDS+reg_eax;break;
+       case 1: /* ECX Base */
+               base=BaseDS+reg_ecx;break;
+       case 2: /* EDX Base */
+               base=BaseDS+reg_edx;break;
+       case 3: /* EBX Base */
+               base=BaseDS+reg_ebx;break;
+       case 4: /* ESP Base */
+               base=BaseSS+reg_esp;break;
+       case 5: /* #1 Base */
+               if (!mode) {
+                       base=BaseDS+Fetchd();break;
+               } else {
+                       base=BaseSS+reg_ebp;break;
+               }
+       case 6: /* ESI Base */
+               base=BaseDS+reg_esi;break;
+       case 7: /* EDI Base */
+               base=BaseDS+reg_edi;break;
+       }
+       base+=*SIBIndex[(sib >> 3) &7] << (sib >> 6);
+       return base;
+}
+
+static PhysPt EA_32_00_n(void) { return BaseDS+reg_eax; }
+static PhysPt EA_32_01_n(void) { return BaseDS+reg_ecx; }
+static PhysPt EA_32_02_n(void) { return BaseDS+reg_edx; }
+static PhysPt EA_32_03_n(void) { return BaseDS+reg_ebx; }
+static PhysPt EA_32_04_n(void) { return Sib(0);}
+static PhysPt EA_32_05_n(void) { return BaseDS+Fetchd(); }
+static PhysPt EA_32_06_n(void) { return BaseDS+reg_esi; }
+static PhysPt EA_32_07_n(void) { return BaseDS+reg_edi; }
+
+static PhysPt EA_32_40_n(void) { return BaseDS+reg_eax+Fetchbs(); }
+static PhysPt EA_32_41_n(void) { return BaseDS+reg_ecx+Fetchbs(); }
+static PhysPt EA_32_42_n(void) { return BaseDS+reg_edx+Fetchbs(); }
+static PhysPt EA_32_43_n(void) { return BaseDS+reg_ebx+Fetchbs(); }
+static PhysPt EA_32_44_n(void) { PhysPt temp=Sib(1);return temp+Fetchbs();}
+//static PhysPt EA_32_44_n(void) { return Sib(1)+Fetchbs();}
+static PhysPt EA_32_45_n(void) { return BaseSS+reg_ebp+Fetchbs(); }
+static PhysPt EA_32_46_n(void) { return BaseDS+reg_esi+Fetchbs(); }
+static PhysPt EA_32_47_n(void) { return BaseDS+reg_edi+Fetchbs(); }
+
+static PhysPt EA_32_80_n(void) { return BaseDS+reg_eax+Fetchds(); }
+static PhysPt EA_32_81_n(void) { return BaseDS+reg_ecx+Fetchds(); }
+static PhysPt EA_32_82_n(void) { return BaseDS+reg_edx+Fetchds(); }
+static PhysPt EA_32_83_n(void) { return BaseDS+reg_ebx+Fetchds(); }
+static PhysPt EA_32_84_n(void) { PhysPt temp=Sib(2);return temp+Fetchds();}
+//static PhysPt EA_32_84_n(void) { return Sib(2)+Fetchds();}
+static PhysPt EA_32_85_n(void) { return BaseSS+reg_ebp+Fetchds(); }
+static PhysPt EA_32_86_n(void) { return BaseDS+reg_esi+Fetchds(); }
+static PhysPt EA_32_87_n(void) { return BaseDS+reg_edi+Fetchds(); }
+
+static GetEAHandler EATable[512]={
+/* 00 */
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+       EA_16_00_n,EA_16_01_n,EA_16_02_n,EA_16_03_n,EA_16_04_n,EA_16_05_n,EA_16_06_n,EA_16_07_n,
+/* 01 */
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+       EA_16_40_n,EA_16_41_n,EA_16_42_n,EA_16_43_n,EA_16_44_n,EA_16_45_n,EA_16_46_n,EA_16_47_n,
+/* 10 */
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+       EA_16_80_n,EA_16_81_n,EA_16_82_n,EA_16_83_n,EA_16_84_n,EA_16_85_n,EA_16_86_n,EA_16_87_n,
+/* 11 These are illegal so make em 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,
+/* 00 */
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+       EA_32_00_n,EA_32_01_n,EA_32_02_n,EA_32_03_n,EA_32_04_n,EA_32_05_n,EA_32_06_n,EA_32_07_n,
+/* 01 */
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+       EA_32_40_n,EA_32_41_n,EA_32_42_n,EA_32_43_n,EA_32_44_n,EA_32_45_n,EA_32_46_n,EA_32_47_n,
+/* 10 */
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+       EA_32_80_n,EA_32_81_n,EA_32_82_n,EA_32_83_n,EA_32_84_n,EA_32_85_n,EA_32_86_n,EA_32_87_n,
+/* 11 These are illegal so make em 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
+};
+
+#define GetEADirect                                                    \
+       PhysPt eaa;                                                             \
+       if (TEST_PREFIX_ADDR) {                                 \
+               eaa=BaseDS+Fetchd();                            \
+       } else {                                                                \
+               eaa=BaseDS+Fetchw();                            \
+       }                                                                               \
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_prefetch.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/core_prefetch.cpp
new file mode 100644 (file)
index 0000000..47db2c1
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <stdio.h>
+
+#include "dosbox.h"
+#include "mem.h"
+#include "cpu.h"
+#include "lazyflags.h"
+#include "inout.h"
+#include "callback.h"
+#include "pic.h"
+#include "fpu.h"
+#include "paging.h"
+
+#if C_DEBUG
+#include "debug.h"
+#endif
+
+#if (!C_CORE_INLINE)
+#define LoadMb(off) mem_readb(off)
+#define LoadMw(off) mem_readw(off)
+#define LoadMd(off) mem_readd(off)
+#define SaveMb(off,val)        mem_writeb(off,val)
+#define SaveMw(off,val)        mem_writew(off,val)
+#define SaveMd(off,val)        mem_writed(off,val)
+#else 
+#include "paging.h"
+#define LoadMb(off) mem_readb_inline(off)
+#define LoadMw(off) mem_readw_inline(off)
+#define LoadMd(off) mem_readd_inline(off)
+#define SaveMb(off,val)        mem_writeb_inline(off,val)
+#define SaveMw(off,val)        mem_writew_inline(off,val)
+#define SaveMd(off,val)        mem_writed_inline(off,val)
+#endif
+
+extern Bitu cycle_count;
+
+#if C_FPU
+#define CPU_FPU        1                                               //Enable FPU escape instructions
+#endif
+
+#define CPU_PIC_CHECK 1
+#define CPU_TRAP_CHECK 1
+
+#define OPCODE_NONE                    0x000
+#define OPCODE_0F                      0x100
+#define OPCODE_SIZE                    0x200
+
+#define PREFIX_ADDR                    0x1
+#define PREFIX_REP                     0x2
+
+#define TEST_PREFIX_ADDR       (core.prefixes & PREFIX_ADDR)
+#define TEST_PREFIX_REP                (core.prefixes & PREFIX_REP)
+
+#define DO_PREFIX_SEG(_SEG)                                    \
+       BaseDS=SegBase(_SEG);                                   \
+       BaseSS=SegBase(_SEG);                                   \
+       core.base_val_ds=_SEG;                                  \
+       goto restart_opcode;
+
+#define DO_PREFIX_ADDR()                                                               \
+       core.prefixes=(core.prefixes & ~PREFIX_ADDR) |          \
+       (cpu.code.big ^ PREFIX_ADDR);                                           \
+       core.ea_table=&EATable[(core.prefixes&1) * 256];        \
+       goto restart_opcode;
+
+#define DO_PREFIX_REP(_ZERO)                           \
+       core.prefixes|=PREFIX_REP;                              \
+       core.rep_zero=_ZERO;                                    \
+       goto restart_opcode;
+
+typedef PhysPt (*GetEAHandler)(void);
+
+static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
+
+static struct {
+       Bitu opcode_index;
+       PhysPt cseip;
+       PhysPt base_ds,base_ss;
+       SegNames base_val_ds;
+       bool rep_zero;
+       Bitu prefixes;
+       GetEAHandler * ea_table;
+} core;
+
+#define GETIP          (core.cseip-SegBase(cs))
+#define SAVEIP         reg_eip=GETIP;
+#define LOADIP         core.cseip=(SegBase(cs)+reg_eip);
+
+#define SegBase(c)     SegPhys(c)
+#define BaseDS         core.base_ds
+#define BaseSS         core.base_ss
+
+
+#define MAX_PQ_SIZE 32
+static Bit8u prefetch_buffer[MAX_PQ_SIZE];
+static bool pq_valid=false;
+static Bitu pq_start;
+
+static Bit8u Fetchb() {
+       Bit8u temp;
+       if (pq_valid && (core.cseip>=pq_start) && (core.cseip<pq_start+CPU_PrefetchQueueSize)) {
+               temp=prefetch_buffer[core.cseip-pq_start];
+               if ((core.cseip+1>=pq_start+CPU_PrefetchQueueSize-4) &&
+                       (core.cseip+1<pq_start+CPU_PrefetchQueueSize)) {
+                       Bitu remaining_bytes=pq_start+CPU_PrefetchQueueSize-(core.cseip+1);
+                       for (Bitu i=0; i<remaining_bytes; i++) prefetch_buffer[i]=prefetch_buffer[core.cseip+1-pq_start+i];
+                       for (Bitu i=remaining_bytes; i<CPU_PrefetchQueueSize; i++) prefetch_buffer[i]=LoadMb(core.cseip+1+i);
+                       pq_start=core.cseip+1;
+                       pq_valid=true;
+               }
+       } else {
+               for (Bitu i=0; i<CPU_PrefetchQueueSize; i++) prefetch_buffer[i]=LoadMb(core.cseip+i);
+               pq_start=core.cseip;
+               pq_valid=true;
+               temp=prefetch_buffer[0];
+       }
+/*     if (temp!=LoadMb(core.cseip)) {
+               LOG_MSG("prefetch queue content!=memory at %x:%x",SegValue(cs),reg_eip);
+       } */
+       core.cseip+=1;
+       return temp;
+}
+
+static Bit16u Fetchw() {
+       Bit16u temp;
+       if (pq_valid && (core.cseip>=pq_start) && (core.cseip+2<pq_start+CPU_PrefetchQueueSize)) {
+               temp=prefetch_buffer[core.cseip-pq_start]|
+                       (prefetch_buffer[core.cseip-pq_start+1]<<8);
+               if ((core.cseip+2>=pq_start+CPU_PrefetchQueueSize-4) &&
+                       (core.cseip+2<pq_start+CPU_PrefetchQueueSize)) {
+                       Bitu remaining_bytes=pq_start+CPU_PrefetchQueueSize-(core.cseip+2);
+                       for (Bitu i=0; i<remaining_bytes; i++) prefetch_buffer[i]=prefetch_buffer[core.cseip+2-pq_start+i];
+                       for (Bitu i=remaining_bytes; i<CPU_PrefetchQueueSize; i++) prefetch_buffer[i]=LoadMb(core.cseip+2+i);
+                       pq_start=core.cseip+2;
+                       pq_valid=true;
+               }
+       } else {
+               for (Bitu i=0; i<CPU_PrefetchQueueSize; i++) prefetch_buffer[i]=LoadMb(core.cseip+i);
+               pq_start=core.cseip;
+               pq_valid=true;
+               temp=prefetch_buffer[0] | (prefetch_buffer[1]<<8);
+       }
+/*     if (temp!=LoadMw(core.cseip)) {
+               LOG_MSG("prefetch queue content!=memory at %x:%x",SegValue(cs),reg_eip);
+       } */
+       core.cseip+=2;
+       return temp;
+}
+
+static Bit32u Fetchd() {
+       Bit32u temp;
+       if (pq_valid && (core.cseip>=pq_start) && (core.cseip+4<pq_start+CPU_PrefetchQueueSize)) {
+               temp=prefetch_buffer[core.cseip-pq_start]|
+                       (prefetch_buffer[core.cseip-pq_start+1]<<8)|
+                       (prefetch_buffer[core.cseip-pq_start+2]<<16)|
+                       (prefetch_buffer[core.cseip-pq_start+3]<<24);
+               if ((core.cseip+4>=pq_start+CPU_PrefetchQueueSize-4) &&
+                       (core.cseip+4<pq_start+CPU_PrefetchQueueSize)) {
+                       Bitu remaining_bytes=pq_start+CPU_PrefetchQueueSize-(core.cseip+4);
+                       for (Bitu i=0; i<remaining_bytes; i++) prefetch_buffer[i]=prefetch_buffer[core.cseip+4-pq_start+i];
+                       for (Bitu i=remaining_bytes; i<CPU_PrefetchQueueSize; i++) prefetch_buffer[i]=LoadMb(core.cseip+4+i);
+                       pq_start=core.cseip+4;
+                       pq_valid=true;
+               }
+       } else {
+               for (Bitu i=0; i<CPU_PrefetchQueueSize; i++) prefetch_buffer[i]=LoadMb(core.cseip+i);
+               pq_start=core.cseip;
+               pq_valid=true;
+               temp=prefetch_buffer[0] | (prefetch_buffer[1]<<8) |
+                       (prefetch_buffer[2]<<16) | (prefetch_buffer[3]<<24);
+       }
+/*     if (temp!=LoadMd(core.cseip)) {
+               LOG_MSG("prefetch queue content!=memory at %x:%x",SegValue(cs),reg_eip);
+       } */
+       core.cseip+=4;
+       return temp;
+}
+
+#define Push_16 CPU_Push16
+#define Push_32 CPU_Push32
+#define Pop_16 CPU_Pop16
+#define Pop_32 CPU_Pop32
+
+#include "instructions.h"
+#include "core_normal/support.h"
+#include "core_normal/string.h"
+
+
+#define EALookupTable (core.ea_table)
+
+Bits CPU_Core_Prefetch_Run(void) {
+       bool invalidate_pq=false;
+       while (CPU_Cycles-->0) {
+               if (invalidate_pq) {
+                       pq_valid=false;
+                       invalidate_pq=false;
+               }
+               LOADIP;
+               core.opcode_index=cpu.code.big*0x200;
+               core.prefixes=cpu.code.big;
+               core.ea_table=&EATable[cpu.code.big*256];
+               BaseDS=SegBase(ds);
+               BaseSS=SegBase(ss);
+               core.base_val_ds=ds;
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+               if (DEBUG_HeavyIsBreakpoint()) {
+                       FillFlags();
+                       return debugCallback;
+               };
+#endif
+               cycle_count++;
+#endif
+restart_opcode:
+               Bit8u next_opcode=Fetchb();
+               invalidate_pq=false;
+               if (core.opcode_index&OPCODE_0F) invalidate_pq=true;
+               else switch (next_opcode) {
+                       case 0x70:      case 0x71:      case 0x72:      case 0x73:
+                       case 0x74:      case 0x75:      case 0x76:      case 0x77:
+                       case 0x78:      case 0x79:      case 0x7a:      case 0x7b:
+                       case 0x7c:      case 0x7d:      case 0x7e:      case 0x7f:      // jcc
+                       case 0x9a:      // call
+                       case 0xc2:      case 0xc3:      // retn
+                       case 0xc8:      // enter
+                       case 0xc9:      // leave
+                       case 0xca:      case 0xcb:      // retf
+                       case 0xcc:      // int3
+                       case 0xcd:      // int
+                       case 0xce:      // into
+                       case 0xcf:      // iret
+                       case 0xe0:      // loopnz
+                       case 0xe1:      // loopz
+                       case 0xe2:      // loop
+                       case 0xe3:      // jcxz
+                       case 0xe8:      // call
+                       case 0xe9:      case 0xea:      case 0xeb:      // jmp
+                       case 0xff:
+                               invalidate_pq=true;
+                               break;
+                       default:
+                               break;
+               }
+               switch (core.opcode_index+next_opcode) {
+               #include "core_normal/prefix_none.h"
+               #include "core_normal/prefix_0f.h"
+               #include "core_normal/prefix_66.h"
+               #include "core_normal/prefix_66_0f.h"
+               default:
+               illegal_opcode:
+#if C_DEBUG    
+                       {
+                               Bitu len=(GETIP-reg_eip);
+                               LOADIP;
+                               if (len>16) len=16;
+                               char tempcode[16*2+1];char * writecode=tempcode;
+                               for (;len>0;len--) {
+                                       sprintf(writecode,"%02X",mem_readb(core.cseip++));
+                                       writecode+=2;
+                               }
+                               LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode);
+                       }
+#endif
+                       CPU_Exception(6,0);
+                       invalidate_pq=true;
+                       continue;
+               }
+               SAVEIP;
+       }
+       FillFlags();
+       return CBRET_NONE;
+decode_end:
+       SAVEIP;
+       FillFlags();
+       return CBRET_NONE;
+}
+
+Bits CPU_Core_Prefetch_Trap_Run(void) {
+       Bits oldCycles = CPU_Cycles;
+       CPU_Cycles = 1;
+       cpu.trap_skip = false;
+
+       Bits ret=CPU_Core_Prefetch_Run();
+       if (!cpu.trap_skip) CPU_HW_Interrupt(1);
+       CPU_Cycles = oldCycles-1;
+       cpudecoder = &CPU_Core_Prefetch_Run;
+
+       return ret;
+}
+
+
+
+void CPU_Core_Prefetch_Init(void) {
+
+}
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/core_simple.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/core_simple.cpp
new file mode 100644 (file)
index 0000000..d8fdb9e
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+
+#include "dosbox.h"
+#include "mem.h"
+#include "cpu.h"
+#include "lazyflags.h"
+#include "inout.h"
+#include "callback.h"
+#include "pic.h"
+#include "fpu.h"
+
+#if C_DEBUG
+#include "debug.h"
+#endif
+
+#include "paging.h"
+#define SegBase(c)     SegPhys(c)
+#define LoadMb(off) mem_readb(off)
+#define LoadMw(off) mem_readw(off)
+#define LoadMd(off) mem_readd(off)
+
+#define SaveMb(off,val)        mem_writeb(off,val)
+#define SaveMw(off,val)        mem_writew(off,val)
+#define SaveMd(off,val)        mem_writed(off,val)
+
+extern Bitu cycle_count;
+
+#if C_FPU
+#define CPU_FPU        1                                               //Enable FPU escape instructions
+#endif
+
+#define CPU_PIC_CHECK 1
+#define CPU_TRAP_CHECK 1
+
+#define OPCODE_NONE                    0x000
+#define OPCODE_0F                      0x100
+#define OPCODE_SIZE                    0x200
+
+#define PREFIX_ADDR                    0x1
+#define PREFIX_REP                     0x2
+
+#define TEST_PREFIX_ADDR       (core.prefixes & PREFIX_ADDR)
+#define TEST_PREFIX_REP                (core.prefixes & PREFIX_REP)
+
+#define DO_PREFIX_SEG(_SEG)                                    \
+       BaseDS=SegBase(_SEG);                                   \
+       BaseSS=SegBase(_SEG);                                   \
+       core.base_val_ds=_SEG;                                  \
+       goto restart_opcode;
+
+#define DO_PREFIX_ADDR()                                                               \
+       core.prefixes=(core.prefixes & ~PREFIX_ADDR) |          \
+       (cpu.code.big ^ PREFIX_ADDR);                                           \
+       core.ea_table=&EATable[(core.prefixes&1) * 256];        \
+       goto restart_opcode;
+
+#define DO_PREFIX_REP(_ZERO)                           \
+       core.prefixes|=PREFIX_REP;                              \
+       core.rep_zero=_ZERO;                                    \
+       goto restart_opcode;
+
+typedef PhysPt (*GetEAHandler)(void);
+
+static const Bit32u AddrMaskTable[2]={0x0000ffff,0xffffffff};
+
+static struct {
+       Bitu opcode_index;
+#if defined (_MSC_VER)
+       volatile HostPt cseip;
+#else
+       HostPt cseip;
+#endif
+       PhysPt base_ds,base_ss;
+       SegNames base_val_ds;
+       bool rep_zero;
+       Bitu prefixes;
+       GetEAHandler * ea_table;
+} core;
+
+#define GETIP          (core.cseip-SegBase(cs)-MemBase)
+#define SAVEIP         reg_eip=GETIP;
+#define LOADIP         core.cseip=(MemBase+SegBase(cs)+reg_eip);
+
+#define SegBase(c)     SegPhys(c)
+#define BaseDS         core.base_ds
+#define BaseSS         core.base_ss
+
+static INLINE Bit8u Fetchb() {
+       Bit8u temp=host_readb(core.cseip);
+       core.cseip+=1;
+       return temp;
+}
+
+static INLINE Bit16u Fetchw() {
+       Bit16u temp=host_readw(core.cseip);
+       core.cseip+=2;
+       return temp;
+}
+static INLINE Bit32u Fetchd() {
+       Bit32u temp=host_readd(core.cseip);
+       core.cseip+=4;
+       return temp;
+}
+
+#define Push_16 CPU_Push16
+#define Push_32 CPU_Push32
+#define Pop_16 CPU_Pop16
+#define Pop_32 CPU_Pop32
+
+#include "instructions.h"
+#include "core_normal/support.h"
+#include "core_normal/string.h"
+
+
+#define EALookupTable (core.ea_table)
+
+Bits CPU_Core_Simple_Run(void) {
+       while (CPU_Cycles-->0) {
+               LOADIP;
+               core.opcode_index=cpu.code.big*0x200;
+               core.prefixes=cpu.code.big;
+               core.ea_table=&EATable[cpu.code.big*256];
+               BaseDS=SegBase(ds);
+               BaseSS=SegBase(ss);
+               core.base_val_ds=ds;
+#if C_DEBUG
+#if C_HEAVY_DEBUG
+               if (DEBUG_HeavyIsBreakpoint()) {
+                       FillFlags();
+                       return debugCallback;
+               };
+#endif
+               cycle_count++;
+#endif
+restart_opcode:
+               switch (core.opcode_index+Fetchb()) {
+
+               #include "core_normal/prefix_none.h"
+               #include "core_normal/prefix_0f.h"
+               #include "core_normal/prefix_66.h"
+               #include "core_normal/prefix_66_0f.h"
+               default:
+               illegal_opcode:
+#if C_DEBUG    
+                       {
+                               Bitu len=(GETIP-reg_eip);
+                               LOADIP;
+                               if (len>16) len=16;
+                               char tempcode[16*2+1];char * writecode=tempcode;
+                               for (;len>0;len--) {
+//                                     sprintf(writecode,"%X",mem_readb(core.cseip++));
+                                       writecode+=2;
+                               }
+                               LOG(LOG_CPU,LOG_NORMAL)("Illegal/Unhandled opcode %s",tempcode);
+                       }
+#endif
+                       CPU_Exception(6,0);
+                       continue;
+               }
+               SAVEIP;
+       }
+       FillFlags();
+       return CBRET_NONE;
+decode_end:
+       SAVEIP;
+       FillFlags();
+       return CBRET_NONE;
+}
+
+// not really used
+Bits CPU_Core_Simple_Trap_Run(void) {
+       Bits oldCycles = CPU_Cycles;
+       CPU_Cycles = 1;
+       cpu.trap_skip = false;
+
+       Bits ret=CPU_Core_Normal_Run();
+       if (!cpu.trap_skip) CPU_HW_Interrupt(1);
+       CPU_Cycles = oldCycles-1;
+       cpudecoder = &CPU_Core_Simple_Run;
+
+       return ret;
+}
+
+
+
+void CPU_Core_Simple_Init(void) {
+
+}
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/cpu.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/cpu.cpp
new file mode 100644 (file)
index 0000000..90b79b6
--- /dev/null
@@ -0,0 +1,2427 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <assert.h>
+#include <sstream>
+#include <stddef.h>
+#include "dosbox.h"
+#include "cpu.h"
+#include "memory.h"
+#include "debug.h"
+#include "mapper.h"
+#include "setup.h"
+#include "programs.h"
+#include "paging.h"
+#include "lazyflags.h"
+#include "support.h"
+
+Bitu DEBUG_EnableDebugger(void);
+extern void GFX_SetTitle(Bit32s cycles ,Bits frameskip,bool paused);
+
+#if 1
+#undef LOG
+#if defined (_MSC_VER)
+#define LOG(X,Y)
+#else
+#define LOG(X,Y) CPU_LOG
+#define CPU_LOG(...)
+#endif
+#endif
+
+CPU_Regs cpu_regs;
+CPUBlock cpu;
+Segments Segs;
+
+Bit32s CPU_Cycles = 0;
+Bit32s CPU_CycleLeft = 3000;
+Bit32s CPU_CycleMax = 3000;
+Bit32s CPU_OldCycleMax = 3000;
+Bit32s CPU_CyclePercUsed = 100;
+Bit32s CPU_CycleLimit = -1;
+Bit32s CPU_CycleUp = 0;
+Bit32s CPU_CycleDown = 0;
+Bit64s CPU_IODelayRemoved = 0;
+CPU_Decoder * cpudecoder;
+bool CPU_CycleAutoAdjust = false;
+bool CPU_SkipCycleAutoAdjust = false;
+Bitu CPU_AutoDetermineMode = 0;
+
+Bitu CPU_ArchitectureType = CPU_ARCHTYPE_MIXED;
+
+Bitu CPU_extflags_toggle=0;    // ID and AC flags may be toggled depending on emulated CPU architecture
+
+Bitu CPU_PrefetchQueueSize=0;
+
+void CPU_Core_Full_Init(void);
+void CPU_Core_Normal_Init(void);
+void CPU_Core_Simple_Init(void);
+#if (C_DYNAMIC_X86)
+void CPU_Core_Dyn_X86_Init(void);
+void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache);
+void CPU_Core_Dyn_X86_Cache_Close(void);
+void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu);
+#elif (C_DYNREC)
+void CPU_Core_Dynrec_Init(void);
+void CPU_Core_Dynrec_Cache_Init(bool enable_cache);
+void CPU_Core_Dynrec_Cache_Close(void);
+#endif
+
+/* In debug mode exceptions are tested and dosbox exits when 
+ * a unhandled exception state is detected. 
+ * USE CHECK_EXCEPT to raise an exception in that case to see if that exception
+ * solves the problem.
+ * 
+ * In non-debug mode dosbox doesn't do detection (and hence doesn't crash at
+ * that point). (game might crash later due to the unhandled exception) */
+
+#if C_DEBUG
+// #define CPU_CHECK_EXCEPT 1
+// #define CPU_CHECK_IGNORE 1
+ /* Use CHECK_EXCEPT when something doesn't work to see if a exception is 
+ * needed that isn't enabled by default.*/
+#else
+/* NORMAL NO CHECKING => More Speed */
+#define CPU_CHECK_IGNORE 1
+#endif /* C_DEBUG */
+
+#if defined(CPU_CHECK_IGNORE)
+#define CPU_CHECK_COND(cond,msg,exc,sel) {     \
+       if (cond) do {} while (0);                              \
+}
+#elif defined(CPU_CHECK_EXCEPT)
+#define CPU_CHECK_COND(cond,msg,exc,sel) {     \
+       if (cond) {                                     \
+               CPU_Exception(exc,sel);         \
+               return;                         \
+       }                                       \
+}
+#else
+#define CPU_CHECK_COND(cond,msg,exc,sel) {     \
+       if (cond) E_Exit(msg);                  \
+}
+#endif
+
+
+void Descriptor::Load(PhysPt address) {
+       cpu.mpl=0;
+       Bit32u* data = (Bit32u*)&saved;
+       *data     = mem_readd(address);
+       *(data+1) = mem_readd(address+4);
+       cpu.mpl=3;
+}
+void Descriptor:: Save(PhysPt address) {
+       cpu.mpl=0;
+       Bit32u* data = (Bit32u*)&saved;
+       mem_writed(address,*data);
+       mem_writed(address+4,*(data+1));
+       cpu.mpl=03;
+}
+
+
+void CPU_Push16(Bitu value) {
+       Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask);
+       mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value);
+       reg_esp=new_esp;
+}
+
+void CPU_Push32(Bitu value) {
+       Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-4)&cpu.stack.mask);
+       mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value);
+       reg_esp=new_esp;
+}
+
+Bitu CPU_Pop16(void) {
+       Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+       reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask);
+       return val;
+}
+
+Bitu CPU_Pop32(void) {
+       Bitu val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+       reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask);
+       return val;
+}
+
+PhysPt SelBase(Bitu sel) {
+       if (cpu.cr0 & CR0_PROTECTION) {
+               Descriptor desc;
+               cpu.gdt.GetDescriptor(sel,desc);
+               return desc.GetBase();
+       } else {
+               return sel<<4;
+       }
+}
+
+
+void CPU_SetFlags(Bitu word,Bitu mask) {
+       mask|=CPU_extflags_toggle;      // ID-flag and AC-flag can be toggled on CPUID-supporting CPUs
+       reg_flags=(reg_flags & ~mask)|(word & mask)|2;
+       cpu.direction=1-((reg_flags & FLAG_DF) >> 9);
+}
+
+bool CPU_PrepareException(Bitu which,Bitu error) {
+       cpu.exception.which=which;
+       cpu.exception.error=error;
+       return true;
+}
+
+bool CPU_CLI(void) {
+       if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
+               return CPU_PrepareException(EXCEPTION_GP,0);
+       } else {
+               SETFLAGBIT(IF,false);
+               return false;
+       }
+}
+
+bool CPU_STI(void) {
+       if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) || (GETFLAG(VM) && (GETFLAG_IOPL<3)))) {
+               return CPU_PrepareException(EXCEPTION_GP,0);
+       } else {
+               SETFLAGBIT(IF,true);
+               return false;
+       }
+}
+
+bool CPU_POPF(Bitu use32) {
+       if (cpu.pmode && GETFLAG(VM) && (GETFLAG(IOPL)!=FLAG_IOPL)) {
+               /* Not enough privileges to execute POPF */
+               return CPU_PrepareException(EXCEPTION_GP,0);
+       }
+       Bitu mask=FMASK_ALL;
+       /* IOPL field can only be modified when CPL=0 or in real mode: */
+       if (cpu.pmode && (cpu.cpl>0)) mask &= (~FLAG_IOPL);
+       if (cpu.pmode && !GETFLAG(VM) && (GETFLAG_IOPL<cpu.cpl)) mask &= (~FLAG_IF);
+       if (use32)
+               CPU_SetFlags(CPU_Pop32(),mask);
+       else CPU_SetFlags(CPU_Pop16(),mask & 0xffff);
+       DestroyConditionFlags();
+       return false;
+}
+
+bool CPU_PUSHF(Bitu use32) {
+       if (cpu.pmode && GETFLAG(VM) && (GETFLAG(IOPL)!=FLAG_IOPL)) {
+               /* Not enough privileges to execute PUSHF */
+               return CPU_PrepareException(EXCEPTION_GP,0);
+       }
+       FillFlags();
+       if (use32) 
+               CPU_Push32(reg_flags & 0xfcffff);
+       else CPU_Push16(reg_flags);
+       return false;
+}
+
+void CPU_CheckSegments(void) {
+       bool needs_invalidation=false;
+       Descriptor desc;
+       if (!cpu.gdt.GetDescriptor(SegValue(es),desc)) needs_invalidation=true;
+       else switch (desc.Type()) {
+               case DESC_DATA_EU_RO_NA:        case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+               case DESC_DATA_ED_RO_NA:        case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+               case DESC_CODE_N_NC_A:  case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A:  case DESC_CODE_R_NC_NA:
+                       if (cpu.cpl>desc.DPL()) needs_invalidation=true; break;
+               default: break; }
+       if (needs_invalidation) CPU_SetSegGeneral(es,0);
+
+       needs_invalidation=false;
+       if (!cpu.gdt.GetDescriptor(SegValue(ds),desc)) needs_invalidation=true;
+       else switch (desc.Type()) {
+               case DESC_DATA_EU_RO_NA:        case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+               case DESC_DATA_ED_RO_NA:        case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+               case DESC_CODE_N_NC_A:  case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A:  case DESC_CODE_R_NC_NA:
+                       if (cpu.cpl>desc.DPL()) needs_invalidation=true; break;
+               default: break; }
+       if (needs_invalidation) CPU_SetSegGeneral(ds,0);
+
+       needs_invalidation=false;
+       if (!cpu.gdt.GetDescriptor(SegValue(fs),desc)) needs_invalidation=true;
+       else switch (desc.Type()) {
+               case DESC_DATA_EU_RO_NA:        case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+               case DESC_DATA_ED_RO_NA:        case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+               case DESC_CODE_N_NC_A:  case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A:  case DESC_CODE_R_NC_NA:
+                       if (cpu.cpl>desc.DPL()) needs_invalidation=true; break;
+               default: break; }
+       if (needs_invalidation) CPU_SetSegGeneral(fs,0);
+
+       needs_invalidation=false;
+       if (!cpu.gdt.GetDescriptor(SegValue(gs),desc)) needs_invalidation=true;
+       else switch (desc.Type()) {
+               case DESC_DATA_EU_RO_NA:        case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+               case DESC_DATA_ED_RO_NA:        case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+               case DESC_CODE_N_NC_A:  case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A:  case DESC_CODE_R_NC_NA:
+                       if (cpu.cpl>desc.DPL()) needs_invalidation=true; break;
+               default: break; }
+       if (needs_invalidation) CPU_SetSegGeneral(gs,0);
+}
+
+
+class TaskStateSegment {
+public:
+       TaskStateSegment() {
+               valid=false;
+       }
+       bool IsValid(void) {
+               return valid;
+       }
+       Bitu Get_back(void) {
+               cpu.mpl=0;
+               Bit16u backlink=mem_readw(base);
+               cpu.mpl=3;
+               return backlink;
+       }
+       void SaveSelector(void) {
+               cpu.gdt.SetDescriptor(selector,desc);
+       }
+       void Get_SSx_ESPx(Bitu level,Bitu & _ss,Bitu & _esp) {
+               cpu.mpl=0;
+               if (is386) {
+                       PhysPt where=base+offsetof(TSS_32,esp0)+level*8;
+                       _esp=mem_readd(where);
+                       _ss=mem_readw(where+4);
+               } else {
+                       PhysPt where=base+offsetof(TSS_16,sp0)+level*4;
+                       _esp=mem_readw(where);
+                       _ss=mem_readw(where+2);
+               }
+               cpu.mpl=3;
+       }
+       bool SetSelector(Bitu new_sel) {
+               valid=false;
+               if ((new_sel & 0xfffc)==0) {
+                       selector=0;
+                       base=0;
+                       limit=0;
+                       is386=1;
+                       return true;
+               }
+               if (new_sel&4) return false;
+               if (!cpu.gdt.GetDescriptor(new_sel,desc)) return false;
+               switch (desc.Type()) {
+                       case DESC_286_TSS_A:            case DESC_286_TSS_B:
+                       case DESC_386_TSS_A:            case DESC_386_TSS_B:
+                               break;
+                       default:
+                               return false;
+               }
+               if (!desc.saved.seg.p) return false;
+               selector=new_sel;
+               valid=true;
+               base=desc.GetBase();
+               limit=desc.GetLimit();
+               is386=desc.Is386();
+               return true;
+       }
+       TSS_Descriptor desc;
+       Bitu selector;
+       PhysPt base;
+       Bitu limit;
+       Bitu is386;
+       bool valid;
+};
+
+TaskStateSegment cpu_tss;
+
+enum TSwitchType {
+       TSwitch_JMP,TSwitch_CALL_INT,TSwitch_IRET
+};
+
+bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype,Bitu old_eip) {
+       FillFlags();
+       TaskStateSegment new_tss;
+       if (!new_tss.SetSelector(new_tss_selector)) 
+               E_Exit("Illegal TSS for switch, selector=%x, switchtype=%x",new_tss_selector,tstype);
+       if (tstype==TSwitch_IRET) {
+               if (!new_tss.desc.IsBusy())
+                       E_Exit("TSS not busy for IRET");
+       } else {
+               if (new_tss.desc.IsBusy())
+                       E_Exit("TSS busy for JMP/CALL/INT");
+       }
+       Bitu new_cr3=0;
+       Bitu new_eax,new_ebx,new_ecx,new_edx,new_esp,new_ebp,new_esi,new_edi;
+       Bitu new_es,new_cs,new_ss,new_ds,new_fs,new_gs;
+       Bitu new_ldt,new_eip,new_eflags;
+       /* Read new context from new TSS */
+       if (new_tss.is386) {
+               new_cr3=mem_readd(new_tss.base+offsetof(TSS_32,cr3));
+               new_eip=mem_readd(new_tss.base+offsetof(TSS_32,eip));
+               new_eflags=mem_readd(new_tss.base+offsetof(TSS_32,eflags));
+               new_eax=mem_readd(new_tss.base+offsetof(TSS_32,eax));
+               new_ecx=mem_readd(new_tss.base+offsetof(TSS_32,ecx));
+               new_edx=mem_readd(new_tss.base+offsetof(TSS_32,edx));
+               new_ebx=mem_readd(new_tss.base+offsetof(TSS_32,ebx));
+               new_esp=mem_readd(new_tss.base+offsetof(TSS_32,esp));
+               new_ebp=mem_readd(new_tss.base+offsetof(TSS_32,ebp));
+               new_edi=mem_readd(new_tss.base+offsetof(TSS_32,edi));
+               new_esi=mem_readd(new_tss.base+offsetof(TSS_32,esi));
+
+               new_es=mem_readw(new_tss.base+offsetof(TSS_32,es));
+               new_cs=mem_readw(new_tss.base+offsetof(TSS_32,cs));
+               new_ss=mem_readw(new_tss.base+offsetof(TSS_32,ss));
+               new_ds=mem_readw(new_tss.base+offsetof(TSS_32,ds));
+               new_fs=mem_readw(new_tss.base+offsetof(TSS_32,fs));
+               new_gs=mem_readw(new_tss.base+offsetof(TSS_32,gs));
+               new_ldt=mem_readw(new_tss.base+offsetof(TSS_32,ldt));
+       } else {
+               E_Exit("286 task switch");
+               new_cr3=0;
+               new_eip=0;
+               new_eflags=0;
+               new_eax=0;      new_ecx=0;      new_edx=0;      new_ebx=0;
+               new_esp=0;      new_ebp=0;      new_edi=0;      new_esi=0;
+
+               new_es=0;       new_cs=0;       new_ss=0;       new_ds=0;       new_fs=0;       new_gs=0;
+               new_ldt=0;
+       }
+
+       /* Check if we need to clear busy bit of old TASK */
+       if (tstype==TSwitch_JMP || tstype==TSwitch_IRET) {
+               cpu_tss.desc.SetBusy(false);
+               cpu_tss.SaveSelector();
+       }
+       Bit32u old_flags = reg_flags;
+       if (tstype==TSwitch_IRET) old_flags &= (~FLAG_NT);
+
+       /* Save current context in current TSS */
+       if (cpu_tss.is386) {
+               mem_writed(cpu_tss.base+offsetof(TSS_32,eflags),old_flags);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,eip),old_eip);
+
+               mem_writed(cpu_tss.base+offsetof(TSS_32,eax),reg_eax);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,ecx),reg_ecx);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,edx),reg_edx);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,ebx),reg_ebx);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,esp),reg_esp);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,ebp),reg_ebp);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,esi),reg_esi);
+               mem_writed(cpu_tss.base+offsetof(TSS_32,edi),reg_edi);
+
+               mem_writed(cpu_tss.base+offsetof(TSS_32,es),SegValue(es));
+               mem_writed(cpu_tss.base+offsetof(TSS_32,cs),SegValue(cs));
+               mem_writed(cpu_tss.base+offsetof(TSS_32,ss),SegValue(ss));
+               mem_writed(cpu_tss.base+offsetof(TSS_32,ds),SegValue(ds));
+               mem_writed(cpu_tss.base+offsetof(TSS_32,fs),SegValue(fs));
+               mem_writed(cpu_tss.base+offsetof(TSS_32,gs),SegValue(gs));
+       } else {
+               E_Exit("286 task switch");
+       }
+
+       /* Setup a back link to the old TSS in new TSS */
+       if (tstype==TSwitch_CALL_INT) {
+               if (new_tss.is386) {
+                       mem_writed(new_tss.base+offsetof(TSS_32,back),cpu_tss.selector);
+               } else {
+                       mem_writew(new_tss.base+offsetof(TSS_16,back),cpu_tss.selector);
+               }
+               /* And make the new task's eflag have the nested task bit */
+               new_eflags|=FLAG_NT;
+       }
+       /* Set the busy bit in the new task */
+       if (tstype==TSwitch_JMP || tstype==TSwitch_CALL_INT) {
+               new_tss.desc.SetBusy(true);
+               new_tss.SaveSelector();
+       }
+
+//     cpu.cr0|=CR0_TASKSWITCHED;
+       if (new_tss_selector == cpu_tss.selector) {
+               reg_eip = old_eip;
+               new_cs = SegValue(cs);
+               new_ss = SegValue(ss);
+               new_ds = SegValue(ds);
+               new_es = SegValue(es);
+               new_fs = SegValue(fs);
+               new_gs = SegValue(gs);
+       } else {
+       
+               /* Setup the new cr3 */
+               PAGING_SetDirBase(new_cr3);
+
+               /* Load new context */
+               if (new_tss.is386) {
+                       reg_eip=new_eip;
+                       CPU_SetFlags(new_eflags,FMASK_ALL | FLAG_VM);
+                       reg_eax=new_eax;
+                       reg_ecx=new_ecx;
+                       reg_edx=new_edx;
+                       reg_ebx=new_ebx;
+                       reg_esp=new_esp;
+                       reg_ebp=new_ebp;
+                       reg_edi=new_edi;
+                       reg_esi=new_esi;
+
+//                     new_cs=mem_readw(new_tss.base+offsetof(TSS_32,cs));
+               } else {
+                       E_Exit("286 task switch");
+               }
+       }
+       /* Load the new selectors */
+       if (reg_flags & FLAG_VM) {
+               SegSet16(cs,new_cs);
+               cpu.code.big=false;
+               cpu.cpl=3;                      //We don't have segment caches so this will do
+       } else {
+               /* Protected mode task */
+               if (new_ldt!=0) CPU_LLDT(new_ldt);
+               /* Load the new CS*/
+               Descriptor cs_desc;
+               cpu.cpl=new_cs & 3;
+               if (!cpu.gdt.GetDescriptor(new_cs,cs_desc))
+                       E_Exit("Task switch with CS beyond limits");
+               if (!cs_desc.saved.seg.p)
+                       E_Exit("Task switch with non present code-segment");
+               switch (cs_desc.Type()) {
+               case DESC_CODE_N_NC_A:          case DESC_CODE_N_NC_NA:
+               case DESC_CODE_R_NC_A:          case DESC_CODE_R_NC_NA:
+                       if (cpu.cpl != cs_desc.DPL()) E_Exit("Task CS RPL != DPL");
+                       goto doconforming;
+               case DESC_CODE_N_C_A:           case DESC_CODE_N_C_NA:
+               case DESC_CODE_R_C_A:           case DESC_CODE_R_C_NA:
+                       if (cpu.cpl < cs_desc.DPL()) E_Exit("Task CS RPL < DPL");
+doconforming:
+                       Segs.phys[cs]=cs_desc.GetBase();
+                       cpu.code.big=cs_desc.Big()>0;
+                       Segs.val[cs]=new_cs;
+                       break;
+               default:
+                       E_Exit("Task switch CS Type %d",cs_desc.Type());
+               }
+       }
+       CPU_SetSegGeneral(es,new_es);
+       CPU_SetSegGeneral(ss,new_ss);
+       CPU_SetSegGeneral(ds,new_ds);
+       CPU_SetSegGeneral(fs,new_fs);
+       CPU_SetSegGeneral(gs,new_gs);
+       if (!cpu_tss.SetSelector(new_tss_selector)) {
+               LOG(LOG_CPU,LOG_NORMAL)("TaskSwitch: set tss selector %X failed",new_tss_selector);
+       }
+//     cpu_tss.desc.SetBusy(true);
+//     cpu_tss.SaveSelector();
+//     LOG_MSG("Task CPL %X CS:%X IP:%X SS:%X SP:%X eflags %x",cpu.cpl,SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags);
+       return true;
+}
+
+bool CPU_IO_Exception(Bitu port,Bitu size) {
+       if (cpu.pmode && ((GETFLAG_IOPL<cpu.cpl) || GETFLAG(VM))) {
+               cpu.mpl=0;
+               if (!cpu_tss.is386) goto doexception;
+               PhysPt bwhere=cpu_tss.base+0x66;
+               Bitu ofs=mem_readw(bwhere);
+               if (ofs>cpu_tss.limit) goto doexception;
+               bwhere=cpu_tss.base+ofs+(port/8);
+               Bitu map=mem_readw(bwhere);
+               Bitu mask=(0xffff>>(16-size)) << (port&7);
+               if (map & mask) goto doexception;
+               cpu.mpl=3;
+       }
+       return false;
+doexception:
+       cpu.mpl=3;
+       LOG(LOG_CPU,LOG_NORMAL)("IO Exception port %X",port);
+       return CPU_PrepareException(EXCEPTION_GP,0);
+}
+
+void CPU_Exception(Bitu which,Bitu error ) {
+//     LOG_MSG("Exception %d error %x",which,error);
+       cpu.exception.error=error;
+       CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip);
+}
+
+Bit8u lastint;
+void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) {
+       lastint=num;
+       FillFlags();
+#if C_DEBUG
+       switch (num) {
+       case 0xcd:
+#if C_HEAVY_DEBUG
+               LOG(LOG_CPU,LOG_ERROR)("Call to interrupt 0xCD this is BAD");
+               DEBUG_HeavyWriteLogInstruction();
+               E_Exit("Call to interrupt 0xCD this is BAD");
+#endif
+               break;
+       case 0x03:
+               if (DEBUG_Breakpoint()) {
+                       CPU_Cycles=0;
+                       return;
+               }
+       };
+#endif
+       if (!cpu.pmode) {
+               /* Save everything on a 16-bit stack */
+               CPU_Push16(reg_flags & 0xffff);
+               CPU_Push16(SegValue(cs));
+               CPU_Push16(oldeip);
+               SETFLAGBIT(IF,false);
+               SETFLAGBIT(TF,false);
+               /* Get the new CS:IP from vector table */
+               PhysPt base=cpu.idt.GetBase();
+               reg_eip=mem_readw(base+(num << 2));
+               Segs.val[cs]=mem_readw(base+(num << 2)+2);
+               Segs.phys[cs]=Segs.val[cs]<<4;
+               cpu.code.big=false;
+               return;
+       } else {
+               /* Protected Mode Interrupt */
+               if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE) && !(type&CPU_INT_NOIOPLCHECK)) {
+//                     LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12);
+                       if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
+                               CPU_Exception(EXCEPTION_GP,0);
+                               return;
+                       }
+               } 
+
+               Descriptor gate;
+               if (!cpu.idt.GetDescriptor(num<<3,gate)) {
+                       // zone66
+                       CPU_Exception(EXCEPTION_GP,num*8+2+(type&CPU_INT_SOFTWARE)?0:1);
+                       return;
+               }
+
+               if ((type&CPU_INT_SOFTWARE) && (gate.DPL()<cpu.cpl)) {
+                       // zone66, win3.x e
+                       CPU_Exception(EXCEPTION_GP,num*8+2);
+                       return;
+               }
+
+
+               switch (gate.Type()) {
+               case DESC_286_INT_GATE:         case DESC_386_INT_GATE:
+               case DESC_286_TRAP_GATE:        case DESC_386_TRAP_GATE:
+                       {
+                               CPU_CHECK_COND(!gate.saved.seg.p,
+                                       "INT:Gate segment not present",
+                                       EXCEPTION_NP,num*8+2+(type&CPU_INT_SOFTWARE)?0:1)
+
+                               Descriptor cs_desc;
+                               Bitu gate_sel=gate.GetSelector();
+                               Bitu gate_off=gate.GetOffset();
+                               CPU_CHECK_COND((gate_sel & 0xfffc)==0,
+                                       "INT:Gate with CS zero selector",
+                                       EXCEPTION_GP,(type&CPU_INT_SOFTWARE)?0:1)
+                               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(gate_sel,cs_desc),
+                                       "INT:Gate with CS beyond limit",
+                                       EXCEPTION_GP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1)
+
+                               Bitu cs_dpl=cs_desc.DPL();
+                               CPU_CHECK_COND(cs_dpl>cpu.cpl,
+                                       "Interrupt to higher privilege",
+                                       EXCEPTION_GP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1)
+                               switch (cs_desc.Type()) {
+                               case DESC_CODE_N_NC_A:  case DESC_CODE_N_NC_NA:
+                               case DESC_CODE_R_NC_A:  case DESC_CODE_R_NC_NA:
+                                       if (cs_dpl<cpu.cpl) {
+                                               /* Prepare for gate to inner level */
+                                               CPU_CHECK_COND(!cs_desc.saved.seg.p,
+                                                       "INT:Inner level:CS segment not present",
+                                                       EXCEPTION_NP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1)
+                                               CPU_CHECK_COND((reg_flags & FLAG_VM) && (cs_dpl!=0),
+                                                       "V86 interrupt calling codesegment with DPL>0",
+                                                       EXCEPTION_GP,gate_sel & 0xfffc)
+
+                                               Bitu n_ss,n_esp;
+                                               Bitu o_ss,o_esp;
+                                               o_ss=SegValue(ss);
+                                               o_esp=reg_esp;
+                                               cpu_tss.Get_SSx_ESPx(cs_dpl,n_ss,n_esp);
+                                               CPU_CHECK_COND((n_ss & 0xfffc)==0,
+                                                       "INT:Gate with SS zero selector",
+                                                       EXCEPTION_TS,(type&CPU_INT_SOFTWARE)?0:1)
+                                               Descriptor n_ss_desc;
+                                               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss,n_ss_desc),
+                                                       "INT:Gate with SS beyond limit",
+                                                       EXCEPTION_TS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1)
+                                               CPU_CHECK_COND(((n_ss & 3)!=cs_dpl) || (n_ss_desc.DPL()!=cs_dpl),
+                                                       "INT:Inner level with CS_DPL!=SS_DPL and SS_RPL",
+                                                       EXCEPTION_TS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1)
+
+                                               // check if stack segment is a writable data segment
+                                               switch (n_ss_desc.Type()) {
+                                               case DESC_DATA_EU_RW_NA:                case DESC_DATA_EU_RW_A:
+                                               case DESC_DATA_ED_RW_NA:                case DESC_DATA_ED_RW_A:
+                                                       break;
+                                               default:
+                                                       E_Exit("INT:Inner level:Stack segment not writable.");          // or #TS(ss_sel+EXT)
+                                               }
+                                               CPU_CHECK_COND(!n_ss_desc.saved.seg.p,
+                                                       "INT:Inner level with nonpresent SS",
+                                                       EXCEPTION_SS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1)
+
+                                               // commit point
+                                               Segs.phys[ss]=n_ss_desc.GetBase();
+                                               Segs.val[ss]=n_ss;
+                                               if (n_ss_desc.Big()) {
+                                                       cpu.stack.big=true;
+                                                       cpu.stack.mask=0xffffffff;
+                                                       cpu.stack.notmask=0;
+                                                       reg_esp=n_esp;
+                                               } else {
+                                                       cpu.stack.big=false;
+                                                       cpu.stack.mask=0xffff;
+                                                       cpu.stack.notmask=0xffff0000;
+                                                       reg_sp=n_esp & 0xffff;
+                                               }
+
+                                               cpu.cpl=cs_dpl;
+                                               if (gate.Type() & 0x8) {        /* 32-bit Gate */
+                                                       if (reg_flags & FLAG_VM) {
+                                                               CPU_Push32(SegValue(gs));SegSet16(gs,0x0);
+                                                               CPU_Push32(SegValue(fs));SegSet16(fs,0x0);
+                                                               CPU_Push32(SegValue(ds));SegSet16(ds,0x0);
+                                                               CPU_Push32(SegValue(es));SegSet16(es,0x0);
+                                                       }
+                                                       CPU_Push32(o_ss);
+                                                       CPU_Push32(o_esp);
+                                               } else {                                        /* 16-bit Gate */
+                                                       if (reg_flags & FLAG_VM) E_Exit("V86 to 16-bit gate");
+                                                       CPU_Push16(o_ss);
+                                                       CPU_Push16(o_esp);
+                                               }
+//                                             LOG_MSG("INT:Gate to inner level SS:%X SP:%X",n_ss,n_esp);
+                                               goto do_interrupt;
+                                       } 
+                                       if (cs_dpl!=cpu.cpl)
+                                               E_Exit("Non-conforming intra privilege INT with DPL!=CPL");
+                               case DESC_CODE_N_C_A:   case DESC_CODE_N_C_NA:
+                               case DESC_CODE_R_C_A:   case DESC_CODE_R_C_NA:
+                                       /* Prepare stack for gate to same priviledge */
+                                       CPU_CHECK_COND(!cs_desc.saved.seg.p,
+                                                       "INT:Same level:CS segment not present",
+                                               EXCEPTION_NP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1)
+                                       if ((reg_flags & FLAG_VM) && (cs_dpl<cpu.cpl))
+                                               E_Exit("V86 interrupt doesn't change to pl0");  // or #GP(cs_sel)
+
+                                       // commit point
+do_interrupt:
+                                       if (gate.Type() & 0x8) {        /* 32-bit Gate */
+                                               CPU_Push32(reg_flags);
+                                               CPU_Push32(SegValue(cs));
+                                               CPU_Push32(oldeip);
+                                               if (type & CPU_INT_HAS_ERROR) CPU_Push32(cpu.exception.error);
+                                       } else {                                        /* 16-bit gate */
+                                               CPU_Push16(reg_flags & 0xffff);
+                                               CPU_Push16(SegValue(cs));
+                                               CPU_Push16(oldeip);
+                                               if (type & CPU_INT_HAS_ERROR) CPU_Push16(cpu.exception.error);
+                                       }
+                                       break;          
+                               default:
+                                       E_Exit("INT:Gate Selector points to illegal descriptor with type %x",cs_desc.Type());
+                               }
+
+                               Segs.val[cs]=(gate_sel&0xfffc) | cpu.cpl;
+                               Segs.phys[cs]=cs_desc.GetBase();
+                               cpu.code.big=cs_desc.Big()>0;
+                               reg_eip=gate_off;
+
+                               if (!(gate.Type()&1)) {
+                                       SETFLAGBIT(IF,false);
+                               }
+                               SETFLAGBIT(TF,false);
+                               SETFLAGBIT(NT,false);
+                               SETFLAGBIT(VM,false);
+                               LOG(LOG_CPU,LOG_NORMAL)("INT:Gate to %X:%X big %d %s",gate_sel,gate_off,cs_desc.Big(),gate.Type() & 0x8 ? "386" : "286");
+                               return;
+                       }
+               case DESC_TASK_GATE:
+                       CPU_CHECK_COND(!gate.saved.seg.p,
+                               "INT:Gate segment not present",
+                               EXCEPTION_NP,num*8+2+(type&CPU_INT_SOFTWARE)?0:1)
+
+                       CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT,oldeip);
+                       if (type & CPU_INT_HAS_ERROR) {
+                               //TODO Be sure about this, seems somewhat unclear
+                               if (cpu_tss.is386) CPU_Push32(cpu.exception.error);
+                               else CPU_Push16(cpu.exception.error);
+                       }
+                       return;
+               default:
+                       E_Exit("Illegal descriptor type %X for int %X",gate.Type(),num);
+               }
+       }
+       assert(1);
+       return ; // make compiler happy
+}
+
+
+void CPU_IRET(bool use32,Bitu oldeip) {
+       if (!cpu.pmode) {                                       /* RealMode IRET */
+               if (use32) {
+                       reg_eip=CPU_Pop32();
+                       SegSet16(cs,CPU_Pop32());
+                       CPU_SetFlags(CPU_Pop32(),FMASK_ALL);
+               } else {
+                       reg_eip=CPU_Pop16();
+                       SegSet16(cs,CPU_Pop16());
+                       CPU_SetFlags(CPU_Pop16(),FMASK_ALL & 0xffff);
+               }
+               cpu.code.big=false;
+               DestroyConditionFlags();
+               return;
+       } else {        /* Protected mode IRET */
+               if (reg_flags & FLAG_VM) {
+                       if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) {
+                               // win3.x e
+                               CPU_Exception(EXCEPTION_GP,0);
+                               return;
+                       } else {
+                               if (use32) {
+                                       Bit32u new_eip=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+                                       Bit32u tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask);
+                                       Bit32u new_cs=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                                       tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask);
+                                       Bit32u new_flags=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                                       reg_esp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask);
+
+                                       reg_eip=new_eip;
+                                       SegSet16(cs,(Bit16u)(new_cs&0xffff));
+                                       /* IOPL can not be modified in v86 mode by IRET */
+                                       CPU_SetFlags(new_flags,FMASK_NORMAL|FLAG_NT);
+                               } else {
+                                       Bit16u new_eip=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+                                       Bit32u tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask);
+                                       Bit16u new_cs=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                                       tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask);
+                                       Bit16u new_flags=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                                       reg_esp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask);
+
+                                       reg_eip=(Bit32u)new_eip;
+                                       SegSet16(cs,new_cs);
+                                       /* IOPL can not be modified in v86 mode by IRET */
+                                       CPU_SetFlags(new_flags,FMASK_NORMAL|FLAG_NT);
+                               }
+                               cpu.code.big=false;
+                               DestroyConditionFlags();
+                               return;
+                       }
+               }
+               /* Check if this is task IRET */        
+               if (GETFLAG(NT)) {
+                       if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set");
+                       CPU_CHECK_COND(!cpu_tss.IsValid(),
+                               "TASK Iret without valid TSS",
+                               EXCEPTION_TS,cpu_tss.selector & 0xfffc)
+                       if (!cpu_tss.desc.IsBusy()) {
+                               LOG(LOG_CPU,LOG_ERROR)("TASK Iret:TSS not busy");
+                       }
+                       Bitu back_link=cpu_tss.Get_back();
+                       CPU_SwitchTask(back_link,TSwitch_IRET,oldeip);
+                       return;
+               }
+               Bitu n_cs_sel,n_eip,n_flags;
+               Bit32u tempesp;
+               if (use32) {
+                       n_eip=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+                       tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask);
+                       n_cs_sel=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)) & 0xffff;
+                       tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask);
+                       n_flags=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                       tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask);
+
+                       if ((n_flags & FLAG_VM) && (cpu.cpl==0)) {
+                               // commit point
+                               reg_esp=tempesp;
+                               reg_eip=n_eip & 0xffff;
+                               Bitu n_ss,n_esp,n_es,n_ds,n_fs,n_gs;
+                               n_esp=CPU_Pop32();
+                               n_ss=CPU_Pop32() & 0xffff;
+                               n_es=CPU_Pop32() & 0xffff;
+                               n_ds=CPU_Pop32() & 0xffff;
+                               n_fs=CPU_Pop32() & 0xffff;
+                               n_gs=CPU_Pop32() & 0xffff;
+
+                               CPU_SetFlags(n_flags,FMASK_ALL | FLAG_VM);
+                               DestroyConditionFlags();
+                               cpu.cpl=3;
+
+                               CPU_SetSegGeneral(ss,n_ss);
+                               CPU_SetSegGeneral(es,n_es);
+                               CPU_SetSegGeneral(ds,n_ds);
+                               CPU_SetSegGeneral(fs,n_fs);
+                               CPU_SetSegGeneral(gs,n_gs);
+                               reg_esp=n_esp;
+                               cpu.code.big=false;
+                               SegSet16(cs,n_cs_sel);
+                               LOG(LOG_CPU,LOG_NORMAL)("IRET:Back to V86: CS:%X IP %X SS:%X SP %X FLAGS:%X",SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags);      
+                               return;
+                       }
+                       if (n_flags & FLAG_VM) E_Exit("IRET from pmode to v86 with CPL!=0");
+               } else {
+                       n_eip=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+                       tempesp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask);
+                       n_cs_sel=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                       tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask);
+                       n_flags=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                       n_flags|=(reg_flags & 0xffff0000);
+                       tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask);
+
+                       if (n_flags & FLAG_VM) E_Exit("VM Flag in 16-bit iret");
+               }
+               CPU_CHECK_COND((n_cs_sel & 0xfffc)==0,
+                       "IRET:CS selector zero",
+                       EXCEPTION_GP,0)
+               Bitu n_cs_rpl=n_cs_sel & 3;
+               Descriptor n_cs_desc;
+               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc),
+                       "IRET:CS selector beyond limits",
+                       EXCEPTION_GP,n_cs_sel & 0xfffc)
+               CPU_CHECK_COND(n_cs_rpl<cpu.cpl,
+                       "IRET to lower privilege",
+                       EXCEPTION_GP,n_cs_sel & 0xfffc)
+
+               switch (n_cs_desc.Type()) {
+               case DESC_CODE_N_NC_A:  case DESC_CODE_N_NC_NA:
+               case DESC_CODE_R_NC_A:  case DESC_CODE_R_NC_NA:
+               case 18:
+                       CPU_CHECK_COND(n_cs_rpl!=n_cs_desc.DPL(),
+                               "IRET:NC:DPL!=RPL",
+                               EXCEPTION_GP,n_cs_sel & 0xfffc)
+                       break;
+               case DESC_CODE_N_C_A:   case DESC_CODE_N_C_NA:
+               case DESC_CODE_R_C_A:   case DESC_CODE_R_C_NA:
+                       CPU_CHECK_COND(n_cs_desc.DPL()>n_cs_rpl,
+                               "IRET:C:DPL>RPL",
+                               EXCEPTION_GP,n_cs_sel & 0xfffc)
+                       break;
+               default:
+                       E_Exit("IRET:Illegal descriptor type %X",n_cs_desc.Type());
+               }
+               CPU_CHECK_COND(!n_cs_desc.saved.seg.p,
+                       "IRET with nonpresent code segment",
+                       EXCEPTION_NP,n_cs_sel & 0xfffc)
+
+               if (n_cs_rpl==cpu.cpl) {        
+                       /* Return to same level */
+
+                       // commit point
+                       reg_esp=tempesp;
+                       Segs.phys[cs]=n_cs_desc.GetBase();
+                       cpu.code.big=n_cs_desc.Big()>0;
+                       Segs.val[cs]=n_cs_sel;
+                       reg_eip=n_eip;
+
+                       Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL;
+                       if (GETFLAG_IOPL<cpu.cpl) mask &= (~FLAG_IF);
+                       CPU_SetFlags(n_flags,mask);
+                       DestroyConditionFlags();
+                       LOG(LOG_CPU,LOG_NORMAL)("IRET:Same level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
+               } else {
+                       /* Return to outer level */
+                       Bitu n_ss,n_esp;
+                       if (use32) {
+                               n_esp=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                               tempesp=(tempesp&cpu.stack.notmask)|((tempesp+4)&cpu.stack.mask);
+                               n_ss=mem_readd(SegPhys(ss) + (tempesp & cpu.stack.mask)) & 0xffff;
+                       } else {
+                               n_esp=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                               tempesp=(tempesp&cpu.stack.notmask)|((tempesp+2)&cpu.stack.mask);
+                               n_ss=mem_readw(SegPhys(ss) + (tempesp & cpu.stack.mask));
+                       }
+                       CPU_CHECK_COND((n_ss & 0xfffc)==0,
+                               "IRET:Outer level:SS selector zero",
+                               EXCEPTION_GP,0)
+                       CPU_CHECK_COND((n_ss & 3)!=n_cs_rpl,
+                               "IRET:Outer level:SS rpl!=CS rpl",
+                               EXCEPTION_GP,n_ss & 0xfffc)
+                       Descriptor n_ss_desc;
+                       CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss,n_ss_desc),
+                               "IRET:Outer level:SS beyond limit",
+                               EXCEPTION_GP,n_ss & 0xfffc)
+                       CPU_CHECK_COND(n_ss_desc.DPL()!=n_cs_rpl,
+                               "IRET:Outer level:SS dpl!=CS rpl",
+                               EXCEPTION_GP,n_ss & 0xfffc)
+
+                       // check if stack segment is a writable data segment
+                       switch (n_ss_desc.Type()) {
+                       case DESC_DATA_EU_RW_NA:                case DESC_DATA_EU_RW_A:
+                       case DESC_DATA_ED_RW_NA:                case DESC_DATA_ED_RW_A:
+                               break;
+                       default:
+                               E_Exit("IRET:Outer level:Stack segment not writable");          // or #GP(ss_sel)
+                       }
+                       CPU_CHECK_COND(!n_ss_desc.saved.seg.p,
+                               "IRET:Outer level:Stack segment not present",
+                               EXCEPTION_NP,n_ss & 0xfffc)
+
+                       // commit point
+
+                       Segs.phys[cs]=n_cs_desc.GetBase();
+                       cpu.code.big=n_cs_desc.Big()>0;
+                       Segs.val[cs]=n_cs_sel;
+
+                       Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL;
+                       if (GETFLAG_IOPL<cpu.cpl) mask &= (~FLAG_IF);
+                       CPU_SetFlags(n_flags,mask);
+                       DestroyConditionFlags();
+
+                       cpu.cpl=n_cs_rpl;
+                       reg_eip=n_eip;
+
+                       Segs.val[ss]=n_ss;
+                       Segs.phys[ss]=n_ss_desc.GetBase();
+                       if (n_ss_desc.Big()) {
+                               cpu.stack.big=true;
+                               cpu.stack.mask=0xffffffff;
+                               cpu.stack.notmask=0;
+                               reg_esp=n_esp;
+                       } else {
+                               cpu.stack.big=false;
+                               cpu.stack.mask=0xffff;
+                               cpu.stack.notmask=0xffff0000;
+                               reg_sp=n_esp & 0xffff;
+                       }
+
+                       // borland extender, zrdx
+                       CPU_CheckSegments();
+
+                       LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big);
+               }
+               return;
+       }
+}
+
+
+void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
+       if (!cpu.pmode || (reg_flags & FLAG_VM)) {
+               if (!use32) {
+                       reg_eip=offset&0xffff;
+               } else {
+                       reg_eip=offset;
+               }
+               SegSet16(cs,selector);
+               cpu.code.big=false;
+               return;
+       } else {
+               CPU_CHECK_COND((selector & 0xfffc)==0,
+                       "JMP:CS selector zero",
+                       EXCEPTION_GP,0)
+               Bitu rpl=selector & 3;
+               Descriptor desc;
+               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(selector,desc),
+                       "JMP:CS beyond limits",
+                       EXCEPTION_GP,selector & 0xfffc)
+               switch (desc.Type()) {
+               case DESC_CODE_N_NC_A:          case DESC_CODE_N_NC_NA:
+               case DESC_CODE_R_NC_A:          case DESC_CODE_R_NC_NA:
+               case 18:
+                       CPU_CHECK_COND(rpl>cpu.cpl,
+                               "JMP:NC:RPL>CPL",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       CPU_CHECK_COND(cpu.cpl!=desc.DPL(),
+                               "JMP:NC:RPL != DPL",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big());
+                       goto CODE_jmp;
+               case DESC_CODE_N_C_A:           case DESC_CODE_N_C_NA:
+               case DESC_CODE_R_C_A:           case DESC_CODE_R_C_NA:
+                       LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:C to %X:%X big %d",selector,offset,desc.Big());
+                       CPU_CHECK_COND(cpu.cpl<desc.DPL(),
+                               "JMP:C:CPL < DPL",
+                               EXCEPTION_GP,selector & 0xfffc)
+CODE_jmp:
+                       if (!desc.saved.seg.p) {
+                               // win
+                               CPU_Exception(EXCEPTION_NP,selector & 0xfffc);
+                               return;
+                       }
+
+                       /* Normal jump to another selector:offset */
+                       Segs.phys[cs]=desc.GetBase();
+                       cpu.code.big=desc.Big()>0;
+                       Segs.val[cs]=(selector & 0xfffc) | cpu.cpl;
+                       reg_eip=offset;
+                       return;
+               case DESC_386_TSS_A:
+                       CPU_CHECK_COND(desc.DPL()<cpu.cpl,
+                               "JMP:TSS:dpl<cpl",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       CPU_CHECK_COND(desc.DPL()<rpl,
+                               "JMP:TSS:dpl<rpl",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       LOG(LOG_CPU,LOG_NORMAL)("JMP:TSS to %X",selector);
+                       CPU_SwitchTask(selector,TSwitch_JMP,oldeip);
+                       break;
+               default:
+                       E_Exit("JMP Illegal descriptor type %X",desc.Type());
+               }
+       }
+       assert(1);
+}
+
+
+void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip) {
+       if (!cpu.pmode || (reg_flags & FLAG_VM)) {
+               if (!use32) {
+                       CPU_Push16(SegValue(cs));
+                       CPU_Push16(oldeip);
+                       reg_eip=offset&0xffff;
+               } else {
+                       CPU_Push32(SegValue(cs));
+                       CPU_Push32(oldeip);
+                       reg_eip=offset;
+               }
+               cpu.code.big=false;
+               SegSet16(cs,selector);
+               return;
+       } else {
+               CPU_CHECK_COND((selector & 0xfffc)==0,
+                       "CALL:CS selector zero",
+                       EXCEPTION_GP,0)
+               Bitu rpl=selector & 3;
+               Descriptor call;
+               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(selector,call),
+                       "CALL:CS beyond limits",
+                       EXCEPTION_GP,selector & 0xfffc)
+               /* Check for type of far call */
+               switch (call.Type()) {
+               case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA:
+               case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA:
+                       CPU_CHECK_COND(rpl>cpu.cpl,
+                               "CALL:CODE:NC:RPL>CPL",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       CPU_CHECK_COND(call.DPL()!=cpu.cpl,
+                               "CALL:CODE:NC:DPL!=CPL",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:NC to %X:%X",selector,offset);
+                       goto call_code; 
+               case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA:
+               case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA:
+                       CPU_CHECK_COND(call.DPL()>cpu.cpl,
+                               "CALL:CODE:C:DPL>CPL",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:C to %X:%X",selector,offset);
+call_code:
+                       if (!call.saved.seg.p) {
+                               // borland extender (RTM)
+                               CPU_Exception(EXCEPTION_NP,selector & 0xfffc);
+                               return;
+                       }
+                       // commit point
+                       if (!use32) {
+                               CPU_Push16(SegValue(cs));
+                               CPU_Push16(oldeip);
+                               reg_eip=offset & 0xffff;
+                       } else {
+                               CPU_Push32(SegValue(cs));
+                               CPU_Push32(oldeip);
+                               reg_eip=offset;
+                       }
+                       Segs.phys[cs]=call.GetBase();
+                       cpu.code.big=call.Big()>0;
+                       Segs.val[cs]=(selector & 0xfffc) | cpu.cpl;
+                       return;
+               case DESC_386_CALL_GATE: 
+               case DESC_286_CALL_GATE:
+                       {
+                               CPU_CHECK_COND(call.DPL()<cpu.cpl,
+                                       "CALL:Gate:Gate DPL<CPL",
+                                       EXCEPTION_GP,selector & 0xfffc)
+                               CPU_CHECK_COND(call.DPL()<rpl,
+                                       "CALL:Gate:Gate DPL<RPL",
+                                       EXCEPTION_GP,selector & 0xfffc)
+                               CPU_CHECK_COND(!call.saved.seg.p,
+                                       "CALL:Gate:Segment not present",
+                                       EXCEPTION_NP,selector & 0xfffc)
+                               Descriptor n_cs_desc;
+                               Bitu n_cs_sel=call.GetSelector();
+
+                               CPU_CHECK_COND((n_cs_sel & 0xfffc)==0,
+                                       "CALL:Gate:CS selector zero",
+                                       EXCEPTION_GP,0)
+                               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc),
+                                       "CALL:Gate:CS beyond limits",
+                                       EXCEPTION_GP,n_cs_sel & 0xfffc)
+                               Bitu n_cs_dpl   = n_cs_desc.DPL();
+                               CPU_CHECK_COND(n_cs_dpl>cpu.cpl,
+                                       "CALL:Gate:CS DPL>CPL",
+                                       EXCEPTION_GP,n_cs_sel & 0xfffc)
+
+                               CPU_CHECK_COND(!n_cs_desc.saved.seg.p,
+                                       "CALL:Gate:CS not present",
+                                       EXCEPTION_NP,n_cs_sel & 0xfffc)
+
+                               Bitu n_eip              = call.GetOffset();
+                               switch (n_cs_desc.Type()) {
+                               case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA:
+                               case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA:
+                                       /* Check if we goto inner priviledge */
+                                       if (n_cs_dpl < cpu.cpl) {
+                                               /* Get new SS:ESP out of TSS */
+                                               Bitu n_ss_sel,n_esp;
+                                               Descriptor n_ss_desc;
+                                               cpu_tss.Get_SSx_ESPx(n_cs_dpl,n_ss_sel,n_esp);
+                                               CPU_CHECK_COND((n_ss_sel & 0xfffc)==0,
+                                                       "CALL:Gate:NC:SS selector zero",
+                                                       EXCEPTION_TS,0)
+                                               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss_sel,n_ss_desc),
+                                                       "CALL:Gate:Invalid SS selector",
+                                                       EXCEPTION_TS,n_ss_sel & 0xfffc)
+                                               CPU_CHECK_COND(((n_ss_sel & 3)!=n_cs_desc.DPL()) || (n_ss_desc.DPL()!=n_cs_desc.DPL()),
+                                                       "CALL:Gate:Invalid SS selector privileges",
+                                                       EXCEPTION_TS,n_ss_sel & 0xfffc)
+
+                                               switch (n_ss_desc.Type()) {
+                                               case DESC_DATA_EU_RW_NA:                case DESC_DATA_EU_RW_A:
+                                               case DESC_DATA_ED_RW_NA:                case DESC_DATA_ED_RW_A:
+                                                       // writable data segment
+                                                       break;
+                                               default:
+                                                       E_Exit("Call:Gate:SS no writable data segment");        // or #TS(ss_sel)
+                                               }
+                                               CPU_CHECK_COND(!n_ss_desc.saved.seg.p,
+                                                       "CALL:Gate:Stack segment not present",
+                                                       EXCEPTION_SS,n_ss_sel & 0xfffc)
+
+                                               /* Load the new SS:ESP and save data on it */
+                                               Bitu o_esp              = reg_esp;
+                                               Bitu o_ss               = SegValue(ss);
+                                               PhysPt o_stack  = SegPhys(ss)+(reg_esp & cpu.stack.mask);
+
+
+                                               // catch pagefaults
+                                               if (call.saved.gate.paramcount&31) {
+                                                       if (call.Type()==DESC_386_CALL_GATE) {
+                                                               for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) 
+                                                                       mem_readd(o_stack+i*4);
+                                                       } else {
+                                                               for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
+                                                                       mem_readw(o_stack+i*2);
+                                                       }
+                                               }
+
+                                               // commit point
+                                               Segs.val[ss]=n_ss_sel;
+                                               Segs.phys[ss]=n_ss_desc.GetBase();
+                                               if (n_ss_desc.Big()) {
+                                                       cpu.stack.big=true;
+                                                       cpu.stack.mask=0xffffffff;
+                                                       cpu.stack.notmask=0;
+                                                       reg_esp=n_esp;
+                                               } else {
+                                                       cpu.stack.big=false;
+                                                       cpu.stack.mask=0xffff;
+                                                       cpu.stack.notmask=0xffff0000;
+                                                       reg_sp=n_esp & 0xffff;
+                                               }
+
+                                               cpu.cpl = n_cs_desc.DPL();
+                                               Bit16u oldcs    = SegValue(cs);
+                                               /* Switch to new CS:EIP */
+                                               Segs.phys[cs]   = n_cs_desc.GetBase();
+                                               Segs.val[cs]    = (n_cs_sel & 0xfffc) | cpu.cpl;
+                                               cpu.code.big    = n_cs_desc.Big()>0;
+                                               reg_eip                 = n_eip;
+                                               if (!use32)     reg_eip&=0xffff;
+
+                                               if (call.Type()==DESC_386_CALL_GATE) {
+                                                       CPU_Push32(o_ss);               //save old stack
+                                                       CPU_Push32(o_esp);
+                                                       if (call.saved.gate.paramcount&31)
+                                                               for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) 
+                                                                       CPU_Push32(mem_readd(o_stack+i*4));
+                                                       CPU_Push32(oldcs);
+                                                       CPU_Push32(oldeip);
+                                               } else {
+                                                       CPU_Push16(o_ss);               //save old stack
+                                                       CPU_Push16(o_esp);
+                                                       if (call.saved.gate.paramcount&31)
+                                                               for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--)
+                                                                       CPU_Push16(mem_readw(o_stack+i*2));
+                                                       CPU_Push16(oldcs);
+                                                       CPU_Push16(oldeip);
+                                               }
+
+                                               break;          
+                                       } else if (n_cs_dpl > cpu.cpl)
+                                               E_Exit("CALL:GATE:CS DPL>CPL");         // or #GP(sel)
+                               case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA:
+                               case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA:
+                                       // zrdx extender
+
+                                       if (call.Type()==DESC_386_CALL_GATE) {
+                                               CPU_Push32(SegValue(cs));
+                                               CPU_Push32(oldeip);
+                                       } else {
+                                               CPU_Push16(SegValue(cs));
+                                               CPU_Push16(oldeip);
+                                       }
+
+                                       /* Switch to new CS:EIP */
+                                       Segs.phys[cs]   = n_cs_desc.GetBase();
+                                       Segs.val[cs]    = (n_cs_sel & 0xfffc) | cpu.cpl;
+                                       cpu.code.big    = n_cs_desc.Big()>0;
+                                       reg_eip                 = n_eip;
+                                       if (!use32)     reg_eip&=0xffff;
+                                       break;
+                               default:
+                                       E_Exit("CALL:GATE:CS no executable segment");
+                               }
+                       }                       /* Call Gates */
+                       break;
+               case DESC_386_TSS_A:
+                       CPU_CHECK_COND(call.DPL()<cpu.cpl,
+                               "CALL:TSS:dpl<cpl",
+                               EXCEPTION_GP,selector & 0xfffc)
+                       CPU_CHECK_COND(call.DPL()<rpl,
+                               "CALL:TSS:dpl<rpl",
+                               EXCEPTION_GP,selector & 0xfffc)
+
+                       CPU_CHECK_COND(!call.saved.seg.p,
+                               "CALL:TSS:Segment not present",
+                               EXCEPTION_NP,selector & 0xfffc)
+
+                       LOG(LOG_CPU,LOG_NORMAL)("CALL:TSS to %X",selector);
+                       CPU_SwitchTask(selector,TSwitch_CALL_INT,oldeip);
+                       break;
+               case DESC_DATA_EU_RW_NA:        // vbdos
+               case DESC_INVALID:                      // used by some installers
+                       CPU_Exception(EXCEPTION_GP,selector & 0xfffc);
+                       return;
+               default:
+                       E_Exit("CALL:Descriptor type %x unsupported",call.Type());
+               }
+       }
+       assert(1);
+}
+
+
+void CPU_RET(bool use32,Bitu bytes,Bitu oldeip) {
+       if (!cpu.pmode || (reg_flags & FLAG_VM)) {
+               Bitu new_ip,new_cs;
+               if (!use32) {
+                       new_ip=CPU_Pop16();
+                       new_cs=CPU_Pop16();
+               } else {
+                       new_ip=CPU_Pop32();
+                       new_cs=CPU_Pop32() & 0xffff;
+               }
+               reg_esp+=bytes;
+               SegSet16(cs,new_cs);
+               reg_eip=new_ip;
+               cpu.code.big=false;
+               return;
+       } else {
+               Bitu offset,selector;
+               if (!use32) selector    = mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask) + 2);
+               else            selector        = mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask) + 4) & 0xffff;
+
+               Descriptor desc;
+               Bitu rpl=selector & 3;
+               if(rpl < cpu.cpl) {
+                       // win setup
+                       CPU_Exception(EXCEPTION_GP,selector & 0xfffc);
+                       return;
+               }
+
+               CPU_CHECK_COND((selector & 0xfffc)==0,
+                       "RET:CS selector zero",
+                       EXCEPTION_GP,0)
+               CPU_CHECK_COND(!cpu.gdt.GetDescriptor(selector,desc),
+                       "RET:CS beyond limits",
+                       EXCEPTION_GP,selector & 0xfffc)
+
+               if (cpu.cpl==rpl) {     
+                       /* Return to same level */
+                       switch (desc.Type()) {
+                       case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA:
+                       case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA:
+                       case 18:
+                               CPU_CHECK_COND(cpu.cpl!=desc.DPL(),
+                                       "RET to NC segment of other privilege",
+                                       EXCEPTION_GP,selector & 0xfffc)
+                               goto RET_same_level;
+                       case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA:
+                       case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA:
+                               CPU_CHECK_COND(desc.DPL()>cpu.cpl,
+                                       "RET to C segment of higher privilege",
+                                       EXCEPTION_GP,selector & 0xfffc)
+                               break;
+                       default:
+                               E_Exit("RET from illegal descriptor type %X",desc.Type());
+                       }
+RET_same_level:
+                       if (!desc.saved.seg.p) {
+                               // borland extender (RTM)
+                               CPU_Exception(EXCEPTION_NP,selector & 0xfffc);
+                               return;
+                       }
+
+                       // commit point
+                       if (!use32) {
+                               offset=CPU_Pop16();
+                               selector=CPU_Pop16();
+                       } else {
+                               offset=CPU_Pop32();
+                               selector=CPU_Pop32() & 0xffff;
+                       }
+
+                       Segs.phys[cs]=desc.GetBase();
+                       cpu.code.big=desc.Big()>0;
+                       Segs.val[cs]=selector;
+                       reg_eip=offset;
+                       if (cpu.stack.big) {
+                               reg_esp+=bytes;
+                       } else {
+                               reg_sp+=bytes;
+                       }
+                       LOG(LOG_CPU,LOG_NORMAL)("RET - Same level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL());
+                       return;
+               } else {
+                       /* Return to outer level */
+                       switch (desc.Type()) {
+                       case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA:
+                       case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA:
+                               CPU_CHECK_COND(desc.DPL()!=rpl,
+                                       "RET to outer NC segment with DPL!=RPL",
+                                       EXCEPTION_GP,selector & 0xfffc)
+                               break;
+                       case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA:
+                       case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA:
+                               CPU_CHECK_COND(desc.DPL()>rpl,
+                                       "RET to outer C segment with DPL>RPL",
+                                       EXCEPTION_GP,selector & 0xfffc)
+                               break;
+                       default:
+                               E_Exit("RET from illegal descriptor type %X",desc.Type());              // or #GP(selector)
+                       }
+
+                       CPU_CHECK_COND(!desc.saved.seg.p,
+                               "RET:Outer level:CS not present",
+                               EXCEPTION_NP,selector & 0xfffc)
+
+                       // commit point
+                       Bitu n_esp,n_ss;
+                       if (use32) {
+                               offset=CPU_Pop32();
+                               selector=CPU_Pop32() & 0xffff;
+                               reg_esp+=bytes;
+                               n_esp = CPU_Pop32();
+                               n_ss = CPU_Pop32() & 0xffff;
+                       } else {
+                               offset=CPU_Pop16();
+                               selector=CPU_Pop16();
+                               reg_esp+=bytes;
+                               n_esp = CPU_Pop16();
+                               n_ss = CPU_Pop16();
+                       }
+
+                       CPU_CHECK_COND((n_ss & 0xfffc)==0,
+                               "RET to outer level with SS selector zero",
+                               EXCEPTION_GP,0)
+
+                       Descriptor n_ss_desc;
+                       CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss,n_ss_desc),
+                               "RET:SS beyond limits",
+                               EXCEPTION_GP,n_ss & 0xfffc)
+
+                       CPU_CHECK_COND(((n_ss & 3)!=rpl) || (n_ss_desc.DPL()!=rpl),
+                               "RET to outer segment with invalid SS privileges",
+                               EXCEPTION_GP,n_ss & 0xfffc)
+                       switch (n_ss_desc.Type()) {
+                       case DESC_DATA_EU_RW_NA:                case DESC_DATA_EU_RW_A:
+                       case DESC_DATA_ED_RW_NA:                case DESC_DATA_ED_RW_A:
+                               break;
+                       default:
+                               E_Exit("RET:SS selector type no writable data segment");        // or #GP(selector)
+                       }
+                       CPU_CHECK_COND(!n_ss_desc.saved.seg.p,
+                               "RET:Stack segment not present",
+                               EXCEPTION_SS,n_ss & 0xfffc)
+
+                       cpu.cpl = rpl;
+                       Segs.phys[cs]=desc.GetBase();
+                       cpu.code.big=desc.Big()>0;
+                       Segs.val[cs]=(selector&0xfffc) | cpu.cpl;
+                       reg_eip=offset;
+
+                       Segs.val[ss]=n_ss;
+                       Segs.phys[ss]=n_ss_desc.GetBase();
+                       if (n_ss_desc.Big()) {
+                               cpu.stack.big=true;
+                               cpu.stack.mask=0xffffffff;
+                               cpu.stack.notmask=0;
+                               reg_esp=n_esp+bytes;
+                       } else {
+                               cpu.stack.big=false;
+                               cpu.stack.mask=0xffff;
+                               cpu.stack.notmask=0xffff0000;
+                               reg_sp=(n_esp & 0xffff)+bytes;
+                       }
+
+                       CPU_CheckSegments();
+
+//                     LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL());
+                       return;
+               }
+               LOG(LOG_CPU,LOG_NORMAL)("Prot ret %X:%X",selector,offset);
+               return;
+       }
+       assert(1);
+}
+
+
+Bitu CPU_SLDT(void) {
+       return cpu.gdt.SLDT();
+}
+
+bool CPU_LLDT(Bitu selector) {
+       if (!cpu.gdt.LLDT(selector)) {
+               LOG(LOG_CPU,LOG_ERROR)("LLDT failed, selector=%X",selector);
+               return true;
+       }
+       LOG(LOG_CPU,LOG_NORMAL)("LDT Set to %X",selector);
+       return false;
+}
+
+Bitu CPU_STR(void) {
+       return cpu_tss.selector;
+}
+
+bool CPU_LTR(Bitu selector) {
+       if ((selector & 0xfffc)==0) {
+               cpu_tss.SetSelector(selector);
+               return false;
+       }
+       TSS_Descriptor desc;
+       if ((selector & 4) || (!cpu.gdt.GetDescriptor(selector,desc))) {
+               LOG(LOG_CPU,LOG_ERROR)("LTR failed, selector=%X",selector);
+               return CPU_PrepareException(EXCEPTION_GP,selector);
+       }
+
+       if ((desc.Type()==DESC_286_TSS_A) || (desc.Type()==DESC_386_TSS_A)) {
+               if (!desc.saved.seg.p) {
+                       LOG(LOG_CPU,LOG_ERROR)("LTR failed, selector=%X (not present)",selector);
+                       return CPU_PrepareException(EXCEPTION_NP,selector);
+               }
+               if (!cpu_tss.SetSelector(selector)) E_Exit("LTR failed, selector=%X",selector);
+               cpu_tss.desc.SetBusy(true);
+               cpu_tss.SaveSelector();
+       } else {
+               /* Descriptor was no available TSS descriptor */ 
+               LOG(LOG_CPU,LOG_NORMAL)("LTR failed, selector=%X (type=%X)",selector,desc.Type());
+               return CPU_PrepareException(EXCEPTION_GP,selector);
+       }
+       return false;
+}
+
+void CPU_LGDT(Bitu limit,Bitu base) {
+       LOG(LOG_CPU,LOG_NORMAL)("GDT Set to base:%X limit:%X",base,limit);
+       cpu.gdt.SetLimit(limit);
+       cpu.gdt.SetBase(base);
+}
+
+void CPU_LIDT(Bitu limit,Bitu base) {
+       LOG(LOG_CPU,LOG_NORMAL)("IDT Set to base:%X limit:%X",base,limit);
+       cpu.idt.SetLimit(limit);
+       cpu.idt.SetBase(base);
+}
+
+Bitu CPU_SGDT_base(void) {
+       return cpu.gdt.GetBase();
+}
+Bitu CPU_SGDT_limit(void) {
+       return cpu.gdt.GetLimit();
+}
+
+Bitu CPU_SIDT_base(void) {
+       return cpu.idt.GetBase();
+}
+Bitu CPU_SIDT_limit(void) {
+       return cpu.idt.GetLimit();
+}
+
+static bool printed_cycles_auto_info = false;
+void CPU_SET_CRX(Bitu cr,Bitu value) {
+       switch (cr) {
+       case 0:
+               {
+                       value|=CR0_FPUPRESENT;
+                       Bitu changed=cpu.cr0 ^ value;
+                       if (!changed) return;
+                       cpu.cr0=value;
+                       if (value & CR0_PROTECTION) {
+                               cpu.pmode=true;
+                               LOG(LOG_CPU,LOG_NORMAL)("Protected mode");
+                               PAGING_Enable((value & CR0_PAGING)>0);
+
+                               if (!(CPU_AutoDetermineMode&CPU_AUTODETERMINE_MASK)) break;
+
+                               if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CYCLES) {
+                                       CPU_CycleAutoAdjust=true;
+                                       CPU_CycleLeft=0;
+                                       CPU_Cycles=0;
+                                       CPU_OldCycleMax=CPU_CycleMax;
+                                       GFX_SetTitle(CPU_CyclePercUsed,-1,false);
+                                       if(!printed_cycles_auto_info) {
+                                               printed_cycles_auto_info = true;
+                                               LOG_MSG("DOSBox has switched to max cycles, because of the setting: cycles=auto.\nIf the game runs too fast, try a fixed cycles amount in DOSBox's options.");
+                                       }
+                               } else {
+                                       GFX_SetTitle(-1,-1,false);
+                               }
+#if (C_DYNAMIC_X86)
+                               if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CORE) {
+                                       CPU_Core_Dyn_X86_Cache_Init(true);
+                                       cpudecoder=&CPU_Core_Dyn_X86_Run;
+                               }
+#elif (C_DYNREC)
+                               if (CPU_AutoDetermineMode&CPU_AUTODETERMINE_CORE) {
+                                       CPU_Core_Dynrec_Cache_Init(true);
+                                       cpudecoder=&CPU_Core_Dynrec_Run;
+                               }
+#endif
+                               CPU_AutoDetermineMode<<=CPU_AUTODETERMINE_SHIFT;
+                       } else {
+                               cpu.pmode=false;
+                               if (value & CR0_PAGING) LOG_MSG("Paging requested without PE=1");
+                               PAGING_Enable(false);
+                               LOG(LOG_CPU,LOG_NORMAL)("Real mode");
+                       }
+                       break;
+               }
+       case 2:
+               paging.cr2=value;
+               break;
+       case 3:
+               PAGING_SetDirBase(value);
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV CR%d,%X",cr,value);
+               break;
+       }
+}
+
+bool CPU_WRITE_CRX(Bitu cr,Bitu value) {
+       /* Check if privileged to access control registers */
+       if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
+       if ((cr==1) || (cr>4)) return CPU_PrepareException(EXCEPTION_UD,0);
+       if (CPU_ArchitectureType<CPU_ARCHTYPE_486OLDSLOW) {
+               if (cr==4) return CPU_PrepareException(EXCEPTION_UD,0);
+       }
+       CPU_SET_CRX(cr,value);
+       return false;
+}
+
+Bitu CPU_GET_CRX(Bitu cr) {
+       switch (cr) {
+       case 0:
+               if (CPU_ArchitectureType>=CPU_ARCHTYPE_PENTIUMSLOW) return cpu.cr0;
+               else if (CPU_ArchitectureType>=CPU_ARCHTYPE_486OLDSLOW) return (cpu.cr0 & 0xe005003f);
+               else return (cpu.cr0 | 0x7ffffff0);
+       case 2:
+               return paging.cr2;
+       case 3:
+               return PAGING_GetDirBase() & 0xfffff000;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, CR%d",cr);
+               break;
+       }
+       return 0;
+}
+
+bool CPU_READ_CRX(Bitu cr,Bit32u & retvalue) {
+       /* Check if privileged to access control registers */
+       if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
+       if ((cr==1) || (cr>4)) return CPU_PrepareException(EXCEPTION_UD,0);
+       retvalue=CPU_GET_CRX(cr);
+       return false;
+}
+
+
+bool CPU_WRITE_DRX(Bitu dr,Bitu value) {
+       /* Check if privileged to access control registers */
+       if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
+       switch (dr) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+               cpu.drx[dr]=value;
+               break;
+       case 4:
+       case 6:
+               cpu.drx[6]=(value|0xffff0ff0) & 0xffffefff;
+               break;
+       case 5:
+       case 7:
+               if (CPU_ArchitectureType<CPU_ARCHTYPE_PENTIUMSLOW) {
+                       cpu.drx[7]=(value|0x400) & 0xffff2fff;
+               } else {
+                       cpu.drx[7]=(value|0x400);
+               }
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV DR%d,%X",dr,value);
+               break;
+       }
+       return false;
+}
+
+bool CPU_READ_DRX(Bitu dr,Bit32u & retvalue) {
+       /* Check if privileged to access control registers */
+       if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
+       switch (dr) {
+       case 0:
+       case 1:
+       case 2:
+       case 3:
+       case 6:
+       case 7:
+               retvalue=cpu.drx[dr];
+               break;
+       case 4:
+               retvalue=cpu.drx[6];
+               break;
+       case 5:
+               retvalue=cpu.drx[7];
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, DR%d",dr);
+               retvalue=0;
+               break;
+       }
+       return false;
+}
+
+bool CPU_WRITE_TRX(Bitu tr,Bitu value) {
+       /* Check if privileged to access control registers */
+       if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
+       switch (tr) {
+//     case 3:
+       case 6:
+       case 7:
+               cpu.trx[tr]=value;
+               return false;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV TR%d,%X",tr,value);
+               break;
+       }
+       return CPU_PrepareException(EXCEPTION_UD,0);
+}
+
+bool CPU_READ_TRX(Bitu tr,Bit32u & retvalue) {
+       /* Check if privileged to access control registers */
+       if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
+       switch (tr) {
+//     case 3:
+       case 6:
+       case 7:
+               retvalue=cpu.trx[tr];
+               return false;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, TR%d",tr);
+               break;
+       }
+       return CPU_PrepareException(EXCEPTION_UD,0);
+}
+
+
+Bitu CPU_SMSW(void) {
+       return cpu.cr0;
+}
+
+bool CPU_LMSW(Bitu word) {
+       if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0);
+       word&=0xf;
+       if (cpu.cr0 & 1) word|=1; 
+       word|=(cpu.cr0&0xfffffff0);
+       CPU_SET_CRX(0,word);
+       return false;
+}
+
+void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) {
+       FillFlags();
+       if ((dest_sel & 3) < (src_sel & 3)) {
+               dest_sel=(dest_sel & 0xfffc) + (src_sel & 3);
+//             dest_sel|=0xff3f0000;
+               SETFLAGBIT(ZF,true);
+       } else {
+               SETFLAGBIT(ZF,false);
+       } 
+}
+       
+void CPU_LAR(Bitu selector,Bitu & ar) {
+       FillFlags();
+       if (selector == 0) {
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       Descriptor desc;Bitu rpl=selector & 3;
+       if (!cpu.gdt.GetDescriptor(selector,desc)){
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       switch (desc.Type()){
+       case DESC_CODE_N_C_A:   case DESC_CODE_N_C_NA:
+       case DESC_CODE_R_C_A:   case DESC_CODE_R_C_NA:
+               break;
+
+       case DESC_286_INT_GATE:         case DESC_286_TRAP_GATE:        {
+       case DESC_386_INT_GATE:         case DESC_386_TRAP_GATE:
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+
+       case DESC_LDT:
+       case DESC_TASK_GATE:
+
+       case DESC_286_TSS_A:            case DESC_286_TSS_B:
+       case DESC_286_CALL_GATE:
+
+       case DESC_386_TSS_A:            case DESC_386_TSS_B:
+       case DESC_386_CALL_GATE:
+       
+
+       case DESC_DATA_EU_RO_NA:        case DESC_DATA_EU_RO_A:
+       case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+       case DESC_DATA_ED_RO_NA:        case DESC_DATA_ED_RO_A:
+       case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+       case DESC_CODE_N_NC_A:          case DESC_CODE_N_NC_NA:
+       case DESC_CODE_R_NC_A:          case DESC_CODE_R_NC_NA:
+               if (desc.DPL()<cpu.cpl || desc.DPL() < rpl) {
+                       SETFLAGBIT(ZF,false);
+                       return;
+               }
+               break;
+       default:
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       /* Valid descriptor */
+       ar=desc.saved.fill[1] & 0x00ffff00;
+       SETFLAGBIT(ZF,true);
+}
+
+void CPU_LSL(Bitu selector,Bitu & limit) {
+       FillFlags();
+       if (selector == 0) {
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       Descriptor desc;Bitu rpl=selector & 3;
+       if (!cpu.gdt.GetDescriptor(selector,desc)){
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       switch (desc.Type()){
+       case DESC_CODE_N_C_A:   case DESC_CODE_N_C_NA:
+       case DESC_CODE_R_C_A:   case DESC_CODE_R_C_NA:
+               break;
+
+       case DESC_LDT:
+       case DESC_286_TSS_A:
+       case DESC_286_TSS_B:
+       
+       case DESC_386_TSS_A:
+       case DESC_386_TSS_B:
+
+       case DESC_DATA_EU_RO_NA:        case DESC_DATA_EU_RO_A:
+       case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+       case DESC_DATA_ED_RO_NA:        case DESC_DATA_ED_RO_A:
+       case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+       
+       case DESC_CODE_N_NC_A:          case DESC_CODE_N_NC_NA:
+       case DESC_CODE_R_NC_A:          case DESC_CODE_R_NC_NA:
+               if (desc.DPL()<cpu.cpl || desc.DPL() < rpl) {
+                       SETFLAGBIT(ZF,false);
+                       return;
+               }
+               break;
+       default:
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       limit=desc.GetLimit();
+       SETFLAGBIT(ZF,true);
+}
+
+void CPU_VERR(Bitu selector) {
+       FillFlags();
+       if (selector == 0) {
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       Descriptor desc;Bitu rpl=selector & 3;
+       if (!cpu.gdt.GetDescriptor(selector,desc)){
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       switch (desc.Type()){
+       case DESC_CODE_R_C_A:           case DESC_CODE_R_C_NA:  
+               //Conforming readable code segments can be always read 
+               break;
+       case DESC_DATA_EU_RO_NA:        case DESC_DATA_EU_RO_A:
+       case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+       case DESC_DATA_ED_RO_NA:        case DESC_DATA_ED_RO_A:
+       case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+
+       case DESC_CODE_R_NC_A:          case DESC_CODE_R_NC_NA:
+               if (desc.DPL()<cpu.cpl || desc.DPL() < rpl) {
+                       SETFLAGBIT(ZF,false);
+                       return;
+               }
+               break;
+       default:
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       SETFLAGBIT(ZF,true);
+}
+
+void CPU_VERW(Bitu selector) {
+       FillFlags();
+       if (selector == 0) {
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       Descriptor desc;Bitu rpl=selector & 3;
+       if (!cpu.gdt.GetDescriptor(selector,desc)){
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       switch (desc.Type()){
+       case DESC_DATA_EU_RW_NA:        case DESC_DATA_EU_RW_A:
+       case DESC_DATA_ED_RW_NA:        case DESC_DATA_ED_RW_A:
+               if (desc.DPL()<cpu.cpl || desc.DPL() < rpl) {
+                       SETFLAGBIT(ZF,false);
+                       return;
+               }
+               break;
+       default:
+               SETFLAGBIT(ZF,false);
+               return;
+       }
+       SETFLAGBIT(ZF,true);
+}
+
+bool CPU_SetSegGeneral(SegNames seg,Bitu value) {
+       value &= 0xffff;
+       if (!cpu.pmode || (reg_flags & FLAG_VM)) {
+               Segs.val[seg]=value;
+               Segs.phys[seg]=value << 4;
+               if (seg==ss) {
+                       cpu.stack.big=false;
+                       cpu.stack.mask=0xffff;
+                       cpu.stack.notmask=0xffff0000;
+               }
+               return false;
+       } else {
+               if (seg==ss) {
+                       // Stack needs to be non-zero
+                       if ((value & 0xfffc)==0) {
+                               E_Exit("CPU_SetSegGeneral: Stack segment zero");
+//                             return CPU_PrepareException(EXCEPTION_GP,0);
+                       }
+                       Descriptor desc;
+                       if (!cpu.gdt.GetDescriptor(value,desc)) {
+                               E_Exit("CPU_SetSegGeneral: Stack segment beyond limits");
+//                             return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc);
+                       }
+                       if (((value & 3)!=cpu.cpl) || (desc.DPL()!=cpu.cpl)) {
+                               E_Exit("CPU_SetSegGeneral: Stack segment with invalid privileges");
+//                             return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc);
+                       }
+
+                       switch (desc.Type()) {
+                       case DESC_DATA_EU_RW_NA:                case DESC_DATA_EU_RW_A:
+                       case DESC_DATA_ED_RW_NA:                case DESC_DATA_ED_RW_A:
+                               break;
+                       default:
+                               //Earth Siege 1
+                               return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc);
+                       }
+
+                       if (!desc.saved.seg.p) {
+//                             E_Exit("CPU_SetSegGeneral: Stack segment not present"); // or #SS(sel)
+                               return CPU_PrepareException(EXCEPTION_SS,value & 0xfffc);
+                       }
+
+                       Segs.val[seg]=value;
+                       Segs.phys[seg]=desc.GetBase();
+                       if (desc.Big()) {
+                               cpu.stack.big=true;
+                               cpu.stack.mask=0xffffffff;
+                               cpu.stack.notmask=0;
+                       } else {
+                               cpu.stack.big=false;
+                               cpu.stack.mask=0xffff;
+                               cpu.stack.notmask=0xffff0000;
+                       }
+               } else {
+                       if ((value & 0xfffc)==0) {
+                               Segs.val[seg]=value;
+                               Segs.phys[seg]=0;       // ??
+                               return false;
+                       }
+                       Descriptor desc;
+                       if (!cpu.gdt.GetDescriptor(value,desc)) {
+                               return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc);
+                       }
+                       switch (desc.Type()) {
+                       case DESC_DATA_EU_RO_NA:                case DESC_DATA_EU_RO_A:
+                       case DESC_DATA_EU_RW_NA:                case DESC_DATA_EU_RW_A:
+                       case DESC_DATA_ED_RO_NA:                case DESC_DATA_ED_RO_A:
+                       case DESC_DATA_ED_RW_NA:                case DESC_DATA_ED_RW_A:
+                       case DESC_CODE_R_NC_A:                  case DESC_CODE_R_NC_NA:
+                               if (((value & 3)>desc.DPL()) || (cpu.cpl>desc.DPL())) {
+                                       // extreme pinball
+                                       return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc);
+                               }
+                               break;
+                       case DESC_CODE_R_C_A:                   case DESC_CODE_R_C_NA:
+                               break;
+                       default:
+                               // gabriel knight
+                               return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc);
+
+                       }
+                       if (!desc.saved.seg.p) {
+                               // win
+                               return CPU_PrepareException(EXCEPTION_NP,value & 0xfffc);
+                       }
+
+                       Segs.val[seg]=value;
+                       Segs.phys[seg]=desc.GetBase();
+               }
+
+               return false;
+       }
+}
+
+bool CPU_PopSeg(SegNames seg,bool use32) {
+       Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask));
+       if (CPU_SetSegGeneral(seg,val)) return true;
+       Bitu addsp=use32?0x04:0x02;
+       reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+addsp)&cpu.stack.mask);
+       return false;
+}
+
+bool CPU_CPUID(void) {
+       if (CPU_ArchitectureType<CPU_ARCHTYPE_486NEWSLOW) return false;
+       switch (reg_eax) {
+       case 0: /* Vendor ID String and maximum level? */
+               reg_eax=1;  /* Maximum level */ 
+               reg_ebx='G' | ('e' << 8) | ('n' << 16) | ('u'<< 24); 
+               reg_edx='i' | ('n' << 8) | ('e' << 16) | ('I'<< 24); 
+               reg_ecx='n' | ('t' << 8) | ('e' << 16) | ('l'<< 24); 
+               break;
+       case 1: /* get processor type/family/model/stepping and feature flags */
+               if ((CPU_ArchitectureType==CPU_ARCHTYPE_486NEWSLOW) ||
+                       (CPU_ArchitectureType==CPU_ARCHTYPE_MIXED)) {
+                       reg_eax=0x402;          /* intel 486dx */
+                       reg_ebx=0;                      /* Not Supported */
+                       reg_ecx=0;                      /* No features */
+                       reg_edx=0x00000001;     /* FPU */
+               } else if (CPU_ArchitectureType==CPU_ARCHTYPE_PENTIUMSLOW) {
+                       reg_eax=0x513;          /* intel pentium */
+                       reg_ebx=0;                      /* Not Supported */
+                       reg_ecx=0;                      /* No features */
+                       reg_edx=0x00000011;     /* FPU+TimeStamp/RDTSC */
+               } else {
+                       return false;
+               }
+               break;
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled CPUID Function %x",reg_eax);
+               reg_eax=0;
+               reg_ebx=0;
+               reg_ecx=0;
+               reg_edx=0;
+               break;
+       }
+       return true;
+}
+
+static Bits HLT_Decode(void) {
+       /* Once an interrupt occurs, it should change cpu core */
+       if (reg_eip!=cpu.hlt.eip || SegValue(cs) != cpu.hlt.cs) {
+               cpudecoder=cpu.hlt.old_decoder;
+       } else {
+               CPU_IODelayRemoved += CPU_Cycles;
+               CPU_Cycles=0;
+       }
+       return 0;
+}
+
+void CPU_HLT(Bitu oldeip) {
+       reg_eip=oldeip;
+       CPU_IODelayRemoved += CPU_Cycles;
+       CPU_Cycles=0;
+       cpu.hlt.cs=SegValue(cs);
+       cpu.hlt.eip=reg_eip;
+       cpu.hlt.old_decoder=cpudecoder;
+       cpudecoder=&HLT_Decode;
+}
+
+void CPU_ENTER(bool use32,Bitu bytes,Bitu level) {
+       level&=0x1f;
+       Bitu sp_index=reg_esp&cpu.stack.mask;
+       Bitu bp_index=reg_ebp&cpu.stack.mask;
+       if (!use32) {
+               sp_index-=2;
+               mem_writew(SegPhys(ss)+sp_index,reg_bp);
+               reg_bp=(Bit16u)(reg_esp-2);
+               if (level) {
+                       for (Bitu i=1;i<level;i++) {    
+                               sp_index-=2;bp_index-=2;
+                               mem_writew(SegPhys(ss)+sp_index,mem_readw(SegPhys(ss)+bp_index));
+                       }
+                       sp_index-=2;
+                       mem_writew(SegPhys(ss)+sp_index,reg_bp);
+               }
+       } else {
+               sp_index-=4;
+        mem_writed(SegPhys(ss)+sp_index,reg_ebp);
+               reg_ebp=(reg_esp-4);
+               if (level) {
+                       for (Bitu i=1;i<level;i++) {    
+                               sp_index-=4;bp_index-=4;
+                               mem_writed(SegPhys(ss)+sp_index,mem_readd(SegPhys(ss)+bp_index));
+                       }
+                       sp_index-=4;
+                       mem_writed(SegPhys(ss)+sp_index,reg_ebp);
+               }
+       }
+       sp_index-=bytes;
+       reg_esp=(reg_esp&cpu.stack.notmask)|((sp_index)&cpu.stack.mask);
+}
+
+static void CPU_CycleIncrease(bool pressed) {
+       if (!pressed) return;
+       if (CPU_CycleAutoAdjust) {
+               CPU_CyclePercUsed+=5;
+               if (CPU_CyclePercUsed>105) CPU_CyclePercUsed=105;
+               LOG_MSG("CPU speed: max %d percent.",CPU_CyclePercUsed);
+               GFX_SetTitle(CPU_CyclePercUsed,-1,false);
+       } else {
+               Bit32s old_cycles=CPU_CycleMax;
+               if (CPU_CycleUp < 100) {
+                       CPU_CycleMax = (Bit32s)(CPU_CycleMax * (1 + (float)CPU_CycleUp / 100.0));
+               } else {
+                       CPU_CycleMax = (Bit32s)(CPU_CycleMax + CPU_CycleUp);
+               }
+           
+               CPU_CycleLeft=0;CPU_Cycles=0;
+               if (CPU_CycleMax==old_cycles) CPU_CycleMax++;
+               if(CPU_CycleMax > 15000 ) 
+                       LOG_MSG("CPU speed: fixed %d cycles. If you need more than 20000, try core=dynamic in DOSBox's options.",CPU_CycleMax);
+               else
+                       LOG_MSG("CPU speed: fixed %d cycles.",CPU_CycleMax);
+               GFX_SetTitle(CPU_CycleMax,-1,false);
+       }
+}
+
+static void CPU_CycleDecrease(bool pressed) {
+       if (!pressed) return;
+       if (CPU_CycleAutoAdjust) {
+               CPU_CyclePercUsed-=5;
+               if (CPU_CyclePercUsed<=0) CPU_CyclePercUsed=1;
+               if(CPU_CyclePercUsed <=70)
+                       LOG_MSG("CPU speed: max %d percent. If the game runs too fast, try a fixed cycles amount in DOSBox's options.",CPU_CyclePercUsed);
+               else
+                       LOG_MSG("CPU speed: max %d percent.",CPU_CyclePercUsed);
+               GFX_SetTitle(CPU_CyclePercUsed,-1,false);
+       } else {
+               if (CPU_CycleDown < 100) {
+                       CPU_CycleMax = (Bit32s)(CPU_CycleMax / (1 + (float)CPU_CycleDown / 100.0));
+               } else {
+                       CPU_CycleMax = (Bit32s)(CPU_CycleMax - CPU_CycleDown);
+               }
+               CPU_CycleLeft=0;CPU_Cycles=0;
+               if (CPU_CycleMax <= 0) CPU_CycleMax=1;
+               LOG_MSG("CPU speed: fixed %d cycles.",CPU_CycleMax);
+               GFX_SetTitle(CPU_CycleMax,-1,false);
+       }
+}
+
+void CPU_Enable_SkipAutoAdjust(void) {
+       if (CPU_CycleAutoAdjust) {
+               CPU_CycleMax /= 2;
+               if (CPU_CycleMax < CPU_CYCLES_LOWER_LIMIT)
+                       CPU_CycleMax = CPU_CYCLES_LOWER_LIMIT;
+       }
+       CPU_SkipCycleAutoAdjust=true;
+}
+
+void CPU_Disable_SkipAutoAdjust(void) {
+       CPU_SkipCycleAutoAdjust=false;
+}
+
+
+extern Bit32s ticksDone;
+extern Bit32u ticksScheduled;
+
+void CPU_Reset_AutoAdjust(void) {
+       CPU_IODelayRemoved = 0;
+       ticksDone = 0;
+       ticksScheduled = 0;
+}
+
+class CPU: public Module_base {
+private:
+       static bool inited;
+public:
+       CPU(Section* configuration):Module_base(configuration) {
+               if(inited) {
+                       Change_Config(configuration);
+                       return;
+               }
+//             Section_prop * section=static_cast<Section_prop *>(configuration);
+               inited=true;
+               reg_eax=0;
+               reg_ebx=0;
+               reg_ecx=0;
+               reg_edx=0;
+               reg_edi=0;
+               reg_esi=0;
+               reg_ebp=0;
+               reg_esp=0;
+       
+               SegSet16(cs,0);
+               SegSet16(ds,0);
+               SegSet16(es,0);
+               SegSet16(fs,0);
+               SegSet16(gs,0);
+               SegSet16(ss,0);
+       
+               CPU_SetFlags(FLAG_IF,FMASK_ALL);                //Enable interrupts
+               cpu.cr0=0xffffffff;
+               CPU_SET_CRX(0,0);                                               //Initialize
+               cpu.code.big=false;
+               cpu.stack.mask=0xffff;
+               cpu.stack.notmask=0xffff0000;
+               cpu.stack.big=false;
+               cpu.trap_skip=false;
+               cpu.idt.SetBase(0);
+               cpu.idt.SetLimit(1023);
+
+               for (Bitu i=0; i<7; i++) {
+                       cpu.drx[i]=0;
+                       cpu.trx[i]=0;
+               }
+               if (CPU_ArchitectureType==CPU_ARCHTYPE_PENTIUMSLOW) {
+                       cpu.drx[6]=0xffff0ff0;
+               } else {
+                       cpu.drx[6]=0xffff1ff0;
+               }
+               cpu.drx[7]=0x00000400;
+
+               /* Init the cpu cores */
+               CPU_Core_Normal_Init();
+               CPU_Core_Simple_Init();
+               CPU_Core_Full_Init();
+#if (C_DYNAMIC_X86)
+               CPU_Core_Dyn_X86_Init();
+#elif (C_DYNREC)
+               CPU_Core_Dynrec_Init();
+#endif
+               MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles");
+               MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup"  ,"Inc Cycles");
+               Change_Config(configuration);   
+               CPU_JMP(false,0,0,0);                                   //Setup the first cpu core
+       }
+       bool Change_Config(Section* newconfig){
+               Section_prop * section=static_cast<Section_prop *>(newconfig);
+               CPU_AutoDetermineMode=CPU_AUTODETERMINE_NONE;
+               //CPU_CycleLeft=0;//needed ?
+               CPU_Cycles=0;
+               CPU_SkipCycleAutoAdjust=false;
+
+               Prop_multival* p = section->Get_multival("cycles");
+               std::string type = p->GetSection()->Get_string("type");
+               std::string str ;
+               CommandLine cmd(0,p->GetSection()->Get_string("parameters"));
+               if (type=="max") {
+                       CPU_CycleMax=0;
+                       CPU_CyclePercUsed=100;
+                       CPU_CycleAutoAdjust=true;
+                       CPU_CycleLimit=-1;
+                       for (Bitu cmdnum=1; cmdnum<=cmd.GetCount(); cmdnum++) {
+                               if (cmd.FindCommand(cmdnum,str)) {
+                                       if (str.find('%')==str.length()-1) {
+                                               str.erase(str.find('%'));
+                                               int percval=0;
+                                               std::istringstream stream(str);
+                                               stream >> percval;
+                                               if ((percval>0) && (percval<=105)) CPU_CyclePercUsed=(Bit32s)percval;
+                                       } else if (str=="limit") {
+                                               cmdnum++;
+                                               if (cmd.FindCommand(cmdnum,str)) {
+                                                       int cyclimit=0;
+                                                       std::istringstream stream(str);
+                                                       stream >> cyclimit;
+                                                       if (cyclimit>0) CPU_CycleLimit=cyclimit;
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       if (type=="auto") {
+                               CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CYCLES;
+                               CPU_CycleMax=3000;
+                               CPU_OldCycleMax=3000;
+                               CPU_CyclePercUsed=100;
+                               for (Bitu cmdnum=0; cmdnum<=cmd.GetCount(); cmdnum++) {
+                                       if (cmd.FindCommand(cmdnum,str)) {
+                                               if (str.find('%')==str.length()-1) {
+                                                       str.erase(str.find('%'));
+                                                       int percval=0;
+                                                       std::istringstream stream(str);
+                                                       stream >> percval;
+                                                       if ((percval>0) && (percval<=105)) CPU_CyclePercUsed=(Bit32s)percval;
+                                               } else if (str=="limit") {
+                                                       cmdnum++;
+                                                       if (cmd.FindCommand(cmdnum,str)) {
+                                                               int cyclimit=0;
+                                                               std::istringstream stream(str);
+                                                               stream >> cyclimit;
+                                                               if (cyclimit>0) CPU_CycleLimit=cyclimit;
+                                                       }
+                                               } else {
+                                                       int rmdval=0;
+                                                       std::istringstream stream(str);
+                                                       stream >> rmdval;
+                                                       if (rmdval>0) {
+                                                               CPU_CycleMax=(Bit32s)rmdval;
+                                                               CPU_OldCycleMax=(Bit32s)rmdval;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else if(type =="fixed") {
+                               cmd.FindCommand(1,str);
+                               int rmdval=0;
+                               std::istringstream stream(str);
+                               stream >> rmdval;
+                               CPU_CycleMax=(Bit32s)rmdval;
+                       } else {
+                               std::istringstream stream(type);
+                               int rmdval=0;
+                               stream >> rmdval;
+                               if(rmdval) CPU_CycleMax=(Bit32s)rmdval;
+                       }
+                       CPU_CycleAutoAdjust=false;
+               }
+
+               CPU_CycleUp=section->Get_int("cycleup");
+               CPU_CycleDown=section->Get_int("cycledown");
+               std::string core(section->Get_string("core"));
+               cpudecoder=&CPU_Core_Normal_Run;
+               if (core == "normal") {
+                       cpudecoder=&CPU_Core_Normal_Run;
+               } else if (core =="simple") {
+                       cpudecoder=&CPU_Core_Simple_Run;
+               } else if (core == "full") {
+                       cpudecoder=&CPU_Core_Full_Run;
+               } else if (core == "auto") {
+                       cpudecoder=&CPU_Core_Normal_Run;
+#if (C_DYNAMIC_X86)
+                       CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE;
+               }
+               else if (core == "dynamic") {
+                       cpudecoder=&CPU_Core_Dyn_X86_Run;
+                       CPU_Core_Dyn_X86_SetFPUMode(true);
+               } else if (core == "dynamic_nodhfpu") {
+                       cpudecoder=&CPU_Core_Dyn_X86_Run;
+                       CPU_Core_Dyn_X86_SetFPUMode(false);
+#elif (C_DYNREC)
+                       CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE;
+               }
+               else if (core == "dynamic") {
+                       cpudecoder=&CPU_Core_Dynrec_Run;
+#else
+
+#endif
+               }
+
+#if (C_DYNAMIC_X86)
+               CPU_Core_Dyn_X86_Cache_Init((core == "dynamic") || (core == "dynamic_nodhfpu"));
+#elif (C_DYNREC)
+               CPU_Core_Dynrec_Cache_Init( core == "dynamic" );
+#endif
+
+               CPU_ArchitectureType = CPU_ARCHTYPE_MIXED;
+               std::string cputype(section->Get_string("cputype"));
+               if (cputype == "auto") {
+                       CPU_ArchitectureType = CPU_ARCHTYPE_MIXED;
+               } else if (cputype == "386") {
+                       CPU_ArchitectureType = CPU_ARCHTYPE_386FAST;
+               } else if (cputype == "386_prefetch") {
+                       CPU_ArchitectureType = CPU_ARCHTYPE_386FAST;
+                       if (core == "normal") {
+                               cpudecoder=&CPU_Core_Prefetch_Run;
+                               CPU_PrefetchQueueSize = 16;
+                       } else if (core == "auto") {
+                               cpudecoder=&CPU_Core_Prefetch_Run;
+                               CPU_PrefetchQueueSize = 16;
+                               CPU_AutoDetermineMode&=(~CPU_AUTODETERMINE_CORE);
+                       } else {
+                               E_Exit("prefetch queue emulation requires the normal core setting.");
+                       }
+               } else if (cputype == "386_slow") {
+                       CPU_ArchitectureType = CPU_ARCHTYPE_386SLOW;
+               } else if (cputype == "486_slow") {
+                       CPU_ArchitectureType = CPU_ARCHTYPE_486NEWSLOW;
+               } else if (cputype == "486_prefetch") {
+                       CPU_ArchitectureType = CPU_ARCHTYPE_486NEWSLOW;
+                       if (core == "normal") {
+                               cpudecoder=&CPU_Core_Prefetch_Run;
+                               CPU_PrefetchQueueSize = 32;
+                       } else if (core == "auto") {
+                               cpudecoder=&CPU_Core_Prefetch_Run;
+                               CPU_PrefetchQueueSize = 32;
+                               CPU_AutoDetermineMode&=(~CPU_AUTODETERMINE_CORE);
+                       } else {
+                               E_Exit("prefetch queue emulation requires the normal core setting.");
+                       }
+               } else if (cputype == "pentium_slow") {
+                       CPU_ArchitectureType = CPU_ARCHTYPE_PENTIUMSLOW;
+               }
+
+               if (CPU_ArchitectureType>=CPU_ARCHTYPE_486NEWSLOW) CPU_extflags_toggle=(FLAG_ID|FLAG_AC);
+               else if (CPU_ArchitectureType>=CPU_ARCHTYPE_486OLDSLOW) CPU_extflags_toggle=(FLAG_AC);
+               else CPU_extflags_toggle=0;
+
+
+               if(CPU_CycleMax <= 0) CPU_CycleMax = 3000;
+               if(CPU_CycleUp <= 0)   CPU_CycleUp = 500;
+               if(CPU_CycleDown <= 0) CPU_CycleDown = 20;
+               if (CPU_CycleAutoAdjust) GFX_SetTitle(CPU_CyclePercUsed,-1,false);
+               else GFX_SetTitle(CPU_CycleMax,-1,false);
+               return true;
+       }
+       ~CPU(){ /* empty */};
+};
+       
+static CPU * test;
+
+void CPU_ShutDown(Section* sec) {
+#if (C_DYNAMIC_X86)
+       CPU_Core_Dyn_X86_Cache_Close();
+#elif (C_DYNREC)
+       CPU_Core_Dynrec_Cache_Close();
+#endif
+       delete test;
+}
+
+void CPU_Init(Section* sec) {
+       test = new CPU(sec);
+       sec->AddDestroyFunction(&CPU_ShutDown,true);
+}
+//initialize static members
+bool CPU::inited=false;
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/flags.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/flags.cpp
new file mode 100644 (file)
index 0000000..1559af1
--- /dev/null
@@ -0,0 +1,1188 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+       Lazy flag system was designed after the same kind of system used in Bochs.
+       Probably still some bugs left in here.
+*/
+
+#include "dosbox.h"
+#include "cpu.h"
+#include "lazyflags.h"
+#include "pic.h"
+
+LazyFlags lflags;
+
+/* CF     Carry Flag -- Set on high-order bit carry or borrow; cleared
+          otherwise.
+*/
+Bit32u get_CF(void) {
+
+       switch (lflags.type) {
+       case t_UNKNOWN:
+       case t_INCb:
+       case t_INCw:
+       case t_INCd:
+       case t_DECb:
+       case t_DECw:
+       case t_DECd:
+       case t_MUL:
+               return GETFLAG(CF);
+       case t_ADDb:    
+               return (lf_resb<lf_var1b);
+       case t_ADDw:    
+               return (lf_resw<lf_var1w);
+       case t_ADDd:
+               return (lf_resd<lf_var1d);
+       case t_ADCb:
+               return (lf_resb < lf_var1b) || (lflags.oldcf && (lf_resb == lf_var1b));
+       case t_ADCw:
+               return (lf_resw < lf_var1w) || (lflags.oldcf && (lf_resw == lf_var1w));
+       case t_ADCd:
+               return (lf_resd < lf_var1d) || (lflags.oldcf && (lf_resd == lf_var1d));
+       case t_SBBb:
+               return (lf_var1b < lf_resb) || (lflags.oldcf && (lf_var2b==0xff));
+       case t_SBBw:
+               return (lf_var1w < lf_resw) || (lflags.oldcf && (lf_var2w==0xffff));
+       case t_SBBd:
+               return (lf_var1d < lf_resd) || (lflags.oldcf && (lf_var2d==0xffffffff));
+       case t_SUBb:
+       case t_CMPb:
+               return (lf_var1b<lf_var2b);
+       case t_SUBw:
+       case t_CMPw:
+               return (lf_var1w<lf_var2w);
+       case t_SUBd:
+       case t_CMPd:
+               return (lf_var1d<lf_var2d);
+       case t_SHLb:
+               if (lf_var2b>8) return false;
+               else return (lf_var1b >> (8-lf_var2b)) & 1;
+       case t_SHLw:
+               if (lf_var2b>16) return false;
+               else return (lf_var1w >> (16-lf_var2b)) & 1;
+       case t_SHLd:
+       case t_DSHLw:   /* Hmm this is not correct for shift higher than 16 */
+       case t_DSHLd:
+               return (lf_var1d >> (32 - lf_var2b)) & 1;
+       case t_RCRb:
+       case t_SHRb:
+               return (lf_var1b >> (lf_var2b - 1)) & 1;
+       case t_RCRw:
+       case t_SHRw:
+               return (lf_var1w >> (lf_var2b - 1)) & 1;
+       case t_RCRd:
+       case t_SHRd:
+       case t_DSHRw:   /* Hmm this is not correct for shift higher than 16 */
+       case t_DSHRd:
+               return (lf_var1d >> (lf_var2b - 1)) & 1;
+       case t_SARb:
+               return (((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1;
+       case t_SARw:
+               return (((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1;
+       case t_SARd:
+               return (((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1;
+       case t_NEGb:
+               return lf_var1b;
+       case t_NEGw:
+               return lf_var1w;
+       case t_NEGd:
+               return lf_var1d;
+       case t_ORb:
+       case t_ORw:
+       case t_ORd:
+       case t_ANDb:
+       case t_ANDw:
+       case t_ANDd:
+       case t_XORb:
+       case t_XORw:
+       case t_XORd:
+       case t_TESTb:
+       case t_TESTw:
+       case t_TESTd:
+               return false;   /* Set to false */
+       case t_DIV:
+               return false;   /* Unkown */
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("get_CF Unknown %d",lflags.type);
+       }
+       return 0;
+}
+
+/* AF     Adjust flag -- Set on carry from or borrow to the low order
+            four bits of   AL; cleared otherwise. Used for decimal
+            arithmetic.
+*/
+Bit32u get_AF(void) {
+       Bitu type=lflags.type;
+       switch (type) {
+       case t_UNKNOWN:
+               return GETFLAG(AF);
+       case t_ADDb:    
+       case t_ADCb:
+       case t_SBBb:
+       case t_SUBb:
+       case t_CMPb:
+               return ((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10;
+       case t_ADDw:
+       case t_ADCw:
+       case t_SBBw:
+       case t_SUBw:
+       case t_CMPw:
+               return ((lf_var1w ^ lf_var2w) ^ lf_resw) & 0x10;
+       case t_ADCd:
+       case t_ADDd:
+       case t_SBBd:
+       case t_SUBd:
+       case t_CMPd:
+               return ((lf_var1d ^ lf_var2d) ^ lf_resd) & 0x10;
+       case t_INCb:
+               return (lf_resb & 0x0f) == 0;
+       case t_INCw:
+               return (lf_resw & 0x0f) == 0;
+       case t_INCd:
+               return (lf_resd & 0x0f) == 0;
+       case t_DECb:
+               return (lf_resb & 0x0f) == 0x0f;
+       case t_DECw:
+               return (lf_resw & 0x0f) == 0x0f;
+       case t_DECd:
+               return (lf_resd & 0x0f) == 0x0f;
+       case t_NEGb:
+               return lf_var1b & 0x0f;
+       case t_NEGw:
+               return lf_var1w & 0x0f;
+       case t_NEGd:
+               return lf_var1d & 0x0f;
+       case t_SHLb:
+       case t_SHRb:
+       case t_SARb:
+               return lf_var2b & 0x1f;
+       case t_SHLw:
+       case t_SHRw:
+       case t_SARw:
+               return lf_var2w & 0x1f;
+       case t_SHLd:
+       case t_SHRd:
+       case t_SARd:
+               return lf_var2d & 0x1f;
+       case t_ORb:
+       case t_ORw:
+       case t_ORd:
+       case t_ANDb:
+       case t_ANDw:
+       case t_ANDd:
+       case t_XORb:
+       case t_XORw:
+       case t_XORd:
+       case t_TESTb:
+       case t_TESTw:
+       case t_TESTd:
+       case t_DSHLw:
+       case t_DSHLd:
+       case t_DSHRw:
+       case t_DSHRd:
+       case t_DIV:
+       case t_MUL:
+               return false;                             /* Unkown */
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("get_AF Unknown %d",lflags.type);
+       }
+       return 0;
+}
+
+/* ZF     Zero Flag -- Set if result is zero; cleared otherwise.
+*/
+
+Bit32u get_ZF(void) {
+       Bitu type=lflags.type;
+       switch (type) {
+       case t_UNKNOWN:
+               return GETFLAG(ZF);
+       case t_ADDb:    
+       case t_ORb:
+       case t_ADCb:
+       case t_SBBb:
+       case t_ANDb:
+       case t_XORb:
+       case t_SUBb:
+       case t_CMPb:
+       case t_INCb:
+       case t_DECb:
+       case t_TESTb:
+       case t_SHLb:
+       case t_SHRb:
+       case t_SARb:
+       case t_NEGb:
+               return (lf_resb==0);
+       case t_ADDw:    
+       case t_ORw:
+       case t_ADCw:
+       case t_SBBw:
+       case t_ANDw:
+       case t_XORw:
+       case t_SUBw:
+       case t_CMPw:
+       case t_INCw:
+       case t_DECw:
+       case t_TESTw:
+       case t_SHLw:
+       case t_SHRw:
+       case t_SARw:
+       case t_DSHLw:
+       case t_DSHRw:
+       case t_NEGw:
+               return (lf_resw==0);
+       case t_ADDd:
+       case t_ORd:
+       case t_ADCd:
+       case t_SBBd:
+       case t_ANDd:
+       case t_XORd:
+       case t_SUBd:
+       case t_CMPd:
+       case t_INCd:
+       case t_DECd:
+       case t_TESTd:
+       case t_SHLd:
+       case t_SHRd:
+       case t_SARd:
+       case t_DSHLd:
+       case t_DSHRd:
+       case t_NEGd:
+               return (lf_resd==0);
+       case t_DIV:
+       case t_MUL:
+               return false;           /* Unkown */
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("get_ZF Unknown %d",lflags.type);
+       }
+       return false;
+}
+/* SF     Sign Flag -- Set equal to high-order bit of result (0 is
+            positive, 1 if negative).
+*/
+Bit32u get_SF(void) {
+       Bitu type=lflags.type;
+       switch (type) {
+       case t_UNKNOWN:
+               return GETFLAG(SF);
+       case t_ADDb:
+       case t_ORb:
+       case t_ADCb:
+       case t_SBBb:
+       case t_ANDb:
+       case t_XORb:
+       case t_SUBb:
+       case t_CMPb:
+       case t_INCb:
+       case t_DECb:
+       case t_TESTb:
+       case t_SHLb:
+       case t_SHRb:
+       case t_SARb:
+       case t_NEGb:
+               return  (lf_resb&0x80);
+       case t_ADDw:
+       case t_ORw:
+       case t_ADCw:
+       case t_SBBw:
+       case t_ANDw:
+       case t_XORw:
+       case t_SUBw:
+       case t_CMPw:
+       case t_INCw:
+       case t_DECw:
+       case t_TESTw:
+       case t_SHLw:
+       case t_SHRw:
+       case t_SARw:
+       case t_DSHLw:
+       case t_DSHRw:
+       case t_NEGw:
+               return  (lf_resw&0x8000);
+       case t_ADDd:
+       case t_ORd:
+       case t_ADCd:
+       case t_SBBd:
+       case t_ANDd:
+       case t_XORd:
+       case t_SUBd:
+       case t_CMPd:
+       case t_INCd:
+       case t_DECd:
+       case t_TESTd:
+       case t_SHLd:
+       case t_SHRd:
+       case t_SARd:
+       case t_DSHLd:
+       case t_DSHRd:
+       case t_NEGd:
+               return  (lf_resd&0x80000000);
+       case t_DIV:
+       case t_MUL:
+               return false;   /* Unkown */
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("get_SF Unkown %d",lflags.type);
+       }
+       return false;
+
+}
+Bit32u get_OF(void) {
+       Bitu type=lflags.type;
+       switch (type) {
+       case t_UNKNOWN:
+       case t_MUL:
+               return GETFLAG(OF);
+       case t_ADDb:
+       case t_ADCb:
+               return ((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var2b)) & 0x80;
+       case t_ADDw:
+       case t_ADCw:
+               return ((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var2w)) & 0x8000;
+       case t_ADDd:
+       case t_ADCd:
+               return ((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var2d)) & 0x80000000;
+       case t_SBBb:
+       case t_SUBb:
+       case t_CMPb:
+               return ((lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb)) & 0x80;
+       case t_SBBw:
+       case t_SUBw:
+       case t_CMPw:
+               return ((lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw)) & 0x8000;
+       case t_SBBd:
+       case t_SUBd:
+       case t_CMPd:
+               return ((lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd)) & 0x80000000;
+       case t_INCb:
+               return (lf_resb == 0x80);
+       case t_INCw:
+               return (lf_resw == 0x8000);
+       case t_INCd:
+               return (lf_resd == 0x80000000);
+       case t_DECb:
+               return (lf_resb == 0x7f);
+       case t_DECw:
+               return (lf_resw == 0x7fff);
+       case t_DECd:
+               return (lf_resd == 0x7fffffff);
+       case t_NEGb:
+               return (lf_var1b == 0x80);
+       case t_NEGw:
+               return (lf_var1w == 0x8000);
+       case t_NEGd:
+               return (lf_var1d == 0x80000000);
+       case t_SHLb:
+               return (lf_resb ^ lf_var1b) & 0x80;
+       case t_SHLw:
+       case t_DSHRw:
+       case t_DSHLw:
+               return (lf_resw ^ lf_var1w) & 0x8000;
+       case t_SHLd:
+       case t_DSHRd:
+       case t_DSHLd:
+               return (lf_resd ^ lf_var1d) & 0x80000000;
+       case t_SHRb:
+               if ((lf_var2b&0x1f)==1) return (lf_var1b > 0x80);
+               else return false;
+       case t_SHRw:
+               if ((lf_var2b&0x1f)==1) return (lf_var1w > 0x8000);
+               else return false;
+       case t_SHRd:
+               if ((lf_var2b&0x1f)==1) return (lf_var1d > 0x80000000);
+               else return false;
+       case t_ORb:
+       case t_ORw:
+       case t_ORd:
+       case t_ANDb:
+       case t_ANDw:
+       case t_ANDd:
+       case t_XORb:
+       case t_XORw:
+       case t_XORd:
+       case t_TESTb:
+       case t_TESTw:
+       case t_TESTd:
+       case t_SARb:
+       case t_SARw:
+       case t_SARd:
+               return false;                   /* Return false */
+       case t_DIV:
+               return false;           /* Unkown */
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("get_OF Unkown %d",lflags.type);
+       }
+       return false;
+}
+
+Bit16u parity_lookup[256] = {
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0,
+  FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF
+  };
+
+Bit32u get_PF(void) {
+       switch (lflags.type) {
+       case t_UNKNOWN:
+               return GETFLAG(PF);
+       default:
+               return  (parity_lookup[lf_resb]);
+       };
+       return 0;
+}
+
+
+#if 0
+
+Bitu FillFlags(void) {
+//     if (lflags.type==t_UNKNOWN) return reg_flags;
+       Bitu new_word=(reg_flags & ~FLAG_MASK);
+       if (get_CF()) new_word|=FLAG_CF;
+       if (get_PF()) new_word|=FLAG_PF;
+       if (get_AF()) new_word|=FLAG_AF;
+       if (get_ZF()) new_word|=FLAG_ZF;
+       if (get_SF()) new_word|=FLAG_SF;
+       if (get_OF()) new_word|=FLAG_OF;
+       reg_flags=new_word;
+       lflags.type=t_UNKNOWN;
+       return reg_flags;
+}
+
+#else
+
+#define DOFLAG_PF      reg_flags=(reg_flags & ~FLAG_PF) | parity_lookup[lf_resb];
+
+#define DOFLAG_AF      reg_flags=(reg_flags & ~FLAG_AF) | (((lf_var1b ^ lf_var2b) ^ lf_resb) & 0x10);
+
+#define DOFLAG_ZFb     SETFLAGBIT(ZF,lf_resb==0);
+#define DOFLAG_ZFw     SETFLAGBIT(ZF,lf_resw==0);
+#define DOFLAG_ZFd     SETFLAGBIT(ZF,lf_resd==0);
+
+#define DOFLAG_SFb     reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resb & 0x80) >> 0);
+#define DOFLAG_SFw     reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resw & 0x8000) >> 8);
+#define DOFLAG_SFd     reg_flags=(reg_flags & ~FLAG_SF) | ((lf_resd & 0x80000000) >> 24);
+
+#define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT);
+
+#define SET_FLAG SETFLAGBIT
+
+Bitu FillFlags(void) {
+       switch (lflags.type) {
+       case t_UNKNOWN:
+               break;
+       case t_ADDb:    
+               SET_FLAG(CF,(lf_resb<lf_var1b));
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var1b)) & 0x80);
+               DOFLAG_PF;
+               break;
+       case t_ADDw:    
+               SET_FLAG(CF,(lf_resw<lf_var1w));
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var1w)) & 0x8000);
+               DOFLAG_PF;
+               break;
+       case t_ADDd:
+               SET_FLAG(CF,(lf_resd<lf_var1d));
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var1d)) & 0x80000000);
+               DOFLAG_PF;
+               break;
+       case t_ADCb:
+               SET_FLAG(CF,(lf_resb < lf_var1b) || (lflags.oldcf && (lf_resb == lf_var1b)));
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,((lf_var1b ^ lf_var2b ^ 0x80) & (lf_resb ^ lf_var1b)) & 0x80);
+               DOFLAG_PF;
+               break;
+       case t_ADCw:
+               SET_FLAG(CF,(lf_resw < lf_var1w) || (lflags.oldcf && (lf_resw == lf_var1w)));
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,((lf_var1w ^ lf_var2w ^ 0x8000) & (lf_resw ^ lf_var1w)) & 0x8000);
+               DOFLAG_PF;
+               break;
+       case t_ADCd:
+               SET_FLAG(CF,(lf_resd < lf_var1d) || (lflags.oldcf && (lf_resd == lf_var1d)));
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,((lf_var1d ^ lf_var2d ^ 0x80000000) & (lf_resd ^ lf_var1d)) & 0x80000000);
+               DOFLAG_PF;
+               break;
+
+
+       case t_SBBb:
+               SET_FLAG(CF,(lf_var1b < lf_resb) || (lflags.oldcf && (lf_var2b==0xff)));
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,(lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb) & 0x80);
+               DOFLAG_PF;
+               break;
+       case t_SBBw:
+               SET_FLAG(CF,(lf_var1w < lf_resw) || (lflags.oldcf && (lf_var2w==0xffff)));
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw) & 0x8000);
+               DOFLAG_PF;
+               break;
+       case t_SBBd:
+               SET_FLAG(CF,(lf_var1d < lf_resd) || (lflags.oldcf && (lf_var2d==0xffffffff)));
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd) & 0x80000000);
+               DOFLAG_PF;
+               break;
+       
+
+       case t_SUBb:
+       case t_CMPb:
+               SET_FLAG(CF,(lf_var1b<lf_var2b));
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,(lf_var1b ^ lf_var2b) & (lf_var1b ^ lf_resb) & 0x80);
+               DOFLAG_PF;
+               break;
+       case t_SUBw:
+       case t_CMPw:
+               SET_FLAG(CF,(lf_var1w<lf_var2w));
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_var1w ^ lf_var2w) & (lf_var1w ^ lf_resw) & 0x8000);
+               DOFLAG_PF;
+               break;
+       case t_SUBd:
+       case t_CMPd:
+               SET_FLAG(CF,(lf_var1d<lf_var2d));
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_var1d ^ lf_var2d) & (lf_var1d ^ lf_resd) & 0x80000000);
+               DOFLAG_PF;
+               break;
+
+
+       case t_ORb:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+       case t_ORw:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+       case t_ORd:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+       
+       
+       case t_TESTb:
+       case t_ANDb:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+       case t_TESTw:
+       case t_ANDw:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+       case t_TESTd:
+       case t_ANDd:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+
+       
+       case t_XORb:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+       case t_XORw:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+       case t_XORd:
+               SET_FLAG(CF,false);
+               SET_FLAG(AF,false);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               break;
+
+
+       case t_SHLb:
+               if (lf_var2b>8) SET_FLAG(CF,false);
+               else SET_FLAG(CF,(lf_var1b >> (8-lf_var2b)) & 1);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2b&0x1f));
+               break;
+       case t_SHLw:
+               if (lf_var2b>16) SET_FLAG(CF,false);
+               else SET_FLAG(CF,(lf_var1w >> (16-lf_var2b)) & 1);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2w&0x1f));
+               break;
+       case t_SHLd:
+               SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2d&0x1f));
+               break;
+
+
+       case t_DSHLw:
+               SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
+               DOFLAG_PF;
+               break;
+       case t_DSHLd:
+               SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
+               DOFLAG_PF;
+               break;
+
+
+       case t_SHRb:
+               SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               if ((lf_var2b&0x1f)==1) SET_FLAG(OF,(lf_var1b >= 0x80));
+               else SET_FLAG(OF,false);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2b&0x1f));
+               break;
+       case t_SHRw:
+               SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               if ((lf_var2w&0x1f)==1) SET_FLAG(OF,(lf_var1w >= 0x8000));
+               else SET_FLAG(OF,false);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2w&0x1f));
+               break;
+       case t_SHRd:
+               SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               if ((lf_var2d&0x1f)==1) SET_FLAG(OF,(lf_var1d >= 0x80000000));
+               else SET_FLAG(OF,false);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2d&0x1f));
+               break;
+
+       
+       case t_DSHRw:   /* Hmm this is not correct for shift higher than 16 */
+               SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000);
+               DOFLAG_PF;
+               break;
+       case t_DSHRd:
+               SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000);
+               DOFLAG_PF;
+               break;
+
+
+       case t_SARb:
+               SET_FLAG(CF,(((Bit8s) lf_var1b) >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2b&0x1f));
+               break;
+       case t_SARw:
+               SET_FLAG(CF,(((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2w&0x1f));
+               break;
+       case t_SARd:
+               SET_FLAG(CF,(((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,false);
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2d&0x1f));
+               break;
+
+       case t_INCb:
+               SET_FLAG(AF,(lf_resb & 0x0f) == 0);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,(lf_resb == 0x80));
+               DOFLAG_PF;
+               break;
+       case t_INCw:
+               SET_FLAG(AF,(lf_resw & 0x0f) == 0);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_resw == 0x8000));
+               DOFLAG_PF;
+               break;
+       case t_INCd:
+               SET_FLAG(AF,(lf_resd & 0x0f) == 0);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_resd == 0x80000000));
+               DOFLAG_PF;
+               break;
+
+       case t_DECb:
+               SET_FLAG(AF,(lf_resb & 0x0f) == 0x0f);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,(lf_resb == 0x7f));
+               DOFLAG_PF;
+               break;
+       case t_DECw:
+               SET_FLAG(AF,(lf_resw & 0x0f) == 0x0f);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_resw == 0x7fff));
+               DOFLAG_PF;
+               break;
+       case t_DECd:
+               SET_FLAG(AF,(lf_resd & 0x0f) == 0x0f);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_resd == 0x7fffffff));
+               DOFLAG_PF;
+               break;
+
+       case t_NEGb:
+               SET_FLAG(CF,(lf_var1b!=0));
+               SET_FLAG(AF,(lf_resb & 0x0f) != 0);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               SET_FLAG(OF,(lf_var1b == 0x80));
+               DOFLAG_PF;
+               break;
+       case t_NEGw:
+               SET_FLAG(CF,(lf_var1w!=0));
+               SET_FLAG(AF,(lf_resw & 0x0f) != 0);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               SET_FLAG(OF,(lf_var1w == 0x8000));
+               DOFLAG_PF;
+               break;
+       case t_NEGd:
+               SET_FLAG(CF,(lf_var1d!=0));
+               SET_FLAG(AF,(lf_resd & 0x0f) != 0);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               SET_FLAG(OF,(lf_var1d == 0x80000000));
+               DOFLAG_PF;
+               break;
+
+       
+       case t_DIV:
+       case t_MUL:
+               break;
+
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type);
+               return 0;
+       }
+       lflags.type=t_UNKNOWN;
+       return reg_flags;
+}
+
+void FillFlagsNoCFOF(void) {
+       switch (lflags.type) {
+       case t_UNKNOWN:
+               return;
+       case t_ADDb:    
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_ADDw:    
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_ADDd:
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+       case t_ADCb:
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_ADCw:
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_ADCd:
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+
+       case t_SBBb:
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_SBBw:
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_SBBd:
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+       
+
+       case t_SUBb:
+       case t_CMPb:
+               DOFLAG_AF;
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_SUBw:
+       case t_CMPw:
+               DOFLAG_AF;
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_SUBd:
+       case t_CMPd:
+               DOFLAG_AF;
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+
+       case t_ORb:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_ORw:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_ORd:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+       
+       
+       case t_TESTb:
+       case t_ANDb:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_TESTw:
+       case t_ANDw:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_TESTd:
+       case t_ANDd:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+       
+       case t_XORb:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_XORw:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_XORd:
+               SET_FLAG(AF,false);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+
+       case t_SHLb:
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2b&0x1f));
+               break;
+       case t_SHLw:
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2w&0x1f));
+               break;
+       case t_SHLd:
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2d&0x1f));
+               break;
+
+
+       case t_DSHLw:
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_DSHLd:
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+
+       case t_SHRb:
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2b&0x1f));
+               break;
+       case t_SHRw:
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2w&0x1f));
+               break;
+       case t_SHRd:
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2d&0x1f));
+               break;
+
+       
+       case t_DSHRw:   /* Hmm this is not correct for shift higher than 16 */
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_DSHRd:
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+
+       case t_SARb:
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2b&0x1f));
+               break;
+       case t_SARw:
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2w&0x1f));
+               break;
+       case t_SARd:
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               SET_FLAG(AF,(lf_var2d&0x1f));
+               break;
+
+       case t_INCb:
+               SET_FLAG(AF,(lf_resb & 0x0f) == 0);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_INCw:
+               SET_FLAG(AF,(lf_resw & 0x0f) == 0);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_INCd:
+               SET_FLAG(AF,(lf_resd & 0x0f) == 0);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+       case t_DECb:
+               SET_FLAG(AF,(lf_resb & 0x0f) == 0x0f);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_DECw:
+               SET_FLAG(AF,(lf_resw & 0x0f) == 0x0f);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_DECd:
+               SET_FLAG(AF,(lf_resd & 0x0f) == 0x0f);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+       case t_NEGb:
+               SET_FLAG(AF,(lf_resb & 0x0f) != 0);
+               DOFLAG_ZFb;
+               DOFLAG_SFb;
+               DOFLAG_PF;
+               break;
+       case t_NEGw:
+               SET_FLAG(AF,(lf_resw & 0x0f) != 0);
+               DOFLAG_ZFw;
+               DOFLAG_SFw;
+               DOFLAG_PF;
+               break;
+       case t_NEGd:
+               SET_FLAG(AF,(lf_resd & 0x0f) != 0);
+               DOFLAG_ZFd;
+               DOFLAG_SFd;
+               DOFLAG_PF;
+               break;
+
+       
+       case t_DIV:
+       case t_MUL:
+               break;
+
+       default:
+               LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type);
+               break;
+       }
+       lflags.type=t_UNKNOWN;
+}
+
+void DestroyConditionFlags(void) {
+       lflags.type=t_UNKNOWN;
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile b/source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile
new file mode 100644 (file)
index 0000000..259a906
--- /dev/null
@@ -0,0 +1,533 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# include/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/dosbox
+pkgincludedir = $(includedir)/dosbox
+pkglibdir = $(libdir)/dosbox
+pkglibexecdir = $(libexecdir)/dosbox
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-pc-linux-gnu
+host_triplet = x86_64-pc-linux-gnu
+subdir = include
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_$(V))
+am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = aclocal-1.16
+ALSA_CFLAGS = 
+ALSA_LIBS =  -lasound -lm -ldl -lpthread
+AMTAR = $${TAR-tar}
+AM_DEFAULT_VERBOSITY = 1
+AUTOCONF = autoconf
+AUTOHEADER = autoheader
+AUTOMAKE = automake-1.16
+AWK = gawk
+CC = gcc
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -E
+CPPFLAGS =  -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = 
+LIBOBJS = 
+LIBS = -lasound -lm -ldl -lpthread -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpng -lz -lX11 -lGL
+LTLIBOBJS = 
+MAKEINFO = makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = dosbox
+PACKAGE_BUGREPORT = 
+PACKAGE_NAME = dosbox
+PACKAGE_STRING = dosbox 0.74
+PACKAGE_TARNAME = dosbox
+PACKAGE_URL = 
+PACKAGE_VERSION = 0.74
+PATH_SEPARATOR = :
+RANLIB = ranlib
+SDL_CFLAGS = -I/usr/local/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+SDL_CONFIG = /usr/local/bin/sdl-config
+SDL_LIBS = -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lSDL -lXfont2 -lXi -lpthread
+SET_MAKE = 
+SHELL = /bin/bash
+STRIP = 
+VERSION = 0.74
+WINDRES = :
+abs_builddir = /home/whatisthis/src/DOSVAXJ3/include
+abs_srcdir = /home/whatisthis/src/DOSVAXJ3/include
+abs_top_builddir = /home/whatisthis/src/DOSVAXJ3
+abs_top_srcdir = /home/whatisthis/src/DOSVAXJ3
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = $${TAR-tar} chof - "$$tardir"
+am__untar = $${TAR-tar} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-pc-linux-gnu
+build_alias = 
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-pc-linux-gnu
+host_alias = 
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/whatisthis/src/DOSVAXJ3/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = $(MKDIR_P)
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+runstatedir = ${localstatedir}/run
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias = 
+top_build_prefix = ../
+top_builddir = ..
+top_srcdir = ..
+noinst_HEADERS = \
+bios.h \
+bios_disk.h \
+callback.h \
+cpu.h \
+cross.h \
+control.h \
+debug.h \
+dma.h \
+dos_inc.h \
+dos_system.h \
+dosbox.h \
+dosv.h \
+fpu.h \
+hardware.h \
+inout.h \
+ipx.h \
+ipxserver.h \
+j3.h \
+jega.h \
+jfont.h \
+joystick.h \
+keyboard.h \
+logging.h \
+mapper.h \
+mem.h \
+midi.h \
+mixer.h \
+modules.h \
+mouse.h \
+paging.h \
+pci_bus.h \
+pic.h \
+programs.h \
+render.h \
+regs.h \
+render.h \
+serialport.h \
+setup.h \
+shell.h \
+support.h \
+timer.h \
+vga.h \
+video.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu include/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile.am b/source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile.am
new file mode 100644 (file)
index 0000000..c85d156
--- /dev/null
@@ -0,0 +1,45 @@
+noinst_HEADERS =  \
+bios.h \
+bios_disk.h \
+callback.h \
+cpu.h \
+cross.h \
+control.h \
+debug.h \
+dma.h \
+dos_inc.h \
+dos_system.h \
+dosbox.h \
+dosv.h \
+fpu.h \
+hardware.h \
+inout.h \
+ipx.h \
+ipxserver.h \
+j3.h \
+jega.h \
+jfont.h \
+joystick.h \
+keyboard.h \
+logging.h \
+mapper.h \
+mem.h \
+midi.h \
+mixer.h \
+modules.h \
+mouse.h \
+paging.h \
+pci_bus.h \
+pic.h \
+programs.h \
+render.h \
+regs.h \
+render.h \
+serialport.h \
+setup.h \
+shell.h \
+support.h \
+timer.h \
+vga.h \
+video.h
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile.in b/source/src/vm/libcpu_newdev/dosbox-i386/include/Makefile.in
new file mode 100644 (file)
index 0000000..5b1cd3c
--- /dev/null
@@ -0,0 +1,533 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs  ]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = include
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+       $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \
+       $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALSA_CFLAGS = @ALSA_CFLAGS@
+ALSA_LIBS = @ALSA_LIBS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+WINDRES = @WINDRES@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_HEADERS = \
+bios.h \
+bios_disk.h \
+callback.h \
+cpu.h \
+cross.h \
+control.h \
+debug.h \
+dma.h \
+dos_inc.h \
+dos_system.h \
+dosbox.h \
+dosv.h \
+fpu.h \
+hardware.h \
+inout.h \
+ipx.h \
+ipxserver.h \
+j3.h \
+jega.h \
+jfont.h \
+joystick.h \
+keyboard.h \
+logging.h \
+mapper.h \
+mem.h \
+midi.h \
+mixer.h \
+modules.h \
+mouse.h \
+paging.h \
+pci_bus.h \
+pic.h \
+programs.h \
+render.h \
+regs.h \
+render.h \
+serialport.h \
+setup.h \
+shell.h \
+support.h \
+timer.h \
+vga.h \
+video.h
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu include/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+ID: $(am__tagged_files)
+       $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       set x; \
+       here=`pwd`; \
+       $(am__define_uniq_tagged_files); \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+       $(am__define_uniq_tagged_files); \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+       list='$(am__tagged_files)'; \
+       case "$(srcdir)" in \
+         [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+         *) sdir=$(subdir)/$(srcdir) ;; \
+       esac; \
+       for i in $$list; do \
+         if test -f "$$i"; then \
+           echo "$(subdir)/$$i"; \
+         else \
+           echo "$$sdir/$$i"; \
+         fi; \
+       done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+       cscopelist-am ctags ctags-am distclean distclean-generic \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+       uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/bios.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/bios.h
new file mode 100644 (file)
index 0000000..e4ed8db
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_BIOS_H
+#define DOSBOX_BIOS_H
+
+#define BIOS_BASE_ADDRESS_COM1          0x400
+#define BIOS_BASE_ADDRESS_COM2          0x402
+#define BIOS_BASE_ADDRESS_COM3          0x404
+#define BIOS_BASE_ADDRESS_COM4          0x406
+#define BIOS_ADDRESS_LPT1               0x408
+#define BIOS_ADDRESS_LPT2               0x40a
+#define BIOS_ADDRESS_LPT3               0x40c
+/* 0x40e is reserved */
+#define BIOS_CONFIGURATION              0x410
+/* 0x412 is reserved */
+#define BIOS_MEMORY_SIZE                0x413
+#define BIOS_TRUE_MEMORY_SIZE           0x415
+/* #define bios_expansion_memory_size      (*(unsigned int   *) 0x415) */
+#define BIOS_KEYBOARD_STATE             0x417
+#define BIOS_KEYBOARD_FLAGS1            BIOS_KEYBOARD_STATE
+#define BIOS_KEYBOARD_FLAGS2            0x418
+#define BIOS_KEYBOARD_TOKEN             0x419
+/* used for keyboard input with Alt-Number */
+#define BIOS_KEYBOARD_BUFFER_HEAD       0x41a
+#define BIOS_KEYBOARD_BUFFER_TAIL       0x41c
+#define BIOS_KEYBOARD_BUFFER            0x41e
+/* #define bios_keyboard_buffer            (*(unsigned int   *) 0x41e) */
+#define BIOS_DRIVE_ACTIVE               0x43e
+#define BIOS_DRIVE_RUNNING              0x43f
+#define BIOS_DISK_MOTOR_TIMEOUT         0x440
+#define BIOS_DISK_STATUS                0x441
+/* #define bios_fdc_result_buffer          (*(unsigned short *) 0x442) */
+#define BIOS_VIDEO_MODE                 0x449
+#define BIOS_SCREEN_COLUMNS             0x44a
+#define BIOS_VIDEO_MEMORY_USED          0x44c
+#define BIOS_VIDEO_MEMORY_ADDRESS       0x44e
+#define BIOS_VIDEO_CURSOR_POS          0x450
+
+
+#define BIOS_CURSOR_SHAPE               0x460
+#define BIOS_CURSOR_LAST_LINE           0x460
+#define BIOS_CURSOR_FIRST_LINE          0x461
+#define BIOS_CURRENT_SCREEN_PAGE        0x462
+#define BIOS_VIDEO_PORT                 0x463
+#define BIOS_VDU_CONTROL                0x465
+#define BIOS_VDU_COLOR_REGISTER         0x466
+/* 0x467-0x468 is reserved */
+#define BIOS_LAST_UNEXPECTED_IRQ        0x46b
+#define BIOS_TIMER                      0x46c
+#define BIOS_24_HOURS_FLAG              0x470
+#define BIOS_KEYBOARD_FLAGS             0x471
+#define BIOS_CTRL_ALT_DEL_FLAG          0x472
+#define BIOS_HARDDISK_COUNT            0x475
+/* 0x474, 0x476, 0x477 is reserved */
+#define BIOS_LPT1_TIMEOUT               0x478
+#define BIOS_LPT2_TIMEOUT               0x479
+#define BIOS_LPT3_TIMEOUT               0x47a
+/* 0x47b is reserved */
+#define BIOS_COM1_TIMEOUT               0x47c
+#define BIOS_COM2_TIMEOUT               0x47d
+#define BIOS_COM3_TIMEOUT               0x47e
+#define BIOS_COM4_TIMEOUT               0x47f
+/* 0x47e is reserved */ //<- why that?
+/* 0x47f-0x4ff is unknow for me */
+#define BIOS_KEYBOARD_BUFFER_START      0x480
+#define BIOS_KEYBOARD_BUFFER_END        0x482
+
+#define BIOS_ROWS_ON_SCREEN_MINUS_1     0x484
+#define BIOS_FONT_HEIGHT                0x485
+
+#define BIOS_VIDEO_INFO_0               0x487
+#define BIOS_VIDEO_INFO_1               0x488
+#define BIOS_VIDEO_INFO_2               0x489
+#define BIOS_VIDEO_COMBO                0x48a
+
+#define BIOS_KEYBOARD_FLAGS3            0x496
+#define BIOS_KEYBOARD_LEDS              0x497
+
+#define BIOS_WAIT_FLAG_POINTER          0x498
+#define BIOS_WAIT_FLAG_COUNT           0x49c           
+#define BIOS_WAIT_FLAG_ACTIVE                  0x4a0
+#define BIOS_WAIT_FLAG_TEMP                            0x4a1
+
+
+#define BIOS_PRINT_SCREEN_FLAG          0x500
+
+#define BIOS_VIDEO_SAVEPTR              0x4a8
+
+
+#define BIOS_DEFAULT_HANDLER_LOCATION  (RealMake(0xf000,0xff53))
+#define BIOS_DEFAULT_INT5_LOCATION             (RealMake(0xf000,0xff54))
+#define BIOS_DEFAULT_IRQ0_LOCATION             (RealMake(0xf000,0xfea5))
+#define BIOS_DEFAULT_IRQ1_LOCATION             (RealMake(0xf000,0xe987))
+#define BIOS_DEFAULT_IRQ2_LOCATION             (RealMake(0xf000,0xff55))
+#define BIOS_DEFAULT_RESET_LOCATION            (RealMake(0xf000,0xe05b))
+
+/* maximum of scancodes handled by keyboard bios routines */
+//#define MAX_SCAN_CODE 0x7f
+#define MAX_SCAN_CODE 0x93
+
+/* The Section handling Bios Disk Access */
+//#define BIOS_MAX_DISK 10
+
+//#define MAX_SWAPPABLE_DISKS 20
+
+void BIOS_ZeroExtendedSize(bool in);
+void char_out(Bit8u chr,Bit32u att,Bit8u page);
+void INT10_StartUp(void);
+void INT16_StartUp(void);
+void INT2A_StartUp(void);
+void INT2F_StartUp(void);
+void INT33_StartUp(void);
+void INT13_StartUp(void);
+
+bool BIOS_AddKeyToBuffer(Bit16u code);
+
+void INT10_ReloadRomFonts();
+
+void BIOS_SetComPorts (Bit16u baseaddr[]);
+void BIOS_SetLPTPort (Bitu port, Bit16u baseaddr);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/bios_disk.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/bios_disk.h
new file mode 100644 (file)
index 0000000..0670ce0
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_BIOS_DISK_H
+#define DOSBOX_BIOS_DISK_H
+
+#include <stdio.h>
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+#ifndef DOSBOX_DOS_INC_H
+#include "dos_inc.h"
+#endif
+#ifndef DOSBOX_BIOS_H
+#include "bios.h"
+#endif
+
+/* The Section handling Bios Disk Access */
+#define BIOS_MAX_DISK 10
+
+#define MAX_SWAPPABLE_DISKS 20
+struct diskGeo {
+       Bit32u ksize;  /* Size in kilobytes */
+       Bit16u secttrack; /* Sectors per track */
+       Bit16u headscyl;  /* Heads per cylinder */
+       Bit16u cylcount;  /* Cylinders per side */
+       Bit16u biosval;   /* Type to return from BIOS */
+};
+extern diskGeo DiskGeometryList[];
+
+class imageDisk  {
+public:
+       Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
+       Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data);
+       Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
+       Bit8u Write_AbsoluteSector(Bit32u sectnum, void * data);
+
+       void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
+       void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize);
+       Bit8u GetBiosType(void);
+       Bit32u getSectSize(void);
+       imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
+       ~imageDisk() { if(diskimg != NULL) { fclose(diskimg); } };
+
+       bool hardDrive;
+       bool active;
+       FILE *diskimg;
+       Bit8u diskname[512];
+       Bit8u floppytype;
+
+       Bit32u sector_size;
+       Bit32u heads,cylinders,sectors;
+private:
+       Bit32u current_fpos;
+       enum { NONE,READ,WRITE } last_action;
+};
+
+void updateDPT(void);
+void incrementFDD(void);
+
+#define MAX_HDD_IMAGES 2
+
+extern imageDisk *imageDiskList[2 + MAX_HDD_IMAGES];
+extern imageDisk *diskSwap[20];
+extern Bit32s swapPosition;
+extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */
+extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */
+extern DOS_DTA *imgDTA;
+
+void swapInDisks(void);
+void swapInNextDisk(void);
+bool getSwapRequest(void);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/callback.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/callback.h
new file mode 100644 (file)
index 0000000..44ebac2
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_CALLBACK_H
+#define DOSBOX_CALLBACK_H
+
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif 
+
+typedef Bitu (*CallBack_Handler)(void);
+extern CallBack_Handler CallBack_Handlers[];
+
+enum { CB_RETN,CB_RETF,CB_RETF8,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1,
+               CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,CB_MOUSE,
+               CB_INT29,CB_INT16,CB_HOOKABLE,CB_TDE_IRET,CB_IPXESR,CB_IPXESR_RET,
+               CB_INT21,CB_INT13,
+               CB_INT6F_ATOK };
+
+#define CB_MAX         128
+#define CB_SIZE                32
+#define CB_SEG         0xF000
+#define CB_SOFFSET     0x1000
+
+enum { 
+       CBRET_NONE=0,CBRET_STOP=1
+};
+
+extern Bit8u lastint;
+
+static INLINE RealPt CALLBACK_RealPointer(Bitu callback) {
+       return RealMake(CB_SEG,(Bit16u)(CB_SOFFSET+callback*CB_SIZE));
+}
+
+static INLINE PhysPt CALLBACK_PhysPointer(Bitu callback) {
+       return PhysMake(CB_SEG,(Bit16u)(CB_SOFFSET+callback*CB_SIZE));
+}
+
+static INLINE PhysPt CALLBACK_GetBase(void) {
+       return (CB_SEG << 4) + CB_SOFFSET;
+}
+
+Bitu CALLBACK_Allocate();
+
+void CALLBACK_Idle(void);
+
+
+void CALLBACK_RunRealInt(Bit8u intnum);
+void CALLBACK_RunRealFar(Bit16u seg,Bit16u off);
+
+bool CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,const char* descr);
+Bitu CALLBACK_Setup(Bitu callback,CallBack_Handler handler,Bitu type,PhysPt addr,const char* descr);
+
+const char* CALLBACK_GetDescription(Bitu callback);
+bool CALLBACK_Free(Bitu callback);
+
+void CALLBACK_SCF(bool val);
+void CALLBACK_SZF(bool val);
+void CALLBACK_SIF(bool val);
+
+extern Bitu call_priv_io;
+
+
+class CALLBACK_HandlerObject{
+private:
+       bool installed;
+       Bitu m_callback;
+       enum {NONE,SETUP,SETUPAT} m_type;
+    struct {   
+               RealPt old_vector;
+               Bit8u interrupt;
+               bool installed;
+       } vectorhandler;
+public:
+       CALLBACK_HandlerObject():installed(false),m_type(NONE) {
+               vectorhandler.installed=false;
+       }
+       ~CALLBACK_HandlerObject();
+
+       //Install and allocate a callback.
+       void Install(CallBack_Handler handler,Bitu type,const char* description);
+       void Install(CallBack_Handler handler,Bitu type,PhysPt addr,const char* description);
+
+       void Uninstall();
+
+       //Only allocate a callback number
+       void Allocate(CallBack_Handler handler,const char* description=0);
+       Bit16u Get_callback() {
+               return (Bit16u)m_callback;
+       }
+       RealPt Get_RealPointer() {
+               return CALLBACK_RealPointer(m_callback);
+       }
+       void Set_RealVec(Bit8u vec);
+};
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/control.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/control.h
new file mode 100644 (file)
index 0000000..4666a27
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_CONTROL_H
+#define DOSBOX_CONTROL_H
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4290 )
+#endif
+
+#ifndef DOSBOX_PROGRAMS_H
+#include "programs.h"
+#endif
+#ifndef DOSBOX_SETUP_H
+#include "setup.h"
+#endif
+
+#ifndef CH_LIST
+#define CH_LIST
+#include <list>
+#endif
+
+#ifndef CH_VECTOR
+#define CH_VECTOR
+#include <vector>
+#endif
+
+#ifndef CH_STRING
+#define CH_STRING
+#include <string>
+#endif
+
+
+
+
+class Config{
+public:
+       CommandLine * cmdline;
+private:
+       std::list<Section*> sectionlist;
+       typedef std::list<Section*>::iterator it;
+       typedef std::list<Section*>::reverse_iterator reverse_it;
+       typedef std::list<Section*>::const_iterator const_it;
+       typedef std::list<Section*>::const_reverse_iterator const_reverse_it;
+       void (* _start_function)(void);
+       bool secure_mode; //Sandbox mode
+public:
+       bool initialised;
+       std::vector<std::string> startup_params;
+       std::vector<std::string> configfiles;
+       Config(CommandLine * cmd):cmdline(cmd),secure_mode(false) {
+               startup_params.push_back(cmdline->GetFileName());
+               cmdline->FillVector(startup_params);
+               initialised=false;
+       }
+       ~Config();
+
+       Section_line * AddSection_line(char const * const _name,void (*_initfunction)(Section*));
+       Section_prop * AddSection_prop(char const * const _name,void (*_initfunction)(Section*),bool canchange=false);
+       
+       Section* GetSection(int index);
+       Section* GetSection(std::string const&_sectionname) const;
+       Section* GetSectionFromProperty(char const * const prop) const;
+
+       void SetStartUp(void (*_function)(void));
+       void Init();
+       void ShutDown();
+       void StartUp();
+       bool PrintConfig(char const * const configfilename) const;
+       bool ParseConfigFile(char const * const configfilename);
+       void ParseEnv(char ** envp);
+       bool SecureMode() const { return secure_mode; }
+       void SwitchToSecureMode() { secure_mode = true; }//can't be undone
+};
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/cpu.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/cpu.h
new file mode 100644 (file)
index 0000000..2f27f2c
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_CPU_H
+#define DOSBOX_CPU_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h" 
+#endif
+#ifndef DOSBOX_REGS_H
+#include "regs.h"
+#endif
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+
+#define CPU_AUTODETERMINE_NONE         0x00
+#define CPU_AUTODETERMINE_CORE         0x01
+#define CPU_AUTODETERMINE_CYCLES       0x02
+
+#define CPU_AUTODETERMINE_SHIFT                0x02
+#define CPU_AUTODETERMINE_MASK         0x03
+
+#define CPU_CYCLES_LOWER_LIMIT         200
+
+
+#define CPU_ARCHTYPE_MIXED                     0xff
+#define CPU_ARCHTYPE_386SLOW           0x30
+#define CPU_ARCHTYPE_386FAST           0x35
+#define CPU_ARCHTYPE_486OLDSLOW                0x40
+#define CPU_ARCHTYPE_486NEWSLOW                0x45
+#define CPU_ARCHTYPE_PENTIUMSLOW       0x50
+
+/* CPU Cycle Timing */
+extern Bit32s CPU_Cycles;
+extern Bit32s CPU_CycleLeft;
+extern Bit32s CPU_CycleMax;
+extern Bit32s CPU_OldCycleMax;
+extern Bit32s CPU_CyclePercUsed;
+extern Bit32s CPU_CycleLimit;
+extern Bit64s CPU_IODelayRemoved;
+extern bool CPU_CycleAutoAdjust;
+extern bool CPU_SkipCycleAutoAdjust;
+extern Bitu CPU_AutoDetermineMode;
+
+extern Bitu CPU_ArchitectureType;
+
+extern Bitu CPU_PrefetchQueueSize;
+
+/* Some common Defines */
+/* A CPU Handler */
+typedef Bits (CPU_Decoder)(void);
+extern CPU_Decoder * cpudecoder;
+
+Bits CPU_Core_Normal_Run(void);
+Bits CPU_Core_Normal_Trap_Run(void);
+Bits CPU_Core_Simple_Run(void);
+Bits CPU_Core_Full_Run(void);
+Bits CPU_Core_Dyn_X86_Run(void);
+Bits CPU_Core_Dyn_X86_Trap_Run(void);
+Bits CPU_Core_Dynrec_Run(void);
+Bits CPU_Core_Dynrec_Trap_Run(void);
+Bits CPU_Core_Prefetch_Run(void);
+Bits CPU_Core_Prefetch_Trap_Run(void);
+
+void CPU_Enable_SkipAutoAdjust(void);
+void CPU_Disable_SkipAutoAdjust(void);
+void CPU_Reset_AutoAdjust(void);
+
+
+//CPU Stuff
+
+extern Bit16u parity_lookup[256];
+
+bool CPU_LLDT(Bitu selector);
+bool CPU_LTR(Bitu selector);
+void CPU_LIDT(Bitu limit,Bitu base);
+void CPU_LGDT(Bitu limit,Bitu base);
+
+Bitu CPU_STR(void);
+Bitu CPU_SLDT(void);
+Bitu CPU_SIDT_base(void);
+Bitu CPU_SIDT_limit(void);
+Bitu CPU_SGDT_base(void);
+Bitu CPU_SGDT_limit(void);
+
+void CPU_ARPL(Bitu & dest_sel,Bitu src_sel);
+void CPU_LAR(Bitu selector,Bitu & ar);
+void CPU_LSL(Bitu selector,Bitu & limit);
+
+void CPU_SET_CRX(Bitu cr,Bitu value);
+bool CPU_WRITE_CRX(Bitu cr,Bitu value);
+Bitu CPU_GET_CRX(Bitu cr);
+bool CPU_READ_CRX(Bitu cr,Bit32u & retvalue);
+
+bool CPU_WRITE_DRX(Bitu dr,Bitu value);
+bool CPU_READ_DRX(Bitu dr,Bit32u & retvalue);
+
+bool CPU_WRITE_TRX(Bitu dr,Bitu value);
+bool CPU_READ_TRX(Bitu dr,Bit32u & retvalue);
+
+Bitu CPU_SMSW(void);
+bool CPU_LMSW(Bitu word);
+
+void CPU_VERR(Bitu selector);
+void CPU_VERW(Bitu selector);
+
+void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
+void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bitu oldeip);
+void CPU_RET(bool use32,Bitu bytes,Bitu oldeip);
+void CPU_IRET(bool use32,Bitu oldeip);
+void CPU_HLT(Bitu oldeip);
+
+bool CPU_POPF(Bitu use32);
+bool CPU_PUSHF(Bitu use32);
+bool CPU_CLI(void);
+bool CPU_STI(void);
+
+bool CPU_IO_Exception(Bitu port,Bitu size);
+void CPU_RunException(void);
+
+void CPU_ENTER(bool use32,Bitu bytes,Bitu level);
+
+#define CPU_INT_SOFTWARE               0x1
+#define CPU_INT_EXCEPTION              0x2
+#define CPU_INT_HAS_ERROR              0x4
+#define CPU_INT_NOIOPLCHECK            0x8
+
+void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip);
+static INLINE void CPU_HW_Interrupt(Bitu num) {
+       CPU_Interrupt(num,0,reg_eip);
+}
+static INLINE void CPU_SW_Interrupt(Bitu num,Bitu oldeip) {
+       CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip);
+}
+static INLINE void CPU_SW_Interrupt_NoIOPLCheck(Bitu num,Bitu oldeip) {
+       CPU_Interrupt(num,CPU_INT_SOFTWARE|CPU_INT_NOIOPLCHECK,oldeip);
+}
+
+bool CPU_PrepareException(Bitu which,Bitu error);
+void CPU_Exception(Bitu which,Bitu error=0);
+
+bool CPU_SetSegGeneral(SegNames seg,Bitu value);
+bool CPU_PopSeg(SegNames seg,bool use32);
+
+bool CPU_CPUID(void);
+Bitu CPU_Pop16(void);
+Bitu CPU_Pop32(void);
+void CPU_Push16(Bitu value);
+void CPU_Push32(Bitu value);
+
+void CPU_SetFlags(Bitu word,Bitu mask);
+
+
+#define EXCEPTION_UD                   6
+#define EXCEPTION_TS                   10
+#define EXCEPTION_NP                   11
+#define EXCEPTION_SS                   12
+#define EXCEPTION_GP                   13
+#define EXCEPTION_PF                   14
+
+#define CR0_PROTECTION                 0x00000001
+#define CR0_MONITORPROCESSOR   0x00000002
+#define CR0_FPUEMULATION               0x00000004
+#define CR0_TASKSWITCH                 0x00000008
+#define CR0_FPUPRESENT                 0x00000010
+#define CR0_PAGING                             0x80000000
+
+
+// *********************************************************************
+// Descriptor
+// *********************************************************************
+
+#define DESC_INVALID                           0x00
+#define DESC_286_TSS_A                         0x01
+#define DESC_LDT                                       0x02
+#define DESC_286_TSS_B                         0x03
+#define DESC_286_CALL_GATE                     0x04
+#define DESC_TASK_GATE                         0x05
+#define DESC_286_INT_GATE                      0x06
+#define DESC_286_TRAP_GATE                     0x07
+
+#define DESC_386_TSS_A                         0x09
+#define DESC_386_TSS_B                         0x0b
+#define DESC_386_CALL_GATE                     0x0c
+#define DESC_386_INT_GATE                      0x0e
+#define DESC_386_TRAP_GATE                     0x0f
+
+/* EU/ED Expand UP/DOWN RO/RW Read Only/Read Write NA/A Accessed */
+#define DESC_DATA_EU_RO_NA                     0x10
+#define DESC_DATA_EU_RO_A                      0x11
+#define DESC_DATA_EU_RW_NA                     0x12
+#define DESC_DATA_EU_RW_A                      0x13
+#define DESC_DATA_ED_RO_NA                     0x14
+#define DESC_DATA_ED_RO_A                      0x15
+#define DESC_DATA_ED_RW_NA                     0x16
+#define DESC_DATA_ED_RW_A                      0x17
+
+/* N/R Readable  NC/C Confirming A/NA Accessed */
+#define DESC_CODE_N_NC_A                       0x18
+#define DESC_CODE_N_NC_NA                      0x19
+#define DESC_CODE_R_NC_A                       0x1a
+#define DESC_CODE_R_NC_NA                      0x1b
+#define DESC_CODE_N_C_A                                0x1c
+#define DESC_CODE_N_C_NA                       0x1d
+#define DESC_CODE_R_C_A                                0x1e
+#define DESC_CODE_R_C_NA                       0x1f
+
+#ifdef _MSC_VER
+#pragma pack (1)
+#endif
+
+struct S_Descriptor {
+#ifdef WORDS_BIGENDIAN
+       Bit32u base_0_15        :16;
+       Bit32u limit_0_15       :16;
+       Bit32u base_24_31       :8;
+       Bit32u g                        :1;
+       Bit32u big                      :1;
+       Bit32u r                        :1;
+       Bit32u avl                      :1;
+       Bit32u limit_16_19      :4;
+       Bit32u p                        :1;
+       Bit32u dpl                      :2;
+       Bit32u type                     :5;
+       Bit32u base_16_23       :8;
+#else
+       Bit32u limit_0_15       :16;
+       Bit32u base_0_15        :16;
+       Bit32u base_16_23       :8;
+       Bit32u type                     :5;
+       Bit32u dpl                      :2;
+       Bit32u p                        :1;
+       Bit32u limit_16_19      :4;
+       Bit32u avl                      :1;
+       Bit32u r                        :1;
+       Bit32u big                      :1;
+       Bit32u g                        :1;
+       Bit32u base_24_31       :8;
+#endif
+}GCC_ATTRIBUTE(packed);
+
+struct G_Descriptor {
+#ifdef WORDS_BIGENDIAN
+       Bit32u selector:        16;
+       Bit32u offset_0_15      :16;
+       Bit32u offset_16_31     :16;
+       Bit32u p                        :1;
+       Bit32u dpl                      :2;
+       Bit32u type                     :5;
+       Bit32u reserved         :3;
+       Bit32u paramcount       :5;
+#else
+       Bit32u offset_0_15      :16;
+       Bit32u selector         :16;
+       Bit32u paramcount       :5;
+       Bit32u reserved         :3;
+       Bit32u type                     :5;
+       Bit32u dpl                      :2;
+       Bit32u p                        :1;
+       Bit32u offset_16_31     :16;
+#endif
+} GCC_ATTRIBUTE(packed);
+
+struct TSS_16 {        
+    Bit16u back;                 /* Back link to other task */
+    Bit16u sp0;                                     /* The CK stack pointer */
+    Bit16u ss0;                                         /* The CK stack selector */
+       Bit16u sp1;                  /* The parent KL stack pointer */
+    Bit16u ss1;                  /* The parent KL stack selector */
+       Bit16u sp2;                  /* Unused */
+    Bit16u ss2;                  /* Unused */
+    Bit16u ip;                   /* The instruction pointer */
+    Bit16u flags;                /* The flags */
+    Bit16u ax, cx, dx, bx;       /* The general purpose registers */
+    Bit16u sp, bp, si, di;       /* The special purpose registers */
+    Bit16u es;                   /* The extra selector */
+    Bit16u cs;                   /* The code selector */
+    Bit16u ss;                   /* The application stack selector */
+    Bit16u ds;                   /* The data selector */
+    Bit16u ldt;                  /* The local descriptor table */
+} GCC_ATTRIBUTE(packed);
+
+struct TSS_32 {        
+    Bit32u back;                /* Back link to other task */
+       Bit32u esp0;                     /* The CK stack pointer */
+    Bit32u ss0;                                         /* The CK stack selector */
+       Bit32u esp1;                 /* The parent KL stack pointer */
+    Bit32u ss1;                  /* The parent KL stack selector */
+       Bit32u esp2;                 /* Unused */
+    Bit32u ss2;                  /* Unused */
+       Bit32u cr3;                  /* The page directory pointer */
+    Bit32u eip;                  /* The instruction pointer */
+    Bit32u eflags;               /* The flags */
+    Bit32u eax, ecx, edx, ebx;   /* The general purpose registers */
+    Bit32u esp, ebp, esi, edi;   /* The special purpose registers */
+    Bit32u es;                   /* The extra selector */
+    Bit32u cs;                   /* The code selector */
+    Bit32u ss;                   /* The application stack selector */
+    Bit32u ds;                   /* The data selector */
+    Bit32u fs;                   /* And another extra selector */
+    Bit32u gs;                   /* ... and another one */
+    Bit32u ldt;                  /* The local descriptor table */
+} GCC_ATTRIBUTE(packed);
+
+#ifdef _MSC_VER
+#pragma pack()
+#endif
+class Descriptor
+{
+public:
+       Descriptor() { saved.fill[0]=saved.fill[1]=0; }
+
+       void Load(PhysPt address);
+       void Save(PhysPt address);
+
+       PhysPt GetBase (void) { 
+               return (saved.seg.base_24_31<<24) | (saved.seg.base_16_23<<16) | saved.seg.base_0_15; 
+       }
+       Bitu GetLimit (void) {
+               Bitu limit = (saved.seg.limit_16_19<<16) | saved.seg.limit_0_15;
+               if (saved.seg.g)        return (limit<<12) | 0xFFF;
+               return limit;
+       }
+       Bitu GetOffset(void) {
+               return (saved.gate.offset_16_31 << 16) | saved.gate.offset_0_15;
+       }
+       Bitu GetSelector(void) {
+               return saved.gate.selector;
+       }
+       Bitu Type(void) {
+               return saved.seg.type;
+       }
+       Bitu Conforming(void) {
+               return saved.seg.type & 8;
+       }
+       Bitu DPL(void) {
+               return saved.seg.dpl;
+       }
+       Bitu Big(void) {
+               return saved.seg.big;
+       }
+public:
+       union {
+               S_Descriptor seg;
+               G_Descriptor gate;
+               Bit32u fill[2];
+       } saved;
+};
+
+class DescriptorTable {
+public:
+       PhysPt  GetBase                 (void)                  { return table_base;    }
+       Bitu    GetLimit                (void)                  { return table_limit;   }
+       void    SetBase                 (PhysPt _base)  { table_base = _base;   }
+       void    SetLimit                (Bitu _limit)   { table_limit= _limit;  }
+
+       bool GetDescriptor      (Bitu selector, Descriptor& desc) {
+               selector&=~7;
+               if (selector>=table_limit) return false;
+               desc.Load(table_base+(selector));
+               return true;
+       }
+protected:
+       PhysPt table_base;
+       Bitu table_limit;
+};
+
+class GDTDescriptorTable : public DescriptorTable {
+public:
+       bool GetDescriptor(Bitu selector, Descriptor& desc) {
+               Bitu address=selector & ~7;
+               if (selector & 4) {
+                       if (address>=ldt_limit) return false;
+                       desc.Load(ldt_base+address);
+                       return true;
+               } else {
+                       if (address>=table_limit) return false;
+                       desc.Load(table_base+address);
+                       return true;
+               }
+       }
+       bool SetDescriptor(Bitu selector, Descriptor& desc) {
+               Bitu address=selector & ~7;
+               if (selector & 4) {
+                       if (address>=ldt_limit) return false;
+                       desc.Save(ldt_base+address);
+                       return true;
+               } else {
+                       if (address>=table_limit) return false;
+                       desc.Save(table_base+address);
+                       return true;
+               }
+       } 
+       Bitu SLDT(void) {
+               return ldt_value;
+       }
+       bool LLDT(Bitu value)   {
+               if ((value&0xfffc)==0) {
+                       ldt_value=0;
+                       ldt_base=0;
+                       ldt_limit=0;
+                       return true;
+               }
+               Descriptor desc;
+               if (!GetDescriptor(value,desc)) return !CPU_PrepareException(EXCEPTION_GP,value);
+               if (desc.Type()!=DESC_LDT) return !CPU_PrepareException(EXCEPTION_GP,value);
+               if (!desc.saved.seg.p) return !CPU_PrepareException(EXCEPTION_NP,value);
+               ldt_base=desc.GetBase();
+               ldt_limit=desc.GetLimit();
+               ldt_value=value;
+               return true;
+       }
+private:
+       PhysPt ldt_base;
+       Bitu ldt_limit;
+       Bitu ldt_value;
+};
+
+class TSS_Descriptor : public Descriptor {
+public:
+       Bitu IsBusy(void) {
+               return saved.seg.type & 2;
+       }
+       Bitu Is386(void) {
+               return saved.seg.type & 8;
+       }
+       void SetBusy(bool busy) {
+               if (busy) saved.seg.type|=2;
+               else saved.seg.type&=~2;
+       }
+};
+
+
+struct CPUBlock {
+       Bitu cpl;                                                       /* Current Privilege */
+       Bitu mpl;
+       Bitu cr0;
+       bool pmode;                                                     /* Is Protected mode enabled */
+       GDTDescriptorTable gdt;
+       DescriptorTable idt;
+       struct {
+               Bitu mask,notmask;
+               bool big;
+       } stack;
+       struct {
+               bool big;
+       } code;
+       struct {
+               Bitu cs,eip;
+               CPU_Decoder * old_decoder;
+       } hlt;
+       struct {
+               Bitu which,error;
+       } exception;
+       Bits direction;
+       bool trap_skip;
+       Bit32u drx[8];
+       Bit32u trx[8];
+};
+
+extern CPUBlock cpu;
+
+static INLINE void CPU_SetFlagsd(Bitu word) {
+       Bitu mask=cpu.cpl ? FMASK_NORMAL : FMASK_ALL;
+       CPU_SetFlags(word,mask);
+}
+
+static INLINE void CPU_SetFlagsw(Bitu word) {
+       Bitu mask=(cpu.cpl ? FMASK_NORMAL : FMASK_ALL) & 0xffff;
+       CPU_SetFlags(word,mask);
+}
+
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/cross.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/cross.h
new file mode 100644 (file)
index 0000000..bcc5484
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ *  Copyright (C) 2002-2017  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Wengier: LFN support
+ */
+
+
+#ifndef DOSBOX_CROSS_H
+#define DOSBOX_CROSS_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string>
+
+#if defined (_MSC_VER)                                         /* MS Visual C++ */
+#include <direct.h>
+#include <io.h>
+#define LONGTYPE(a) a##i64
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#else                                                                          /* LINUX / GCC */
+#include <dirent.h>
+#include <unistd.h>
+#define LONGTYPE(a) a##LL
+#endif
+
+#define CROSS_LEN 512                                          /* Maximum filename size */
+
+
+#if defined (WIN32) || defined (OS2)                           /* Win 32 & OS/2*/
+#define CROSS_FILENAME(blah) 
+#define CROSS_FILESPLIT '\\'
+#define F_OK 0
+#else
+#define        CROSS_FILENAME(blah) strreplace(blah,'\\','/')
+#define CROSS_FILESPLIT '/'
+#endif
+
+#define CROSS_NONE     0
+#define CROSS_FILE     1
+#define CROSS_DIR      2
+#if defined (WIN32)
+#define ftruncate(blah,blah2) chsize(blah,blah2)
+#endif
+
+//Solaris maybe others
+#if defined (DB_HAVE_NO_POWF)
+#include <math.h>
+static inline float powf (float x, float y) { return (float) pow (x,y); }
+#endif
+
+class Cross {
+public:
+       static void GetPlatformConfigDir(std::string& in);
+       static void GetPlatformConfigName(std::string& in);
+       static void CreatePlatformConfigDir(std::string& in);
+       static void ResolveHomedir(std::string & temp_line);
+       static void CreateDir(std::string const& temp);
+       static bool IsPathAbsolute(std::string const& in);
+};
+
+
+#if defined (WIN32)
+
+#define WIN32_LEAN_AND_MEAN        // Exclude rarely-used stuff from 
+#include <windows.h>
+
+typedef struct dir_struct {
+       HANDLE          handle;
+       char            base_path[MAX_PATH+4];
+       WIN32_FIND_DATA search_data;
+} dir_information;
+
+#else
+
+//#include <sys/types.h> //Included above
+#include <dirent.h>
+
+typedef struct dir_struct { 
+       DIR*  dir;
+       char base_path[CROSS_LEN];
+} dir_information;
+
+#endif
+
+dir_information* open_directory(const char* dirname);
+bool read_directory_first(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory);
+bool read_directory_next(dir_information* dirp, char* entry_name, char* entry_sname, bool& is_directory);
+void close_directory(dir_information* dirp);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/debug.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/debug.h
new file mode 100644 (file)
index 0000000..9e21462
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+void DEBUG_SetupConsole(void);
+void DEBUG_DrawScreen(void);
+bool DEBUG_Breakpoint(void);
+bool DEBUG_IntBreakpoint(Bit8u intNum);
+void DEBUG_Enable(bool pressed);
+void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off);
+bool DEBUG_ExitLoop(void);
+void DEBUG_RefreshPage(char scroll);
+Bitu DEBUG_EnableDebugger(void);
+
+extern Bitu cycle_count;
+extern Bitu debugCallback;
+
+#ifdef C_HEAVY_DEBUG
+bool DEBUG_HeavyIsBreakpoint(void);
+void DEBUG_HeavyWriteLogInstruction(void);
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/dma.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/dma.h
new file mode 100644 (file)
index 0000000..3853181
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_DMA_H
+#define DOSBOX_DMA_H
+
+enum DMAEvent {
+       DMA_REACHED_TC,
+       DMA_MASKED,
+       DMA_UNMASKED,
+       DMA_TRANSFEREND
+};
+
+class DmaChannel;
+typedef void (* DMA_CallBack)(DmaChannel * chan,DMAEvent event);
+
+class DmaChannel {
+public:
+       Bit32u pagebase;
+       Bit16u baseaddr;
+       Bit32u curraddr;
+       Bit16u basecnt;
+       Bit16u currcnt;
+       Bit8u channum;
+       Bit8u pagenum;
+       Bit8u DMA16;
+       bool increment;
+       bool autoinit;
+       Bit8u trantype;
+       bool masked;
+       bool tcount;
+       bool request;
+       DMA_CallBack callback;
+
+       DmaChannel(Bit8u num, bool dma16);
+       void DoCallBack(DMAEvent event) {
+               if (callback)   (*callback)(this,event);
+       }
+       void SetMask(bool _mask) {
+               masked=_mask;
+               DoCallBack(masked ? DMA_MASKED : DMA_UNMASKED);
+       }
+       void Register_Callback(DMA_CallBack _cb) { 
+               callback = _cb; 
+               SetMask(masked);
+               if (callback) Raise_Request();
+               else Clear_Request();
+       }
+       void ReachedTC(void) {
+               tcount=true;
+               DoCallBack(DMA_REACHED_TC);
+       }
+       void SetPage(Bit8u val) {
+               pagenum=val;
+               pagebase=(pagenum >> DMA16) << (16+DMA16);
+       }
+       void Raise_Request(void) {
+               request=true;
+       }
+       void Clear_Request(void) {
+               request=false;
+       }
+       Bitu Read(Bitu size, Bit8u * buffer);
+       Bitu Write(Bitu size, Bit8u * buffer);
+};
+
+class DmaController {
+private:
+       Bit8u ctrlnum;
+       bool flipflop;
+       DmaChannel *DmaChannels[4];
+public:
+       IO_ReadHandleObject DMA_ReadHandler[0x11];
+       IO_WriteHandleObject DMA_WriteHandler[0x11];
+       DmaController(Bit8u num) {
+               flipflop = false;
+               ctrlnum = num;          /* first or second DMA controller */
+               for(Bit8u i=0;i<4;i++) {
+                       DmaChannels[i] = new DmaChannel(i+ctrlnum*4,ctrlnum==1);
+               }
+       }
+       ~DmaController(void) {
+               for(Bit8u i=0;i<4;i++) {
+                       delete DmaChannels[i];
+               }
+       }
+       DmaChannel * GetChannel(Bit8u chan) {
+               if (chan<4) return DmaChannels[chan];
+               else return NULL;
+       }
+       void WriteControllerReg(Bitu reg,Bitu val,Bitu len);
+       Bitu ReadControllerReg(Bitu reg,Bitu len);
+};
+
+DmaChannel * GetDMAChannel(Bit8u chan);
+
+void CloseSecondDMAController(void);
+bool SecondDMAControllerAvailable(void);
+
+void DMA_SetWrapping(Bitu wrap);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/dos_inc.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/dos_inc.h
new file mode 100644 (file)
index 0000000..624dd89
--- /dev/null
@@ -0,0 +1,676 @@
+/*
+ *  Copyright (C) 2002-2017  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Wengier: LFN support
+ */
+
+
+#ifndef DOSBOX_DOS_INC_H
+#define DOSBOX_DOS_INC_H
+
+#ifndef DOSBOX_DOS_SYSTEM_H
+#include "dos_system.h"
+#endif
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+
+#include <stddef.h> //for offsetof
+#define CTBUF 127
+
+#ifdef _MSC_VER
+#pragma pack (1)
+#endif
+struct CommandTail{
+  Bit8u count;                         /* number of bytes returned */
+  char buffer[CTBUF];                   /* the buffer itself */
+} GCC_ATTRIBUTE(packed);
+#ifdef _MSC_VER
+#pragma pack ()
+#endif
+
+struct DOS_Date {
+       Bit16u year;
+       Bit8u month;
+       Bit8u day;
+};
+
+struct DOS_Version {
+       Bit8u major,minor,revision;
+};
+
+
+#ifdef _MSC_VER
+#pragma pack (1)
+#endif
+union bootSector {
+       struct entries {
+               Bit8u jump[3];
+               Bit8u oem_name[8];
+               Bit16u bytesect;
+               Bit8u sectclust;
+               Bit16u reserve_sect;
+               Bit8u misc[496];
+       } bootdata;
+       Bit8u rawdata[512];
+} GCC_ATTRIBUTE(packed);
+#ifdef _MSC_VER
+#pragma pack ()
+#endif
+
+
+enum { MCB_FREE=0x0000,MCB_DOS=0x0008 };
+enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3};
+
+#define DOS_FILES 127
+#define DOS_DRIVES 26
+#define DOS_DEVICES 20
+
+
+// dos swappable area is 0x320 bytes beyond the sysvars table
+// device driver chain is inside sysvars
+#define DOS_INFOBLOCK_SEG 0x80 // sysvars (list of lists)
+#define DOS_CONDRV_SEG 0xa0
+#define DOS_CONSTRING_SEG 0xa8
+#define DOS_SDA_SEG 0xb2               // dos swappable area
+#define DOS_SDA_OFS 0
+#define DOS_CDS_SEG 0x108
+#define DOS_FIRST_SHELL 0x118
+#define DOS_MEM_START 0x16f            //First Segment that DOS can use
+
+#define DOS_PRIVATE_SEGMENT 0xc800
+#define DOS_PRIVATE_SEGMENT_END 0xd000
+
+/* internal Dos Tables */
+
+extern DOS_File * Files[DOS_FILES];
+extern DOS_Drive * Drives[DOS_DRIVES];
+extern DOS_Device * Devices[DOS_DEVICES];
+
+extern Bit8u dos_copybuf[0x10000];
+
+
+void DOS_SetError(Bit16u code);
+
+/* File Handling Routines */
+
+enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDPRN=4};
+enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE};
+
+/* Routines for File Class */
+void DOS_SetupFiles (void);
+bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount, bool fcb = false);
+bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount,bool fcb = false);
+bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type,bool fcb = false);
+bool DOS_CloseFile(Bit16u handle,bool fcb = false);
+bool DOS_FlushFile(Bit16u handle);
+bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry);
+bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry);
+bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate);
+
+/* Routines for Drive Class */
+bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry,bool fcb = false);
+bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status);
+bool DOS_CreateFile(char const * name,Bit16u attribute,Bit16u * entry, bool fcb = false);
+bool DOS_UnlinkFile(char const * const name);
+bool DOS_GetSFNPath(char const * const path, char *SFNpath, bool LFN);
+bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false);
+bool DOS_FindNext(void);
+bool DOS_Canonicalize(char const * const name,char * const big);
+bool DOS_CreateTempFile(char * const name,Bit16u * entry);
+bool DOS_FileExists(char const * const name);
+
+/* Helper Functions */
+bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive);
+/* Drive Handing Routines */
+Bit8u DOS_GetDefaultDrive(void);
+void DOS_SetDefaultDrive(Bit8u drive);
+bool DOS_SetDrive(Bit8u drive);
+bool DOS_GetCurrentDir(Bit8u drive,char * const buffer, bool LFN);
+bool DOS_ChangeDir(char const * const dir);
+bool DOS_MakeDir(char const * const dir);
+bool DOS_RemoveDir(char const * const dir);
+bool DOS_Rename(char const * const oldname,char const * const newname);
+bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free);
+bool DOS_GetFileAttr(char const * const name,Bit16u * attr);
+bool DOS_SetFileAttr(char const * const name,Bit16u attr);
+bool DOS_GetFileAttrEx(char const* const name, struct stat *status, Bit8u hdrive=-1);
+DWORD DOS_GetCompressedFileSize(char const* const name);
+HANDLE DOS_CreateOpenFile(char const* const name);
+
+/* IOCTL Stuff */
+bool DOS_IOCTL(void);
+bool DOS_GetSTDINStatus();
+Bit8u DOS_FindDevice(char const * name);
+void DOS_SetupDevices(void);
+void DOS_ClearKeyMap(void);
+
+/* Execute and new process creation */
+bool DOS_NewPSP(Bit16u pspseg,Bit16u size);
+bool DOS_ChildPSP(Bit16u pspseg,Bit16u size);
+bool DOS_Execute(char * name,PhysPt block,Bit8u flags);
+void DOS_Terminate(Bit16u pspseg,bool tsr,Bit8u exitcode);
+
+/* Memory Handling Routines */
+void DOS_SetupMemory(void);
+bool DOS_AllocateMemory(Bit16u * segment,Bit16u * blocks);
+bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks);
+bool DOS_FreeMemory(Bit16u segment);
+void DOS_FreeProcessMemory(Bit16u pspseg);
+Bit16u DOS_GetMemory(Bit16u pages);
+bool DOS_SetMemAllocStrategy(Bit16u strat);
+Bit16u DOS_GetMemAllocStrategy(void);
+void DOS_BuildUMBChain(bool umb_active,bool ems_active);
+bool DOS_LinkUMBsToMemChain(Bit16u linkstate);
+
+/* FCB stuff */
+bool DOS_FCBOpen(Bit16u seg,Bit16u offset);
+bool DOS_FCBCreate(Bit16u seg,Bit16u offset);
+bool DOS_FCBClose(Bit16u seg,Bit16u offset);
+bool DOS_FCBFindFirst(Bit16u seg,Bit16u offset);
+bool DOS_FCBFindNext(Bit16u seg,Bit16u offset);
+Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset, Bit16u numBlocks);
+Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u numBlocks);
+Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u * numRec,bool restore);
+Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u * numRec,bool restore);
+bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset);
+bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset);
+bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset);
+void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset);
+Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u *change);
+bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters);
+
+/* Extra DOS Interrupts */
+void DOS_SetupMisc(void);
+
+/* The DOS Tables */
+void DOS_SetupTables(void);
+
+/* Internal DOS Setup Programs */
+void DOS_SetupPrograms(void);
+
+/* Initialize Keyboard Layout */
+void DOS_KeyboardLayout_Init(Section* sec);
+
+bool DOS_LayoutKey(Bitu key, Bit8u flags1, Bit8u flags2, Bit8u flags3);
+
+enum {
+       KEYB_NOERROR=0,
+       KEYB_FILENOTFOUND,
+       KEYB_INVALIDFILE,
+       KEYB_LAYOUTNOTFOUND,
+       KEYB_INVALIDCPFILE
+};
+
+
+static INLINE Bit16u long2para(Bit32u size) {
+       if (size>0xFFFF0) return 0xffff;
+       if (size&0xf) return (Bit16u)((size>>4)+1);
+       else return (Bit16u)(size>>4);
+}
+
+
+static INLINE Bit16u DOS_PackTime(Bit16u hour,Bit16u min,Bit16u sec) {
+       return (hour&0x1f)<<11 | (min&0x3f) << 5 | ((sec/2)&0x1f);
+}
+
+static INLINE Bit16u DOS_PackDate(Bit16u year,Bit16u mon,Bit16u day) {
+       return ((year-1980)&0x7f)<<9 | (mon&0x3f) << 5 | (day&0x1f);
+}
+
+/* Dos Error Codes */
+#define DOSERR_NONE 0
+#define DOSERR_FUNCTION_NUMBER_INVALID 1
+#define DOSERR_FILE_NOT_FOUND 2
+#define DOSERR_PATH_NOT_FOUND 3
+#define DOSERR_TOO_MANY_OPEN_FILES 4
+#define DOSERR_ACCESS_DENIED 5
+#define DOSERR_INVALID_HANDLE 6
+#define DOSERR_MCB_DESTROYED 7
+#define DOSERR_INSUFFICIENT_MEMORY 8
+#define DOSERR_MB_ADDRESS_INVALID 9
+#define DOSERR_ENVIRONMENT_INVALID 10
+#define DOSERR_FORMAT_INVALID 11
+#define DOSERR_ACCESS_CODE_INVALID 12
+#define DOSERR_DATA_INVALID 13
+#define DOSERR_RESERVED 14
+#define DOSERR_FIXUP_OVERFLOW 14
+#define DOSERR_INVALID_DRIVE 15
+#define DOSERR_REMOVE_CURRENT_DIRECTORY 16
+#define DOSERR_NOT_SAME_DEVICE 17
+#define DOSERR_NO_MORE_FILES 18
+#define DOSERR_WRITE_PROTECTED_DISK 19
+#define DOSERR_FILE_ALREADY_EXISTS 80
+
+
+/* Remains some classes used to access certain things */
+#define sOffset(s,m) ((char*)&(((s*)NULL)->m)-(char*)NULL)
+#define sGet(s,m) GetIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m))
+#define sSave(s,m,val) SaveIt(sizeof(((s *)&pt)->m),(PhysPt)sOffset(s,m),val)
+
+class MemStruct {
+public:
+       Bitu GetIt(Bitu size,PhysPt addr) {
+               switch (size) {
+               case 1:return mem_readb(pt+addr);
+               case 2:return mem_readw(pt+addr);
+               case 4:return mem_readd(pt+addr);
+               }
+               return 0;
+       }
+       void SaveIt(Bitu size,PhysPt addr,Bitu val) {
+               switch (size) {
+               case 1:mem_writeb(pt+addr,(Bit8u)val);break;
+               case 2:mem_writew(pt+addr,(Bit16u)val);break;
+               case 4:mem_writed(pt+addr,(Bit32u)val);break;
+               }
+       }
+       void SetPt(Bit16u seg) { pt=PhysMake(seg,0);}
+       void SetPt(Bit16u seg,Bit16u off) { pt=PhysMake(seg,off);}
+       void SetPt(RealPt addr) { pt=Real2Phys(addr);}
+protected:
+       PhysPt pt;
+};
+
+class DOS_PSP :public MemStruct {
+public:
+       DOS_PSP                                         (Bit16u segment)                { SetPt(segment);seg=segment;};
+       void    MakeNew                         (Bit16u memSize);
+       void    CopyFileTable           (DOS_PSP* srcpsp,bool createchildpsp);
+       Bit16u  FindFreeFileEntry       (void);
+       void    CloseFiles                      (void);
+
+       void    SaveVectors                     (void);
+       void    RestoreVectors          (void);
+       void    SetSize                         (Bit16u size)                   { sSave(sPSP,next_seg,size);            };
+       Bit16u  GetSize                         (void)                                  { return (Bit16u)sGet(sPSP,next_seg);           };
+       void    SetEnvironment          (Bit16u envseg)                 { sSave(sPSP,environment,envseg);       };
+       Bit16u  GetEnvironment          (void)                                  { return (Bit16u)sGet(sPSP,environment);        };
+       Bit16u  GetSegment                      (void)                                  { return seg;                                           };
+       void    SetFileHandle           (Bit16u index, Bit8u handle);
+       Bit8u   GetFileHandle           (Bit16u index);
+       void    SetParent                       (Bit16u parent)                 { sSave(sPSP,psp_parent,parent);        };
+       Bit16u  GetParent                       (void)                                  { return (Bit16u)sGet(sPSP,psp_parent);         };
+       void    SetStack                        (RealPt stackpt)                { sSave(sPSP,stack,stackpt);            };
+       RealPt  GetStack                        (void)                                  { return sGet(sPSP,stack);                      };
+       void    SetInt22                        (RealPt int22pt)                { sSave(sPSP,int_22,int22pt);           };
+       RealPt  GetInt22                        (void)                                  { return sGet(sPSP,int_22);                     };
+       void    SetFCB1                         (RealPt src);
+       void    SetFCB2                         (RealPt src);
+       void    SetCommandTail          (RealPt src);   
+       void    StoreCommandTail    (void);
+       void    RestoreCommandTail  (void);
+       bool    SetNumFiles                     (Bit16u fileNum);
+       Bit16u  FindEntryByHandle       (Bit8u handle);
+                       
+private:
+       #ifdef _MSC_VER
+       #pragma pack(1)
+       #endif
+       struct sPSP {
+               Bit8u   exit[2];                        /* CP/M-like exit poimt */
+               Bit16u  next_seg;                       /* Segment of first byte beyond memory allocated or program */
+               Bit8u   fill_1;                         /* single char fill */
+               Bit8u   far_call;                       /* far call opcode */
+               RealPt  cpm_entry;                      /* CPM Service Request address*/
+               RealPt  int_22;                         /* Terminate Address */
+               RealPt  int_23;                         /* Break Address */
+               RealPt  int_24;                         /* Critical Error Address */
+               Bit16u  psp_parent;                     /* Parent PSP Segment */
+               Bit8u   files[20];                      /* File Table - 0xff is unused */
+               Bit16u  environment;            /* Segment of evironment table */
+               RealPt  stack;                          /* SS:SP Save point for int 0x21 calls */
+               Bit16u  max_files;                      /* Maximum open files */
+               RealPt  file_table;                     /* Pointer to File Table PSP:0x18 */
+               RealPt  prev_psp;                       /* Pointer to previous PSP */
+               Bit8u interim_flag;
+               Bit8u truename_flag;
+               Bit16u nn_flags;
+               Bit16u dos_version;
+               Bit8u   fill_2[14];                     /* Lot's of unused stuff i can't care aboue */
+               Bit8u   service[3];                     /* INT 0x21 Service call int 0x21;retf; */
+               Bit8u   fill_3[9];                      /* This has some blocks with FCB info */
+               Bit8u   fcb1[16];                       /* first FCB */
+               Bit8u   fcb2[16];                       /* second FCB */
+               Bit8u   fill_4[4];                      /* unused */
+               CommandTail cmdtail;            
+       } GCC_ATTRIBUTE(packed);
+       #ifdef _MSC_VER
+       #pragma pack()
+       #endif
+       Bit16u  seg;
+public:
+       static  Bit16u rootpsp;
+};
+
+class DOS_ParamBlock:public MemStruct {
+public:
+       DOS_ParamBlock(PhysPt addr) {pt=addr;}
+       void Clear(void);
+       void LoadData(void);
+       void SaveData(void);            /* Save it as an exec block */
+       #ifdef _MSC_VER
+       #pragma pack (1)
+       #endif
+       struct sOverlay {
+               Bit16u loadseg;
+               Bit16u relocation;
+       } GCC_ATTRIBUTE(packed);
+       struct sExec {
+               Bit16u envseg;
+               RealPt cmdtail;
+               RealPt fcb1;
+               RealPt fcb2;
+               RealPt initsssp;
+               RealPt initcsip;
+       }GCC_ATTRIBUTE(packed);
+       #ifdef _MSC_VER
+       #pragma pack()
+       #endif
+       sExec exec;
+       sOverlay overlay;
+};
+
+class DOS_InfoBlock:public MemStruct {
+public:
+       DOS_InfoBlock                   () {};
+       void SetLocation(Bit16u  seg);
+       void SetFirstMCB(Bit16u _first_mcb);
+       void SetBuffers(Bit16u x,Bit16u y);
+       void SetCurDirStruct(Bit32u _curdirstruct);
+       void SetFCBTable(Bit32u _fcbtable);
+       void SetDeviceChainStart(Bit32u _devchain);
+       void SetDiskBufferHeadPt(Bit32u _dbheadpt);
+       void SetStartOfUMBChain(Bit16u _umbstartseg);
+       void SetUMBChainState(Bit8u _umbchaining);
+       Bit16u  GetStartOfUMBChain(void);
+       Bit8u   GetUMBChainState(void);
+       RealPt  GetPointer(void);
+       Bit32u GetDeviceChain(void);
+
+       #ifdef _MSC_VER
+       #pragma pack(1)
+       #endif
+       struct sDIB {           
+               Bit8u   unknown1[4];
+               Bit16u  magicWord;                      // -0x22 needs to be 1
+               Bit8u   unknown2[8];
+               Bit16u  regCXfrom5e;            // -0x18 CX from last int21/ah=5e
+               Bit16u  countLRUcache;          // -0x16 LRU counter for FCB caching
+               Bit16u  countLRUopens;          // -0x14 LRU counter for FCB openings
+               Bit8u   stuff[6];               // -0x12 some stuff, hopefully never used....
+               Bit16u  sharingCount;           // -0x0c sharing retry count
+               Bit16u  sharingDelay;           // -0x0a sharing retry delay
+               RealPt  diskBufPtr;             // -0x08 pointer to disk buffer
+               Bit16u  ptrCONinput;            // -0x04 pointer to con input
+               Bit16u  firstMCB;               // -0x02 first memory control block
+               RealPt  firstDPB;               //  0x00 first drive parameter block
+               RealPt  firstFileTable;         //  0x04 first system file table
+               RealPt  activeClock;            //  0x08 active clock device header
+               RealPt  activeCon;              //  0x0c active console device header
+               Bit16u  maxSectorLength;        //  0x10 maximum bytes per sector of any block device;
+               RealPt  diskInfoBuffer;         //  0x12 pointer to disk info buffer
+               RealPt  curDirStructure;        //  0x16 pointer to current array of directory structure
+               RealPt  fcbTable;               //  0x1a pointer to system FCB table
+               Bit16u  protFCBs;               //  0x1e protected fcbs
+               Bit8u   blockDevices;           //  0x20 installed block devices
+               Bit8u   lastdrive;              //  0x21 lastdrive
+               Bit32u  nulNextDriver;  //  0x22 NUL driver next pointer
+               Bit16u  nulAttributes;  //  0x26 NUL driver aattributes
+               Bit32u  nulStrategy;    //  0x28 NUL driver strategy routine
+               Bit8u   nulString[8];   //  0x2c NUL driver name string
+               Bit8u   joindedDrives;          //  0x34 joined drives
+               Bit16u  specialCodeSeg;         //  0x35 special code segment
+               RealPt  setverPtr;              //  0x37 pointer to setver
+               Bit16u  a20FixOfs;              //  0x3b a20 fix routine offset
+               Bit16u  pspLastIfHMA;           //  0x3d psp of last program (if dos in hma)
+               Bit16u  buffers_x;              //  0x3f x in BUFFERS x,y
+               Bit16u  buffers_y;              //  0x41 y in BUFFERS x,y
+               Bit8u   bootDrive;              //  0x43 boot drive
+               Bit8u   useDwordMov;            //  0x44 use dword moves
+               Bit16u  extendedSize;           //  0x45 size of extended memory
+               Bit32u  diskBufferHeadPt;       //  0x47 pointer to least-recently used buffer header
+               Bit16u  dirtyDiskBuffers;       //  0x4b number of dirty disk buffers
+               Bit32u  lookaheadBufPt;         //  0x4d pointer to lookahead buffer
+               Bit16u  lookaheadBufNumber;             //  0x51 number of lookahead buffers
+               Bit8u   bufferLocation;                 //  0x53 workspace buffer location
+               Bit32u  workspaceBuffer;                //  0x54 pointer to workspace buffer
+               Bit8u   unknown3[11];                   //  0x58
+               Bit8u   chainingUMB;                    //  0x63 bit0: UMB chain linked to MCB chain
+               Bit16u  minMemForExec;                  //  0x64 minimum paragraphs needed for current program
+               Bit16u  startOfUMBChain;                //  0x66 segment of first UMB-MCB
+               Bit16u  memAllocScanStart;              //  0x68 start paragraph for memory allocation
+       } GCC_ATTRIBUTE(packed);
+       #ifdef _MSC_VER
+       #pragma pack ()
+       #endif
+       Bit16u  seg;
+};
+
+class DOS_DTA:public MemStruct{
+public:
+       DOS_DTA(RealPt addr) { SetPt(addr); }
+
+       void SetupSearch(Bit8u _sdrive,Bit8u _sattr,char * _pattern);
+       void SetResult(const char * _name,const char * _lname,Bit32u _size,Bit16u _date,Bit16u _time,Bit8u _attr);
+       
+       int GetFindData(int fmt,char * finddata);
+       Bit8u GetSearchDrive(void);
+       void GetSearchParams(Bit8u & _sattr,char * _spattern,bool lfn);
+       void GetResult(char * _name,char * _lname,Bit32u & _size,Bit16u & _date,Bit16u & _time,Bit8u & _attr);
+
+       void    SetDirID(Bit16u entry)                  { sSave(sDTA,dirID,entry); };
+       void    SetDirIDCluster(Bit16u entry)   { sSave(sDTA,dirCluster,entry); };
+       Bit16u  GetDirID(void)                          { return (Bit16u)sGet(sDTA,dirID); };
+       Bit16u  GetDirIDCluster(void)           { return (Bit16u)sGet(sDTA,dirCluster); };
+private:
+       #ifdef _MSC_VER
+       #pragma pack(1)
+       #endif
+       struct sDTA {
+               Bit8u sdrive;                                           /* The Drive the search is taking place */
+               Bit8u spname[8];                                        /* The Search pattern for the filename */               
+               Bit8u spext[3];                                         /* The Search pattern for the extenstion */
+               Bit8u sattr;                                            /* The Attributes that need to be found */
+               Bit16u dirID;                                           /* custom: dir-search ID for multiple searches at the same time */
+               Bit16u dirCluster;                                      /* custom (drive_fat only): cluster number for multiple searches at the same time */
+               Bit8u fill[4];
+               Bit8u attr;
+               Bit16u time;
+               Bit16u date;
+               Bit32u size;
+               char name[DOS_NAMELENGTH_ASCII];
+       } GCC_ATTRIBUTE(packed);
+       #ifdef _MSC_VER
+       #pragma pack()
+       #endif
+};
+
+class DOS_FCB: public MemStruct {
+public:
+       DOS_FCB(Bit16u seg,Bit16u off,bool allow_extended=true);
+       void Create(bool _extended);
+       void SetName(Bit8u _drive,char * _fname,char * _ext);
+       void SetSizeDateTime(Bit32u _size, Bit16u _date, Bit16u _time, bool byFindFCB = false);
+       void GetSizeDateTime(Bit32u & _size,Bit16u & _date,Bit16u & _time);
+       void GetName(char * fillname);
+       void FileOpen(Bit8u _fhandle);
+       void FileClose(Bit8u & _fhandle);
+       void GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec);
+       void SetRecord(Bit16u _cur_block,Bit8u _cur_rec);
+       void GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size);
+       void SetSeqData(Bit8u _fhandle,Bit16u _rec_size);
+       void GetRandom(Bit32u & _random);
+       void SetRandom(Bit32u  _random);
+       Bit8u GetDrive(void);
+       bool Extended(void);
+       void GetAttr(Bit8u & attr);
+       void SetAttr(Bit8u attr, bool byFindFCB = false);
+       void SetResult(Bit32u size,Bit16u date,Bit16u time,Bit8u attr);
+       bool Valid(void);
+       void ClearBlockRecsize(void);
+private:
+       bool extended;
+       PhysPt real_pt;
+       #ifdef _MSC_VER
+       #pragma pack (1)
+       #endif
+       struct sFCB {
+               Bit8u drive;                    /* Drive number 0=default, 1=A, etc */
+               Bit8u filename[8];              /* Space padded name */
+               Bit8u ext[3];                   /* Space padded extension */
+               Bit16u cur_block;               /* Current Block */
+               Bit16u rec_size;                /* Logical record size */
+               Bit32u filesize;                /* File Size */
+               Bit16u date;
+               Bit16u time;
+               /* Reserved Block should be 8 bytes */
+               Bit8u sft_entries;
+               Bit8u share_attributes;
+               Bit8u extra_info;
+               /* Maybe swap file_handle and sft_entries now that fcbs 
+                * aren't stored in the psp filetable anymore */
+               Bit8u file_handle;
+               Bit8u reserved[4];
+               /* end */
+               Bit8u  cur_rec;                 /* Current record in current block */
+               Bit32u rndm;                    /* Current relative record number */
+       } GCC_ATTRIBUTE(packed);
+       #ifdef _MSC_VER
+       #pragma pack ()
+       #endif
+};
+
+class DOS_MCB : public MemStruct{
+public:
+       DOS_MCB(Bit16u seg) { SetPt(seg); }
+       void SetFileName(char const * const _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); }
+       void GetFileName(char * const _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;}
+       void SetType(Bit8u _type) { sSave(sMCB,type,_type);}
+       void SetSize(Bit16u _size) { sSave(sMCB,size,_size);}
+       void SetPSPSeg(Bit16u _pspseg) { sSave(sMCB,psp_segment,_pspseg);}
+       Bit8u GetType(void) { return (Bit8u)sGet(sMCB,type);}
+       Bit16u GetSize(void) { return (Bit16u)sGet(sMCB,size);}
+       Bit16u GetPSPSeg(void) { return (Bit16u)sGet(sMCB,psp_segment);}
+private:
+       #ifdef _MSC_VER
+       #pragma pack (1)
+       #endif
+       struct sMCB {
+               Bit8u type;
+               Bit16u psp_segment;
+               Bit16u size;    
+               Bit8u unused[3];
+               Bit8u filename[8];
+       } GCC_ATTRIBUTE(packed);
+       #ifdef _MSC_VER
+       #pragma pack ()
+       #endif
+};
+
+class DOS_SDA : public MemStruct {
+public:
+       DOS_SDA(Bit16u _seg,Bit16u _offs) { SetPt(_seg,_offs); }
+       void Init();   
+       void SetDrive(Bit8u _drive) { sSave(sSDA,current_drive, _drive); }
+       void SetDTA(Bit32u _dta) { sSave(sSDA,current_dta, _dta); }
+       void SetPSP(Bit16u _psp) { sSave(sSDA,current_psp, _psp); }
+       Bit8u GetDrive(void) { return (Bit8u)sGet(sSDA,current_drive); }
+       Bit16u GetPSP(void) { return (Bit16u)sGet(sSDA,current_psp); }
+       Bit32u GetDTA(void) { return (Bit32u)sGet(sSDA,current_dta); }
+       
+       
+private:
+       #ifdef _MSC_VER
+       #pragma pack (1)
+       #endif
+       struct sSDA {
+               Bit8u crit_error_flag;          /* 0x00 Critical Error Flag */
+               Bit8u inDOS_flag;               /* 0x01 InDOS flag (count of active INT 21 calls) */
+               Bit8u drive_crit_error;         /* 0x02 Drive on which current critical error occurred or FFh */
+               Bit8u locus_of_last_error;      /* 0x03 locus of last error */
+               Bit16u extended_error_code;     /* 0x04 extended error code of last error */
+               Bit8u suggested_action;         /* 0x06 suggested action for last error */
+               Bit8u error_class;              /* 0x07 class of last error*/
+               Bit32u last_error_pointer;      /* 0x08 ES:DI pointer for last error */
+               Bit32u current_dta;             /* 0x0C current DTA (Disk Transfer Address) */
+               Bit16u current_psp;             /* 0x10 current PSP */
+               Bit16u sp_int_23;               /* 0x12 stores SP across an INT 23 */
+               Bit16u return_code;             /* 0x14 return code from last process termination (zerod after reading with AH=4Dh) */
+               Bit8u current_drive;            /* 0x16 current drive */
+               Bit8u extended_break_flag;      /* 0x17 extended break flag */
+               Bit8u fill[2];                  /* 0x18 flag: code page switching || flag: copy of previous byte in case of INT 24 Abort*/
+       } GCC_ATTRIBUTE(packed);
+       #ifdef _MSC_VER
+       #pragma pack()
+       #endif
+};
+extern DOS_InfoBlock dos_infoblock;
+
+struct DOS_Block {
+       DOS_Date date;
+       DOS_Version version;
+       Bit16u firstMCB;
+       Bit16u errorcode;
+       Bit16u psp(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetPSP();};
+       void psp(Bit16u _seg){ DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetPSP(_seg);};
+       Bit16u env;
+       RealPt cpmentry;
+       RealPt dta(){return DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).GetDTA();};
+       void dta(RealPt _dta){DOS_SDA(DOS_SDA_SEG,DOS_SDA_OFS).SetDTA(_dta);};
+       Bit8u return_code,return_mode;
+       
+       Bit8u current_drive;
+       bool verify;
+       bool breakcheck;
+       bool echo;          // if set to true dev_con::read will echo input 
+       bool direct_output;
+       struct  {
+               RealPt mediaid;
+               RealPt tempdta;
+               RealPt tempdta_fcbdelete;
+               RealPt dbcs;
+               RealPt filenamechar;
+               RealPt collatingseq;
+               RealPt upcase;
+               //Bit8u* country;//Will be copied to dos memory. resides in real mem
+               Bit16u dpb; //Fake Disk parameter system using only the first entry so the drive letter matches
+               Bit16u country_seg;
+       } tables;
+       Bit16u loaded_codepage;
+
+       //for AX
+       bool set_ax_enabled;
+
+       bool set_dosv_enabled;
+};
+
+extern DOS_Block dos;
+
+static INLINE Bit8u RealHandle(Bit16u handle) {
+       DOS_PSP psp(dos.psp()); 
+       return psp.GetFileHandle(handle);
+}
+
+#define IS_DOS_JAPANESE                (real_readw(dos.tables.country_seg,5) == 932 && mem_readb(Real2Phys(dos.tables.dbcs) + 0x02) == 0x81)
+#define IS_DOSV                                (dos.set_dosv_enabled)
+
+#define        AUTORELOAD_CMD          0x01
+#define        AUTORELOAD_DOS          0x02
+#define        AUTORELOAD_ALL          0x03
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/dos_system.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/dos_system.h
new file mode 100644 (file)
index 0000000..1c2709f
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ *  Copyright (C) 2002-2017  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Wengier: LFN support
+ */
+
+
+#ifndef DOSBOX_DOS_SYSTEM_H
+#define DOSBOX_DOS_SYSTEM_H
+
+#include <vector>
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+#ifndef DOSBOX_CROSS_H
+#include "cross.h"
+#endif
+#ifndef DOSBOX_SUPPORT_H
+#include "support.h"
+#endif
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+
+#define DOS_NAMELENGTH 12
+#define DOS_NAMELENGTH_ASCII (DOS_NAMELENGTH+1)
+#define LFN_NAMELENGTH 255
+#define DOS_FCBNAME 15
+#define DOS_DIRDEPTH 8
+#define DOS_PATHLENGTH 255
+#define DOS_TEMPSIZE 1024
+
+enum {
+       DOS_ATTR_READ_ONLY=     0x01,
+       DOS_ATTR_HIDDEN=        0x02,
+       DOS_ATTR_SYSTEM=        0x04,
+       DOS_ATTR_VOLUME=        0x08,
+       DOS_ATTR_DIRECTORY=     0x10,
+       DOS_ATTR_ARCHIVE=       0x20,
+       DOS_ATTR_DEVICE=        0x40
+};
+
+struct FileStat_Block {
+       Bit32u size;
+       Bit16u time;
+       Bit16u date;
+       Bit16u attr;
+};
+
+class DOS_DTA;
+
+class DOS_File {
+public:
+       DOS_File():flags(0)             { name=0; refCtr = 0; hdrive=0xff; };
+       DOS_File(const DOS_File& orig);
+       DOS_File & operator= (const DOS_File & orig);
+       virtual ~DOS_File(){if(name) delete [] name;};
+       virtual bool    Read(Bit8u * data,Bit16u * size)=0;
+       virtual bool    Write(Bit8u * data,Bit16u * size)=0;
+       virtual bool    Seek(Bit32u * pos,Bit32u type)=0;
+       virtual bool    Close()=0;
+       virtual Bit16u  GetInformation(void)=0;
+       virtual void    SetName(const char* _name)      { if (name) delete[] name; name = new char[strlen(_name)+1]; strcpy(name,_name); }
+       virtual char*   GetName(void)                           { return name; };
+       virtual bool    IsOpen()                                        { return open; };
+       virtual bool    IsName(const char* _name)       { if (!name) return false; return strcasecmp(name,_name)==0; };
+       virtual void    AddRef()                                        { refCtr++; };
+       virtual Bits    RemoveRef()                                     { return --refCtr; };
+       virtual bool    UpdateDateTimeFromHost()        { return true; }
+       void SetDrive(Bit8u drv) { hdrive=drv;}
+       Bit8u GetDrive(void) { return hdrive;}
+       Bit32u flags;
+       Bit16u time;
+       Bit16u date;
+       Bit16u attr;
+       Bits refCtr;
+       bool open;
+       char* name;
+/* Some Device Specific Stuff */
+private:
+       Bit8u hdrive;
+};
+
+class DOS_Device : public DOS_File {
+public:
+       DOS_Device(const DOS_Device& orig):DOS_File(orig) {
+               devnum=orig.devnum;
+               open=true;
+       }
+       DOS_Device & operator= (const DOS_Device & orig) {
+               DOS_File::operator=(orig);
+               devnum=orig.devnum;
+               open=true;
+               return *this;
+       }
+       DOS_Device():DOS_File(),devnum(0){};
+       virtual bool    Read(Bit8u * data,Bit16u * size);
+       virtual bool    Write(Bit8u * data,Bit16u * size);
+       virtual bool    Seek(Bit32u * pos,Bit32u type);
+       virtual bool    Close();
+       virtual Bit16u  GetInformation(void);
+       virtual bool    ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode);
+       virtual bool    WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode);
+       void SetDeviceNumber(Bitu num) { devnum=num;}
+private:
+       Bitu devnum;
+};
+
+/* The following variable can be lowered to free up some memory.
+ * The negative side effect: The stored searches will be turned over faster.
+ * Should not have impact on systems with few directory entries. */
+#define MAX_OPENDIRS 2048
+//Can be high as it's only storage (16 bit variable)
+
+class DOS_Drive_Cache {
+public:
+       DOS_Drive_Cache                                 (void);
+       DOS_Drive_Cache                                 (const char* path);
+       ~DOS_Drive_Cache                                (void);
+
+       enum TDirSort { NOSORT, ALPHABETICAL, DIRALPHABETICAL, ALPHABETICALREV, DIRALPHABETICALREV };
+
+       void            SetBaseDir                      (const char* path);
+       void            SetDirSort                      (TDirSort sort) { sortDirType = sort; };
+       bool            OpenDir                         (const char* path, Bit16u& id);
+       bool            ReadDir                         (Bit16u id, char* &result, char * &lresult);
+
+       void            ExpandName                      (char* path);
+       char*           GetExpandName           (const char* path);
+       bool            GetShortName            (const char* fullname, char* shortname);
+
+       bool            FindFirst                       (char* path, Bit16u& id);
+       bool            FindNext                        (Bit16u id, char* &result, char* &lresult);
+
+       void            CacheOut                        (const char* path, bool ignoreLastDir = false);
+       void            AddEntry                        (const char* path, bool checkExist = false);
+       void            DeleteEntry                     (const char* path, bool ignoreLastDir = false);
+
+       void            EmptyCache                      (void);
+       void            SetLabel                        (const char* name,bool cdrom,bool allowupdate);
+       char*           GetLabel                        (void) { return label; };
+
+       class CFileInfo {
+       public:
+               CFileInfo(void) {
+                       orgname[0] = shortname[0] = 0;
+                       isDir = false;
+                       id = MAX_OPENDIRS;
+                       nextEntry = shortNr = 0;
+               }
+               ~CFileInfo(void) {
+                       for (Bit32u i=0; i<fileList.size(); i++) delete fileList[i];
+                       fileList.clear();
+                       longNameList.clear();
+               };
+               char            orgname         [CROSS_LEN];
+               char            shortname       [DOS_NAMELENGTH_ASCII+16];
+               bool            isDir;
+               Bit16u          id;
+               Bitu            nextEntry;
+               Bitu            shortNr;
+               // contents
+               std::vector<CFileInfo*> fileList;
+               std::vector<CFileInfo*> longNameList;
+       };
+
+private:
+       void ClearFileInfo(CFileInfo *dir);
+       void DeleteFileInfo(CFileInfo *dir);
+
+       bool            RemoveTrailingDot       (char* shortname);
+       Bits            GetLongName             (CFileInfo* info, char* shortname);
+       void            CreateShortName         (CFileInfo* dir, CFileInfo* info);
+       Bitu            CreateShortNameID       (CFileInfo* dir, const char* name);
+       int             CompareShortname        (const char* compareName, const char* shortName);
+       bool            SetResult               (CFileInfo* dir, char * &result, char * &lresult, Bitu entryNr);
+       bool            IsCachedIn              (CFileInfo* dir);
+       CFileInfo*      FindDirInfo             (const char* path, char* expandedPath);
+       bool            RemoveSpaces            (char* str);
+       bool            OpenDir                 (CFileInfo* dir, const char* path, Bit16u& id);
+       void            CreateEntry             (CFileInfo* dir, const char* name, const char* sname, bool query_directory);
+       void            CopyEntry               (CFileInfo* dir, CFileInfo* from);
+       Bit16u          GetFreeID               (CFileInfo* dir);
+       void            Clear                   (void);
+
+       CFileInfo*      dirBase;
+       char            dirPath                         [CROSS_LEN];
+       char            basePath                        [CROSS_LEN];
+       bool            dirFirstTime;
+       TDirSort        sortDirType;
+       CFileInfo*      save_dir;
+       char            save_path                       [CROSS_LEN];
+       char            save_expanded           [CROSS_LEN];
+
+       Bit16u          srchNr;
+       CFileInfo*      dirSearch                       [MAX_OPENDIRS];
+       char            dirSearchName           [MAX_OPENDIRS];
+       CFileInfo*      dirFindFirst            [MAX_OPENDIRS];
+       Bit16u          nextFreeFindFirst;
+
+       char            label                           [CROSS_LEN];
+       bool            updatelabel;
+};
+
+class DOS_Drive {
+public:
+       DOS_Drive();
+       virtual ~DOS_Drive(){};
+       virtual bool FileOpen(DOS_File * * file,char * name,Bit32u flags)=0;
+       virtual bool FileCreate(DOS_File * * file,char * name,Bit16u attributes)=0;
+       virtual bool FileUnlink(char * _name)=0;
+       virtual bool RemoveDir(char * _dir)=0;
+       virtual bool MakeDir(char * _dir)=0;
+       virtual bool TestDir(char * _dir)=0;
+       virtual bool FindFirst(char * _dir,DOS_DTA & dta,bool fcb_findfirst=false)=0;
+       virtual bool FindNext(DOS_DTA & dta)=0;
+       virtual bool GetFileAttr(char * name,Bit16u * attr)=0;
+       virtual bool GetFileAttrEx(char* name, struct stat *status)=0;
+       virtual DWORD GetCompressedSize(char* name)=0;
+       virtual HANDLE CreateOpenFile(char const* const name)=0;
+       virtual bool Rename(char * oldname,char * newname)=0;
+       virtual bool AllocationInfo(Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters,Bit16u * _free_clusters)=0;
+       virtual bool FileExists(const char* name)=0;
+       virtual bool FileStat(const char* name, FileStat_Block * const stat_block)=0;
+       virtual Bit8u GetMediaByte(void)=0;
+       virtual void SetDir(const char* path) { strcpy(curdir,path); };
+       virtual void EmptyCache(void) { dirCache.EmptyCache(); };
+       virtual bool isRemote(void)=0;
+       virtual bool isRemovable(void)=0;
+       virtual bool isWriteProtected(void) = 0;
+       virtual Bits UnMount(void)=0;
+
+       char * GetInfo(void);
+       char curdir[DOS_PATHLENGTH];
+       char info[256];
+       /* Can be overridden for example in iso images */
+       virtual char const * GetLabel(){return dirCache.GetLabel();};
+
+       DOS_Drive_Cache dirCache;
+
+       // disk cycling functionality (request resources)
+       virtual void Activate(void) {};
+};
+
+enum { OPEN_READ=0, OPEN_WRITE=1, OPEN_READWRITE=2, OPEN_READ_NO_MOD=4, DOS_NOT_INHERIT=128};
+enum { DOS_SEEK_SET=0,DOS_SEEK_CUR=1,DOS_SEEK_END=2};
+
+
+/*
+ A multiplex handler should read the registers to check what function is being called
+ If the handler returns false dos will stop checking other handlers
+*/
+
+typedef bool (MultiplexHandler)(void);
+void DOS_AddMultiplexHandler(MultiplexHandler * handler);
+void DOS_DelMultiplexHandler(MultiplexHandler * handler);
+
+/* AddDevice stores the pointer to a created device */
+void DOS_AddDevice(DOS_Device * adddev);
+/* DelDevice destroys the device that is pointed to. */
+void DOS_DelDevice(DOS_Device * dev);
+
+void VFILE_Register(const char * name,Bit8u * data,Bit32u size);
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/dosbox.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/dosbox.h
new file mode 100644 (file)
index 0000000..c2e20a6
--- /dev/null
@@ -0,0 +1,92 @@
+/*\r
+ *  Copyright (C) 2002-2017  The DOSBox Team\r
+ *  Copyright (C) 2016 akm\r
+ *  Copyright (C) 2019 takapyu\r
+ *\r
+ *  This program is free software; you can redistribute it and/or modify\r
+ *  it under the terms of the GNU General Public License as published by\r
+ *  the Free Software Foundation; either version 2 of the License, or\r
+ *  (at your option) any later version.\r
+ *\r
+ *  This program is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *  GNU General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU General Public License\r
+ *  along with this program; if not, write to the Free Software\r
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+ */\r
+\r
+\r
+#ifndef DOSBOX_DOSBOX_H\r
+#define DOSBOX_DOSBOX_H\r
+\r
+#include "config.h"\r
+\r
+#define        BUILD_VERSION   "JP190520"\r
+#ifndef VERSION\r
+#define VERSION BUILD_VERSION\r
+#endif\r
+\r
+GCC_ATTRIBUTE(noreturn) void E_Exit(const char * message,...) GCC_ATTRIBUTE( __format__(__printf__, 1, 2));\r
+\r
+void MSG_Add(const char*,const char*); //add messages to the internal languagefile\r
+const char* MSG_Get(char const *);     //get messages from the internal languagefile\r
+\r
+class Section;\r
+\r
+typedef Bitu (LoopHandler)(void);\r
+\r
+void DOSBOX_RunMachine();\r
+void DOSBOX_SetLoop(LoopHandler * handler);\r
+void DOSBOX_SetNormalLoop();\r
+\r
+void DOSBOX_Init(void);\r
+\r
+class Config;\r
+extern Config * control;\r
+\r
+enum MachineType {\r
+       MCH_HERC,\r
+       MCH_CGA,\r
+       MCH_TANDY,\r
+       MCH_PCJR,\r
+       MCH_EGA,\r
+       MCH_DCGA,\r
+       MCH_VGA\r
+};\r
+\r
+enum SVGACards {\r
+       SVGA_None,\r
+       SVGA_S3Trio,\r
+       SVGA_TsengET4K,\r
+       SVGA_TsengET3K,\r
+       SVGA_ParadisePVGA1A\r
+}; \r
+\r
+extern SVGACards svgaCard;\r
+extern MachineType machine;\r
+extern bool SDLNetInited, uselfn, autolfn;;\r
+\r
+#define IS_TANDY_ARCH ((machine==MCH_TANDY) || (machine==MCH_PCJR))\r
+#define IS_EGAVGA_ARCH ((machine==MCH_EGA) || (machine==MCH_VGA))\r
+#define IS_VGA_ARCH ((machine==MCH_VGA))\r
+#define TANDY_ARCH_CASE MCH_TANDY: case MCH_PCJR\r
+#define EGAVGA_ARCH_CASE MCH_EGA: case MCH_VGA\r
+#define VGA_ARCH_CASE MCH_VGA\r
+#define IS_AX_ARCH (machine==MCH_EGA)// upper compatible with EGA\r
+//#define IS_AX_ARCH (machine==MCH_AX)\r
+#define IS_J3_ARCH (machine==MCH_DCGA)\r
+\r
+#ifndef DOSBOX_LOGGING_H\r
+#include "logging.h"\r
+#endif // the logging system.\r
+\r
+#if !defined (WIN32)\r
+       typedef unsigned int DWORD;\r
+       typedef   signed int HANDLE;\r
+#define INVALID_HANDLE_VALUE -1\r
+#endif\r
+\r
+#endif /* DOSBOX_DOSBOX_H */\r
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/dosv.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/dosv.h
new file mode 100644 (file)
index 0000000..0884f3e
--- /dev/null
@@ -0,0 +1,38 @@
+\r
+#ifndef DOSBOX_DOSV\r
+#define DOSBOX_DOSV\r
+\r
+#include "setup.h"\r
+\r
+enum DOSV_VTEXT_MODE {\r
+       DOSV_VGA,                               // 80x25\r
+       DOSV_VTEXT_VGA,                 // 80x30\r
+       DOSV_VTEXT_SVGA,                // 100x37\r
+       DOSV_VTEXT_XGA,                 // 128x48\r
+       DOSV_VTEXT_XGA_24,              // 85x32\r
+       DOSV_VTEXT_SXGA,                // 160x64\r
+       DOSV_VTEXT_SXGA_24,             // 106x42\r
+};\r
+\r
+enum DOSV_FONT {\r
+       DOSV_FONT_8X16,\r
+       DOSV_FONT_8X19,\r
+       DOSV_FONT_16X16,\r
+       DOSV_FONT_12X24,\r
+       DOSV_FONT_24X24,\r
+\r
+       DOSV_FONT_16X16_WRITE,\r
+       DOSV_FONT_24X24_WRITE,\r
+\r
+       DOSV_FONT_MAX\r
+};\r
+\r
+bool INT10_DOSV_SetCRTBIOSMode(Bitu mode);\r
+void DOSV_SetConfig(Section_prop *section);\r
+void DOSV_Setup();\r
+void DOSV_OffCursor();\r
+void INT8_DOSV();\r
+Bit16u DOSV_GetFontHandlerOffset(enum DOSV_FONT font);\r
+enum DOSV_VTEXT_MODE DOSV_GetVtextMode(Bitu no = 0);\r
+\r
+#endif\r
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/fpu.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/fpu.h
new file mode 100644 (file)
index 0000000..67e1021
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_FPU_H
+#define DOSBOX_FPU_H
+
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+
+void FPU_ESC0_Normal(Bitu rm);
+void FPU_ESC0_EA(Bitu func,PhysPt ea);
+void FPU_ESC1_Normal(Bitu rm);
+void FPU_ESC1_EA(Bitu func,PhysPt ea);
+void FPU_ESC2_Normal(Bitu rm);
+void FPU_ESC2_EA(Bitu func,PhysPt ea);
+void FPU_ESC3_Normal(Bitu rm);
+void FPU_ESC3_EA(Bitu func,PhysPt ea);
+void FPU_ESC4_Normal(Bitu rm);
+void FPU_ESC4_EA(Bitu func,PhysPt ea);
+void FPU_ESC5_Normal(Bitu rm);
+void FPU_ESC5_EA(Bitu func,PhysPt ea);
+void FPU_ESC6_Normal(Bitu rm);
+void FPU_ESC6_EA(Bitu func,PhysPt ea);
+void FPU_ESC7_Normal(Bitu rm);
+void FPU_ESC7_EA(Bitu func,PhysPt ea);
+
+
+typedef union {
+    double d;
+#ifndef WORDS_BIGENDIAN
+    struct {
+        Bit32u lower;
+        Bit32s upper;
+    } l;
+#else
+    struct {
+        Bit32s upper;
+        Bit32u lower;
+    } l;
+#endif
+    Bit64s ll;
+} FPU_Reg;
+
+typedef struct {
+    Bit32u m1;
+    Bit32u m2;
+    Bit16u m3;
+
+    Bit16u d1;
+    Bit32u d2;
+} FPU_P_Reg;
+
+enum FPU_Tag {
+       TAG_Valid = 0,
+       TAG_Zero  = 1,
+       TAG_Weird = 2,
+       TAG_Empty = 3
+};
+
+enum FPU_Round {
+       ROUND_Nearest = 0,              
+       ROUND_Down    = 1,
+       ROUND_Up      = 2,      
+       ROUND_Chop    = 3
+};
+
+typedef struct {
+       FPU_Reg         regs[9];
+       FPU_P_Reg       p_regs[9];
+       FPU_Tag         tags[9];
+       Bit16u          cw,cw_mask_all;
+       Bit16u          sw;
+       Bit32u          top;
+       FPU_Round       round;
+} FPU_rec;
+
+
+//get pi from a real library
+#define PI             3.14159265358979323846
+#define L2E            1.4426950408889634
+#define L2T            3.3219280948873623
+#define LN2            0.69314718055994531
+#define LG2            0.3010299956639812
+
+
+extern FPU_rec fpu;
+
+#define TOP fpu.top
+#define STV(i)  ( (fpu.top+ (i) ) & 7 )
+
+
+Bit16u FPU_GetTag(void);
+void FPU_FLDCW(PhysPt addr);
+
+static INLINE void FPU_SetTag(Bit16u tag){
+       for(Bitu i=0;i<8;i++)
+               fpu.tags[i] = static_cast<FPU_Tag>((tag >>(2*i))&3);
+}
+
+static INLINE void FPU_SetCW(Bitu word){
+       fpu.cw = (Bit16u)word;
+       fpu.cw_mask_all = (Bit16u)(word | 0x3f);
+       fpu.round = (FPU_Round)((word >> 10) & 3);
+}
+
+
+static INLINE Bitu FPU_GET_TOP(void) {
+       return (fpu.sw & 0x3800)>>11;
+}
+
+static INLINE void FPU_SET_TOP(Bitu val){
+       fpu.sw &= ~0x3800;
+       fpu.sw |= (val&7)<<11;
+}
+
+
+static INLINE void FPU_SET_C0(Bitu C){
+       fpu.sw &= ~0x0100;
+       if(C) fpu.sw |=  0x0100;
+}
+
+static INLINE void FPU_SET_C1(Bitu C){
+       fpu.sw &= ~0x0200;
+       if(C) fpu.sw |=  0x0200;
+}
+
+static INLINE void FPU_SET_C2(Bitu C){
+       fpu.sw &= ~0x0400;
+       if(C) fpu.sw |=  0x0400;
+}
+
+static INLINE void FPU_SET_C3(Bitu C){
+       fpu.sw &= ~0x4000;
+       if(C) fpu.sw |= 0x4000;
+}
+
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/hardware.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/hardware.h
new file mode 100644 (file)
index 0000000..26d3fde
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_HARDWARE_H
+#define DOSBOX_HARDWARE_H
+
+#include <stdio.h>
+
+class Section;
+enum OPL_Mode {
+       OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3,OPL_opl3gold
+};
+#define CAPTURE_WAVE   0x01
+#define CAPTURE_OPL            0x02
+#define CAPTURE_MIDI   0x04
+#define CAPTURE_IMAGE  0x08
+#define CAPTURE_VIDEO  0x10
+
+extern Bitu CaptureState;
+
+void OPL_Init(Section* sec,OPL_Mode mode);
+void CMS_Init(Section* sec);
+void OPL_ShutDown(Section* sec);
+void CMS_ShutDown(Section* sec);
+
+bool SB_Get_Address(Bitu& sbaddr, Bitu& sbirq, Bitu& sbdma);
+bool TS_Get_Address(Bitu& tsaddr, Bitu& tsirq, Bitu& tsdma);
+
+extern Bit8u adlib_commandreg;
+FILE * OpenCaptureFile(const char * type,const char * ext);
+
+void CAPTURE_AddWave(Bit32u freq, Bit32u len, Bit16s * data);
+#define CAPTURE_FLAG_DBLW      0x1
+#define CAPTURE_FLAG_DBLH      0x2
+void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal);
+void CAPTURE_AddMidi(bool sysex, Bitu len, Bit8u * data);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/inout.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/inout.h
new file mode 100644 (file)
index 0000000..dd0dc17
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_INOUT_H
+#define DOSBOX_INOUT_H
+
+#define IO_MAX (64*1024+3)
+
+#define IO_MB  0x1
+#define IO_MW  0x2
+#define IO_MD  0x4
+#define IO_MA  (IO_MB | IO_MW | IO_MD )
+
+typedef Bitu IO_ReadHandler(Bitu port,Bitu iolen);
+typedef void IO_WriteHandler(Bitu port,Bitu val,Bitu iolen);
+
+extern IO_WriteHandler * io_writehandlers[3][IO_MAX];
+extern IO_ReadHandler * io_readhandlers[3][IO_MAX];
+
+void IO_RegisterReadHandler(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range=1);
+void IO_RegisterWriteHandler(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1);
+
+void IO_FreeReadHandler(Bitu port,Bitu mask,Bitu range=1);
+void IO_FreeWriteHandler(Bitu port,Bitu mask,Bitu range=1);
+
+void IO_WriteB(Bitu port,Bitu val);
+void IO_WriteW(Bitu port,Bitu val);
+void IO_WriteD(Bitu port,Bitu val);
+
+Bitu IO_ReadB(Bitu port);
+Bitu IO_ReadW(Bitu port);
+Bitu IO_ReadD(Bitu port);
+
+/* Classes to manage the IO objects created by the various devices.
+ * The io objects will remove itself on destruction.*/
+class IO_Base{
+protected:
+       bool installed;
+       Bitu m_port, m_mask,m_range;
+public:
+       IO_Base():installed(false){};
+};
+class IO_ReadHandleObject: private IO_Base{
+public:
+       void Install(Bitu port,IO_ReadHandler * handler,Bitu mask,Bitu range=1);
+       void Uninstall();
+       ~IO_ReadHandleObject();
+};
+class IO_WriteHandleObject: private IO_Base{
+public:
+       void Install(Bitu port,IO_WriteHandler * handler,Bitu mask,Bitu range=1);
+       void Uninstall();
+       ~IO_WriteHandleObject();
+};
+
+static INLINE void IO_Write(Bitu port,Bit8u val) {
+       IO_WriteB(port,val);
+}
+static INLINE Bit8u IO_Read(Bitu port){
+       return (Bit8u)IO_ReadB(port);
+}
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/ipx.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/ipx.h
new file mode 100644 (file)
index 0000000..6e87b1e
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_IPX_H
+#define DOSBOX_IPX_H
+
+// Uncomment this for a lot of debug messages:
+//#define IPX_DEBUGMSG 
+
+#ifdef IPX_DEBUGMSG
+#define LOG_IPX LOG_MSG
+#else
+#if defined (_MSC_VER)
+#define LOG_IPX
+#else
+#define LOG_IPX(...)
+#endif
+#endif
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+
+// In Use Flag codes
+#define USEFLAG_AVAILABLE  0x00
+#define USEFLAG_AESTEMP    0xe0
+#define USEFLAG_IPXCRIT    0xf8
+#define USEFLAG_SPXLISTEN  0xf9
+#define USEFLAG_PROCESSING 0xfa
+#define USEFLAG_HOLDING    0xfb
+#define USEFLAG_AESWAITING 0xfc
+#define USEFLAG_AESCOUNT   0xfd
+#define USEFLAG_LISTENING  0xfe
+#define USEFLAG_SENDING    0xff
+
+// Completion codes
+#define COMP_SUCCESS          0x00
+#define COMP_REMOTETERM       0xec
+#define COMP_DISCONNECT       0xed
+#define COMP_INVALIDID        0xee
+#define COMP_SPXTABLEFULL     0xef
+#define COMP_EVENTNOTCANCELED 0xf9
+#define COMP_NOCONNECTION     0xfa
+#define COMP_CANCELLED        0xfc
+#define COMP_MALFORMED        0xfd
+#define COMP_UNDELIVERABLE    0xfe
+#define COMP_HARDWAREERROR    0xff
+
+#ifdef _MSC_VER
+#pragma pack(1)
+#endif
+
+// For Uint8 type
+#include "SDL_net.h"
+
+struct PackedIP {
+       Uint32 host;
+       Uint16 port;
+} GCC_ATTRIBUTE(packed);
+
+struct nodeType {
+       Uint8 node[6];
+} GCC_ATTRIBUTE(packed) ;
+
+struct IPXHeader {
+       Uint8 checkSum[2];
+       Uint8 length[2];
+       Uint8 transControl; // Transport control
+       Uint8 pType; // Packet type
+
+       struct transport {
+               Uint8 network[4];
+               union addrtype {
+                       nodeType byNode;
+                       PackedIP byIP ;
+               } GCC_ATTRIBUTE(packed) addr;
+               Uint8 socket[2];
+       } dest, src;
+} GCC_ATTRIBUTE(packed);
+
+struct fragmentDescriptor {
+       Bit16u offset;
+       Bit16u segment;
+       Bit16u size;
+};
+
+#define IPXBUFFERSIZE 1424
+
+class ECBClass {
+public:
+       RealPt ECBAddr;
+       bool isInESRList;
+       ECBClass *prevECB;      // Linked List
+       ECBClass *nextECB;
+       
+       Bit8u iuflag;           // Need to save data since we are not always in
+       Bit16u mysocket;        // real mode
+
+       Bit8u* databuffer;      // received data is stored here until we get called
+       Bitu buflen;            // by Interrupt
+
+#ifdef IPX_DEBUGMSG 
+       Bitu SerialNumber;
+#endif
+
+       ECBClass(Bit16u segment, Bit16u offset);
+       Bit16u getSocket(void);
+
+       Bit8u getInUseFlag(void);
+
+       void setInUseFlag(Bit8u flagval);
+
+       void setCompletionFlag(Bit8u flagval);
+
+       Bit16u getFragCount(void);
+
+       bool writeData();
+       void writeDataBuffer(Bit8u* buffer, Bit16u length);
+
+       void getFragDesc(Bit16u descNum, fragmentDescriptor *fragDesc);
+       RealPt getESRAddr(void);
+
+       void NotifyESR(void);
+
+       void setImmAddress(Bit8u *immAddr);
+       void getImmAddress(Bit8u* immAddr);
+
+       ~ECBClass();
+};
+
+// The following routines may not be needed on all systems.  On my build of SDL the IPaddress structure is 8 octects 
+// and therefore screws up my IPXheader structure since it needs to be packed.
+
+void UnpackIP(PackedIP ipPack, IPaddress * ipAddr);
+void PackIP(IPaddress ipAddr, PackedIP *ipPack);
+
+#ifdef _MSC_VER
+#pragma pack()
+#endif
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/ipxserver.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/ipxserver.h
new file mode 100644 (file)
index 0000000..1c6a294
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_IPXSERVER_H_
+#define DOSBOX_IPXSERVER_H_
+
+#if C_IPX
+
+#include "SDL_net.h"
+
+struct packetBuffer {
+       Bit8u buffer[1024];
+       Bit16s packetSize;  // Packet size remaining in read
+       Bit16s packetRead;  // Bytes read of total packet
+       bool inPacket;      // In packet reception flag
+       bool connected;         // Connected flag
+       bool waitsize;
+};
+
+#define SOCKETTABLESIZE 16
+#define CONVIP(hostvar) hostvar & 0xff, (hostvar >> 8) & 0xff, (hostvar >> 16) & 0xff, (hostvar >> 24) & 0xff
+#define CONVIPX(hostvar) hostvar[0], hostvar[1], hostvar[2], hostvar[3], hostvar[4], hostvar[5]
+
+
+void IPX_StopServer();
+bool IPX_StartServer(Bit16u portnum);
+bool IPX_isConnectedToServer(Bits tableNum, IPaddress ** ptrAddr);
+
+Bit8u packetCRC(Bit8u *buffer, Bit16u bufSize);
+
+#endif
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/j3.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/j3.h
new file mode 100644 (file)
index 0000000..09affb5
--- /dev/null
@@ -0,0 +1,36 @@
+\r
+#ifndef DOSBOX_J3_H\r
+#define DOSBOX_J3_H\r
+\r
+#ifndef DOSBOX_DOSBOX_H\r
+#include "dosbox.h"\r
+#endif\r
+\r
+#include "control.h"\r
+\r
+/* AX Global Area */\r
+#define BIOSMEM_J3_SEG                 0x40\r
+\r
+#define BIOSMEM_J3_MODE                        0xD0\r
+#define BIOSMEM_J3_LINE_COUNT  0xD4\r
+#define BIOSMEM_J3_GRAPH_ADDR  0xD6\r
+#define BIOSMEM_J3_CODE_SEG            0xDA\r
+#define BIOSMEM_J3_CODE_OFFSET 0xD8\r
+#define BIOSMEM_J3_SCROLL              0xE2\r
+#define BIOSMEM_J3_BLINK               0xE9\r
+\r
+#define GRAPH_J3_SEG                   0xb800\r
+\r
+//int10_j3.cpp\r
+bool INT10_J3_SetCRTBIOSMode(Bitu mode);\r
+Bitu INT60_Handler(void);\r
+Bitu INT6F_Handler(void);\r
+void INT60_J3_Setup();\r
+void INT8_J3();\r
+void J3_OffCursor();\r
+void J3_SetConfig(Section_prop *section);\r
+void J3_GetPalette(Bit8u no, Bit8u &r, Bit8u &g, Bit8u &b);\r
+Bit16u J3_GetMachineCode();\r
+bool J3_IsJapanese();\r
+\r
+#endif\r
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/jega.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/jega.h
new file mode 100644 (file)
index 0000000..dc93e8c
--- /dev/null
@@ -0,0 +1,87 @@
+\r
+#ifndef DOSBOX_JEGA\r
+#define DOSBOX_JEGA\r
+\r
+#ifndef DOSBOX_DOSBOX_H\r
+#include "dosbox.h"\r
+#endif\r
+\r
+/* AX Global Area */\r
+#define BIOSMEM_AX_SEG         0x40\r
+\r
+#define BIOSMEM_AX_VTRAM_SEGADDR 0xE0\r
+#define BIOSMEM_AX_GRAPH_CHAR 0xE2\r
+#define BIOSMEM_AX_GRAPH_ATTR 0xE3\r
+#define BIOSMEM_AX_JPNSTATUS 0xE4\r
+#define BIOSMEM_AX_JEGA_RMOD1 0xE9\r
+#define BIOSMEM_AX_JEGA_RMOD2 0xEA\r
+#define BIOSMEM_AX_KBDSTATUS 0xEB\r
+\r
+#define BIOS_KEYBOARD_AX_KBDSTATUS 0x4EB\r
+/* 40h:EBh Keyboard Additional Status bits\r
+       bit 2 : Kana holding\r
+       bit 1 : Kana Lock key\r
+       bit 0 : Kana LED indicating\r
+*/\r
+\r
+/* JEGA internal registers */\r
+typedef struct {\r
+       Bitu RMOD1//b9: Mode register 1\r
+               , RMOD2//ba: Mode register 2\r
+               , RDAGS//bb: ANK Group sel (not implemented)\r
+               , RDFFB//bc: Font access first byte\r
+               , RDFSB//bd: Font access second byte\r
+               , RDFAP//be: Font Access Pattern\r
+               , RPESL//09: end scan line (superceded by EGA)\r
+               , RPULP//14: under scan line (superceded by EGA)\r
+               , RPSSC//db: DBCS start scan line\r
+               , RPSSU//d9: 2x DBCS upper start scan\r
+               , RPSSL//da: 2x DBCS lower start scan\r
+               , RPPAJ//dc: super imposed (only AX-2 system, not implemented)\r
+               , RCMOD//dd: Cursor Mode (not implemented)\r
+               , RCCLH//0e: Cursor location Upper bits (superceded by EGA)\r
+               , RCCLL//0f: Cursor location Lower bits (superceded by EGA)\r
+               , RCCSL//0a: Cursor Start Line (superceded by EGA)\r
+               , RCCEL//0b: Cursor End Line (superceded by EGA)\r
+               , RCSKW//de: Cursor Skew control (not implemented)\r
+               , ROMSL//df: Unused?\r
+               , RSTAT//bf: Font register accessible status\r
+               ;\r
+       Bitu fontIndex = 0;\r
+} JEGA_DATA;\r
+\r
+extern JEGA_DATA jega;\r
+\r
+//jfontload.cpp\r
+extern Bit8u jfont_sbcs_19[];\r
+extern Bit8u jfont_dbcs_16[];\r
+extern Bit8u jfont_cache_dbcs_16[];\r
+// for J-3100\r
+extern Bit8u jfont_sbcs_16[];\r
+extern Bit8u jfont_dbcs_24[];\r
+extern Bit8u jfont_sbcs_24[];\r
+\r
+//vga_jega.cpp\r
+void SVGA_Setup_JEGA(void);//Init JEGA and AX system area\r
+\r
+//int10_ax.cpp\r
+bool INT10_AX_SetCRTBIOSMode(Bitu mode);\r
+Bitu INT10_AX_GetCRTBIOSMode(void);\r
+bool INT16_AX_SetKBDBIOSMode(Bitu mode);\r
+Bitu INT16_AX_GetKBDBIOSMode(void);\r
+\r
+//int10_char.cpp\r
+extern Bit8u prevchr;\r
+void ReadVTRAMChar(Bit16u col, Bit16u row, Bit16u * result);\r
+void SetVTRAMChar(Bit16u col, Bit16u row, Bit8u chr, Bit8u attr);\r
+void WriteCharJ(Bit16u col, Bit16u row, Bit8u page, Bit8u chr, Bit8u attr, bool useattr);\r
+\r
+//inline functions\r
+inline bool isKanji1(Bit8u chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); }\r
+inline bool isKanji2(Bit8u chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); }\r
+inline bool isJEGAEnabled() {\r
+       if (!IS_AX_ARCH) return false;\r
+       return !(jega.RMOD1 & 0x40);\r
+}\r
+\r
+#endif\r
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/jfont.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/jfont.h
new file mode 100644 (file)
index 0000000..80c0344
--- /dev/null
@@ -0,0 +1,39 @@
+\r
+#ifndef DOSBOX_JFONT_H\r
+#define DOSBOX_JFONT_H\r
+\r
+#include "setup.h"\r
+\r
+#define        VIRTUAL_TEXT_SIZE               0x500\r
+\r
+void InitFontHandle();\r
+void QuitFont();\r
+bool GetWindowsFont(Bitu code, Bit8u *buff, int width, int height);\r
+Bit16u GetTextSeg();\r
+void SetTextSeg();\r
+bool MakeSbcs19Font();\r
+bool MakeSbcs16Font();\r
+bool MakeSbcs24Font();\r
+Bit8u GetKanjiAttr(Bitu x, Bitu y);\r
+Bit8u GetKanjiAttr();\r
+Bit8u *GetSbcsFont(Bitu code);\r
+Bit8u *GetSbcs19Font(Bitu code);\r
+Bit8u *GetSbcs24Font(Bitu code);\r
+void SetFontName(const char *name);\r
+void GetDbcsFrameFont(Bitu code, Bit8u *buff);\r
+Bit8u *GetDbcsFont(Bitu code);\r
+Bit8u *GetDbcs24Font(Bitu code);\r
+bool CheckStayVz();\r
+bool CheckAnotherDisplayDriver();\r
+Bit16u GetGaijiSeg();\r
+void SetGaijiConfig(Section_prop *section);\r
+bool SetGaijiData(Bit16u code, PhysPt data);\r
+bool SetGaijiData24(Bit16u code, PhysPt data);\r
+\r
+#ifdef NDEBUG\r
+#define JTrace\r
+#else\r
+void JTrace(const char *form , ...);\r
+#endif\r
+\r
+#endif\r
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/joystick.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/joystick.h
new file mode 100644 (file)
index 0000000..a513958
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_JOYSTICK_H
+#define DOSBOX_JOYSTICK_H
+void JOYSTICK_Enable(Bitu which,bool enabled);
+
+void JOYSTICK_Button(Bitu which,Bitu num,bool pressed);
+
+void JOYSTICK_Move_X(Bitu which,float x);
+
+void JOYSTICK_Move_Y(Bitu which,float y);
+
+bool JOYSTICK_IsEnabled(Bitu which);
+
+bool JOYSTICK_GetButton(Bitu which, Bitu num);
+
+float JOYSTICK_GetMove_X(Bitu which);
+
+float JOYSTICK_GetMove_Y(Bitu which);
+
+enum JoystickType {
+       JOY_NONE,
+       JOY_AUTO,
+       JOY_2AXIS,
+       JOY_4AXIS,
+       JOY_4AXIS_2,
+       JOY_FCS,
+       JOY_CH
+};
+
+extern JoystickType joytype;
+extern bool button_wrapping_enabled;
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/keyboard.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/keyboard.h
new file mode 100644 (file)
index 0000000..125cfae
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team\r
+ *  Copyright (C) 2016 akm
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_KEYBOARD_H
+#define DOSBOX_KEYBOARD_H
+
+enum KBD_KEYS {
+       KBD_NONE,
+       KBD_1,  KBD_2,  KBD_3,  KBD_4,  KBD_5,  KBD_6,  KBD_7,  KBD_8,  KBD_9,  KBD_0,          
+       KBD_q,  KBD_w,  KBD_e,  KBD_r,  KBD_t,  KBD_y,  KBD_u,  KBD_i,  KBD_o,  KBD_p,  
+       KBD_a,  KBD_s,  KBD_d,  KBD_f,  KBD_g,  KBD_h,  KBD_j,  KBD_k,  KBD_l,  KBD_z,
+       KBD_x,  KBD_c,  KBD_v,  KBD_b,  KBD_n,  KBD_m,  
+       KBD_f1, KBD_f2, KBD_f3, KBD_f4, KBD_f5, KBD_f6, KBD_f7, KBD_f8, KBD_f9, KBD_f10,KBD_f11,KBD_f12,
+       
+       /*Now the weirder keys */
+
+       KBD_esc,KBD_tab,KBD_backspace,KBD_enter,KBD_space,
+       KBD_leftalt,KBD_rightalt,KBD_leftctrl,KBD_rightctrl,KBD_leftshift,KBD_rightshift,
+       KBD_capslock,KBD_scrolllock,KBD_numlock,
+       
+       KBD_grave,KBD_minus,KBD_equals,KBD_backslash,KBD_leftbracket,KBD_rightbracket,
+       KBD_semicolon,KBD_quote,KBD_period,KBD_comma,KBD_slash,KBD_extra_lt_gt,
+
+       KBD_printscreen,KBD_pause,
+       KBD_insert,KBD_home,KBD_pageup,KBD_delete,KBD_end,KBD_pagedown,
+       KBD_left,KBD_up,KBD_down,KBD_right,
+
+       KBD_kp1,KBD_kp2,KBD_kp3,KBD_kp4,KBD_kp5,KBD_kp6,KBD_kp7,KBD_kp8,KBD_kp9,KBD_kp0,
+       KBD_kpdivide,KBD_kpmultiply,KBD_kpminus,KBD_kpplus,KBD_kpenter,KBD_kpperiod,\r
+       KBD_yen, KBD_underscore,//JP layout
+       KBD_ax,KBD_conv,KBD_nconv, // for AX
+\r
+       KBD_f13,KBD_f14,KBD_f15,
+\r
+       KBD_LAST
+};
+
+void KEYBOARD_ClrBuffer(void);
+void KEYBOARD_AddKey(KBD_KEYS keytype,bool pressed);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/logging.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/logging.h
new file mode 100644 (file)
index 0000000..049e504
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_LOGGING_H
+#define DOSBOX_LOGGING_H
+enum LOG_TYPES {
+       LOG_ALL,
+       LOG_VGA, LOG_VGAGFX,LOG_VGAMISC,LOG_INT10,
+       LOG_SB,LOG_DMACONTROL,
+       LOG_FPU,LOG_CPU,LOG_PAGING,
+       LOG_FCB,LOG_FILES,LOG_IOCTL,LOG_EXEC,LOG_DOSMISC,
+       LOG_PIT,LOG_KEYBOARD,LOG_PIC,
+       LOG_MOUSE,LOG_BIOS,LOG_GUI,LOG_MISC,
+       LOG_IO,
+       LOG_PCI,
+       LOG_MAX
+};
+
+enum LOG_SEVERITIES {
+       LOG_NORMAL,
+       LOG_WARN,
+       LOG_ERROR
+};
+
+#if C_DEBUG
+class LOG 
+{ 
+       LOG_TYPES       d_type;
+       LOG_SEVERITIES  d_severity;
+public:
+
+       LOG (LOG_TYPES type , LOG_SEVERITIES severity):
+               d_type(type),
+               d_severity(severity)
+               {}
+       void operator() (char const* buf, ...) GCC_ATTRIBUTE(__format__(__printf__, 2, 3));  //../src/debug/debug_gui.cpp
+
+};
+
+void DEBUG_ShowMsg(char const* format,...) GCC_ATTRIBUTE(__format__(__printf__, 1, 2));
+#define LOG_MSG DEBUG_ShowMsg
+
+#else  //C_DEBUG
+
+struct LOG
+{
+       LOG(LOG_TYPES , LOG_SEVERITIES )                                                                                { }
+       void operator()(char const* )                                                                                                   { }
+       void operator()(char const* , double )                                                                                  { }
+       void operator()(char const* , double , double )                                                         { }
+       void operator()(char const* , double , double , double )                                        { }
+       void operator()(char const* , double , double , double , double )                                       { }
+       void operator()(char const* , double , double , double , double , double )                                      { }
+       void operator()(char const* , double , double , double , double , double , double )                                     { }
+       void operator()(char const* , double , double , double , double , double , double , double)                                     { }
+
+
+
+       void operator()(char const* , char const* )                                                                     { }
+       void operator()(char const* , char const* , double )                                                    { }
+       void operator()(char const* , char const* , double ,double )                            { }
+       void operator()(char const* , double , char const* )                                            { }
+       void operator()(char const* , double , double, char const* )                                            { }
+       void operator()(char const* , char const*, char const*)                         { }
+
+       void operator()(char const* , double , double , double , char const* )                                  { }
+}; //add missing operators to here
+       //try to avoid anything smaller than bit32...
+void GFX_ShowMsg(char const* format,...) GCC_ATTRIBUTE(__format__(__printf__, 1, 2));
+#define LOG_MSG GFX_ShowMsg
+
+#endif //C_DEBUG
+
+
+#endif //DOSBOX_LOGGING_H
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/mapper.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/mapper.h
new file mode 100644 (file)
index 0000000..3ba648c
--- /dev/null
@@ -0,0 +1,40 @@
+ /*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_MAPPER_H
+#define DOSBOX_MAPPER_H
+
+enum MapKeys {
+       MK_f1,MK_f2,MK_f3,MK_f4,MK_f5,MK_f6,MK_f7,MK_f8,MK_f9,MK_f10,MK_f11,MK_f12,
+       MK_return,MK_kpminus,MK_scrolllock,MK_printscreen,MK_pause,MK_home
+
+};
+
+typedef void (MAPPER_Handler)(bool pressed);
+void MAPPER_AddHandler(MAPPER_Handler * handler,MapKeys key,Bitu mods,char const * const eventname,char const * const buttonname);
+void MAPPER_Init(void);
+void MAPPER_StartUp(Section * sec);
+void MAPPER_Run(bool pressed);
+void MAPPER_RunInternal();
+void MAPPER_LosingFocus(void);
+
+
+#define MMOD1 0x1
+#define MMOD2 0x2
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/mem.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/mem.h
new file mode 100644 (file)
index 0000000..d362cb0
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_MEM_H
+#define DOSBOX_MEM_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+
+typedef Bit32u PhysPt;
+typedef Bit8u * HostPt;
+typedef Bit32u RealPt;
+
+typedef Bit32s MemHandle;
+
+#define MEM_PAGESIZE 4096
+
+extern HostPt MemBase;
+HostPt GetMemBase(void);
+
+bool MEM_A20_Enabled(void);
+void MEM_A20_Enable(bool enable);
+
+/* Memory management / EMS mapping */
+HostPt MEM_GetBlockPage(void);
+Bitu MEM_FreeTotal(void);                      //Free 4 kb pages
+Bitu MEM_FreeLargest(void);                    //Largest free 4 kb pages block
+Bitu MEM_TotalPages(void);                     //Total amount of 4 kb pages
+Bitu MEM_AllocatedPages(MemHandle handle); // amount of allocated pages of handle
+MemHandle MEM_AllocatePages(Bitu pages,bool sequence);
+MemHandle MEM_GetNextFreePage(void);
+PhysPt MEM_AllocatePage(void);
+void MEM_ReleasePages(MemHandle handle);
+bool MEM_ReAllocatePages(MemHandle & handle,Bitu pages,bool sequence);
+
+MemHandle MEM_NextHandle(MemHandle handle);
+MemHandle MEM_NextHandleAt(MemHandle handle,Bitu where);
+
+/* 
+       The folowing six functions are used everywhere in the end so these should be changed for
+       Working on big or little endian machines 
+*/
+
+#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
+
+static INLINE Bit8u host_readb(HostPt off) {
+       return off[0];
+}
+static INLINE Bit16u host_readw(HostPt off) {
+       return off[0] | (off[1] << 8);
+}
+static INLINE Bit32u host_readd(HostPt off) {
+       return off[0] | (off[1] << 8) | (off[2] << 16) | (off[3] << 24);
+}
+static INLINE void host_writeb(HostPt off,Bit8u val) {
+       off[0]=val;
+}
+static INLINE void host_writew(HostPt off,Bit16u val) {
+       off[0]=(Bit8u)(val);
+       off[1]=(Bit8u)(val >> 8);
+}
+static INLINE void host_writed(HostPt off,Bit32u val) {
+       off[0]=(Bit8u)(val);
+       off[1]=(Bit8u)(val >> 8);
+       off[2]=(Bit8u)(val >> 16);
+       off[3]=(Bit8u)(val >> 24);
+}
+
+#else
+
+static INLINE Bit8u host_readb(HostPt off) {
+       return *(Bit8u *)off;
+}
+static INLINE Bit16u host_readw(HostPt off) {
+       return *(Bit16u *)off;
+}
+static INLINE Bit32u host_readd(HostPt off) {
+       return *(Bit32u *)off;
+}
+static INLINE void host_writeb(HostPt off,Bit8u val) {
+       *(Bit8u *)(off)=val;
+}
+static INLINE void host_writew(HostPt off,Bit16u val) {
+       *(Bit16u *)(off)=val;
+}
+static INLINE void host_writed(HostPt off,Bit32u val) {
+       *(Bit32u *)(off)=val;
+}
+
+#endif
+
+
+static INLINE void var_write(Bit8u * var, Bit8u val) {
+       host_writeb((HostPt)var, val);
+}
+
+static INLINE void var_write(Bit16u * var, Bit16u val) {
+       host_writew((HostPt)var, val);
+}
+
+static INLINE void var_write(Bit32u * var, Bit32u val) {
+       host_writed((HostPt)var, val);
+}
+
+/* The Folowing six functions are slower but they recognize the paged memory system */
+
+Bit8u  mem_readb(PhysPt pt);
+Bit16u mem_readw(PhysPt pt);
+Bit32u mem_readd(PhysPt pt);
+
+void mem_writeb(PhysPt pt,Bit8u val);
+void mem_writew(PhysPt pt,Bit16u val);
+void mem_writed(PhysPt pt,Bit32u val);
+
+static INLINE void phys_writeb(PhysPt addr,Bit8u val) {
+       host_writeb(MemBase+addr,val);
+}
+static INLINE void phys_writew(PhysPt addr,Bit16u val){
+       host_writew(MemBase+addr,val);
+}
+static INLINE void phys_writed(PhysPt addr,Bit32u val){
+       host_writed(MemBase+addr,val);
+}
+
+static INLINE Bit8u phys_readb(PhysPt addr) {
+       return host_readb(MemBase+addr);
+}
+static INLINE Bit16u phys_readw(PhysPt addr){
+       return host_readw(MemBase+addr);
+}
+static INLINE Bit32u phys_readd(PhysPt addr){
+       return host_readd(MemBase+addr);
+}
+
+/* These don't check for alignment, better be sure it's correct */
+
+void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size);
+void MEM_BlockRead(PhysPt pt,void * data,Bitu size);
+void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size);
+void MEM_StrCopy(PhysPt pt,char * data,Bitu size);
+
+void mem_memcpy(PhysPt dest,PhysPt src,Bitu size);
+Bitu mem_strlen(PhysPt pt);
+void mem_strcpy(PhysPt dest,PhysPt src);
+
+/* The folowing functions are all shortcuts to the above functions using physical addressing */
+
+static INLINE Bit8u real_readb(Bit16u seg,Bit16u off) {
+       return mem_readb((seg<<4)+off);
+}
+static INLINE Bit16u real_readw(Bit16u seg,Bit16u off) {
+       return mem_readw((seg<<4)+off);
+}
+static INLINE Bit32u real_readd(Bit16u seg,Bit16u off) {
+       return mem_readd((seg<<4)+off);
+}
+
+static INLINE void real_writeb(Bit16u seg,Bit16u off,Bit8u val) {
+       mem_writeb(((seg<<4)+off),val);
+}
+static INLINE void real_writew(Bit16u seg,Bit16u off,Bit16u val) {
+       mem_writew(((seg<<4)+off),val);
+}
+static INLINE void real_writed(Bit16u seg,Bit16u off,Bit32u val) {
+       mem_writed(((seg<<4)+off),val);
+}
+
+
+static INLINE Bit16u RealSeg(RealPt pt) {
+       return (Bit16u)(pt>>16);
+}
+
+static INLINE Bit16u RealOff(RealPt pt) {
+       return (Bit16u)(pt&0xffff);
+}
+
+static INLINE PhysPt Real2Phys(RealPt pt) {
+       return (RealSeg(pt)<<4) +RealOff(pt);
+}
+
+static INLINE PhysPt PhysMake(Bit16u seg,Bit16u off) {
+       return (seg<<4)+off;
+}
+
+static INLINE RealPt RealMake(Bit16u seg,Bit16u off) {
+       return (seg<<16)+off;
+}
+
+static INLINE void RealSetVec(Bit8u vec,RealPt pt) {
+       mem_writed(vec<<2,pt);
+}
+
+static INLINE void RealSetVec(Bit8u vec,RealPt pt,RealPt &old) {
+       old = mem_readd(vec<<2);
+       mem_writed(vec<<2,pt);
+}
+
+static INLINE RealPt RealGetVec(Bit8u vec) {
+       return mem_readd(vec<<2);
+}      
+
+#endif
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/midi.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/midi.h
new file mode 100644 (file)
index 0000000..86431dc
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_MIDI_H
+#define DOSBOX_MIDI_H
+
+#ifndef DOSBOX_PROGRAMS_H
+#include "programs.h"
+#endif
+
+class MidiHandler {
+public:
+       MidiHandler();
+       virtual bool Open(const char * /*conf*/) { return true; };
+       virtual void Close(void) {};
+       virtual void PlayMsg(Bit8u * /*msg*/) {};
+       virtual void PlaySysex(Bit8u * /*sysex*/,Bitu /*len*/) {};
+       virtual const char * GetName(void) { return "none"; };
+       virtual void ListAll(Program * base) {};
+       virtual ~MidiHandler() { };
+       MidiHandler * next;
+};
+
+
+#define SYSEX_SIZE 8192
+struct DB_Midi {
+       Bitu status;
+       Bitu cmd_len;
+       Bitu cmd_pos;
+       Bit8u cmd_buf[8];
+       Bit8u rt_buf[8];
+       struct {
+               Bit8u buf[SYSEX_SIZE];
+               Bitu used;
+               Bitu delay;
+               Bit32u start;
+       } sysex;
+       bool available;
+       MidiHandler * handler;
+};
+
+extern DB_Midi midi;
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/mixer.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/mixer.h
new file mode 100644 (file)
index 0000000..94b806b
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_MIXER_H
+#define DOSBOX_MIXER_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+
+typedef void (*MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
+typedef void (*MIXER_Handler)(Bitu len);
+
+enum BlahModes {
+       MIXER_8MONO,MIXER_8STEREO,
+       MIXER_16MONO,MIXER_16STEREO
+};
+
+enum MixerModes {
+       M_8M,M_8S,
+       M_16M,M_16S
+};
+
+#define MIXER_BUFSIZE (16*1024)
+#define MIXER_BUFMASK (MIXER_BUFSIZE-1)
+extern Bit8u MixTemp[MIXER_BUFSIZE];
+
+#define MAX_AUDIO ((1<<(16-1))-1)
+#define MIN_AUDIO -(1<<(16-1))
+
+class MixerChannel {
+public:
+       void SetVolume(float _left,float _right);
+       void SetScale( float f );
+       void UpdateVolume(void);
+       void SetFreq(Bitu _freq);
+       void Mix(Bitu _needed);
+       void AddSilence(void);                  //Fill up until needed
+
+       template<class Type,bool stereo,bool signeddata,bool nativeorder>
+       void AddSamples(Bitu len, const Type* data);
+
+       void AddSamples_m8(Bitu len, const Bit8u * data);
+       void AddSamples_s8(Bitu len, const Bit8u * data);
+       void AddSamples_m8s(Bitu len, const Bit8s * data);
+       void AddSamples_s8s(Bitu len, const Bit8s * data);
+       void AddSamples_m16(Bitu len, const Bit16s * data);
+       void AddSamples_s16(Bitu len, const Bit16s * data);
+       void AddSamples_m16u(Bitu len, const Bit16u * data);
+       void AddSamples_s16u(Bitu len, const Bit16u * data);
+       void AddSamples_m32(Bitu len, const Bit32s * data);
+       void AddSamples_s32(Bitu len, const Bit32s * data);
+       void AddSamples_m16_nonnative(Bitu len, const Bit16s * data);
+       void AddSamples_s16_nonnative(Bitu len, const Bit16s * data);
+       void AddSamples_m16u_nonnative(Bitu len, const Bit16u * data);
+       void AddSamples_s16u_nonnative(Bitu len, const Bit16u * data);
+       void AddSamples_m32_nonnative(Bitu len, const Bit32s * data);
+       void AddSamples_s32_nonnative(Bitu len, const Bit32s * data);
+
+       void AddStretched(Bitu len,Bit16s * data);              //Strech block up into needed data
+       void FillUp(void);
+       void Enable(bool _yesno);
+       MIXER_Handler handler;
+       float volmain[2];
+       float scale;
+       Bit32s volmul[2];
+       Bitu freq_add,freq_index;
+       Bitu done,needed;
+       Bits last[2];
+       const char * name;
+       bool enabled;
+       MixerChannel * next;
+};
+
+MixerChannel * MIXER_AddChannel(MIXER_Handler handler,Bitu freq,const char * name);
+MixerChannel * MIXER_FindChannel(const char * name);
+/* Find the device you want to delete with findchannel "delchan gets deleted" */
+void MIXER_DelChannel(MixerChannel* delchan); 
+
+/* Object to maintain a mixerchannel; As all objects it registers itself with create
+ * and removes itself when destroyed. */
+class MixerObject{
+private:
+       bool installed;
+       char m_name[32];
+public:
+       MixerObject():installed(false){};
+       MixerChannel* Install(MIXER_Handler handler,Bitu freq,const char * name);
+       ~MixerObject();
+};
+
+
+/* PC Speakers functions, tightly related to the timer functions */
+void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode);
+void PCSPEAKER_SetType(Bitu mode);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/modules.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/modules.h
new file mode 100644 (file)
index 0000000..6bbeffc
--- /dev/null
@@ -0,0 +1,180 @@
+/* Standard data types used */
+
+typedef unsigned char Bit8u;
+typedef signed char Bit8s;
+typedef unsigned short Bit16u;
+typedef signed short Bit16s;
+typedef unsigned long Bit32u;
+typedef signed long Bit32s;
+#if defined(_MSC_VER)
+typedef unsigned __int64 Bit64u;
+typedef signed __int64 Bit64s;
+#else
+typedef unsigned long long int Bit64u;
+typedef signed long long int Bit64s;
+#endif
+
+
+
+/* Setting up pointers to all subfunctions */
+#ifdef MODULE_WANT_IO_READ
+typedef Bit8u (* IO_ReadHandler)(Bit32u port);
+static void (* IO_RegisterReadHandler)(Bit32u port,IO_ReadHandler handler,char * name);
+static void (* IO_FreeReadHandler)(Bit32u port);
+#endif
+
+#ifdef MODULE_WANT_IO_WRITE
+typedef void (* IO_WriteHandler)(Bit32u port,Bit8u value);
+static void (* IO_RegisterWriteHandler)(Bit32u port,IO_WriteHandler handler,char * name);
+static void (* IO_FreeWriteHandler)(Bit32u port);
+#endif
+
+#ifdef MODULE_WANT_IRQ_EOI
+typedef void (* IRQ_EOIHandler)(void);
+static void (* IRQ_RegisterEOIHandler)(Bit32u irq,IRQ_EOIHandler handler,char * name);
+static void (* IRQ_FreeEOIHandler)(Bit32u irq);
+#endif
+
+#ifdef MODULE_WANT_IRQ 
+static void (* IRQ_Activate)(Bit32u irq);
+static void (* IRQ_Deactivate)(Bit32u irq);
+#endif
+
+#ifdef MODULE_WANT_TIMER
+typedef void (* TIMER_MicroHandler)(void);
+static  void (* TIMER_RegisterMicroHandler)(TIMER_MicroHandler handler,Bit32u micro);
+#endif
+
+#ifdef MODULE_WANT_TIMER_TICK
+typedef void (* TIMER_TickHandler)(Bit32u ticks);
+static  void (* TIMER_RegisterTickHandler)(TIMER_TickHandler handler);
+#endif
+
+/* 
+       4 8-bit and 4 16-bit channels you can read data from 
+       16-bit reads are word sized
+*/
+
+#ifdef MODULE_WANT_DMA_READ
+static void (* DMA_8_Read)(Bit32u chan,Bit8u * data,Bit16u size);
+static void (* DMA_16_Read)(Bit32u chan,Bit8u * data,Bit16u size);
+#endif
+
+/* 
+       4 8-bit and 4 16-bit channels you can write data from 
+       16-bit writes are word sized
+*/
+
+#ifdef MODULE_WANT_DMA_READ
+static void (* DMA_8_Write)(Bit32u chan,Bit8u * data,Bit16u size);
+static void (* DMA_16_Write)(Bit32u chan,Bit8u * data,Bit16u size);
+#endif
+
+
+#ifdef MODULE_WANT_MIXER 
+/*     The len here means the amount of samples needed not the buffersize it needed to fill */
+typedef void (* MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
+
+/* Different types if modes a mixer channel can work in */
+#define MIXER_8MONO            0
+#define MIXER_8STEREO  1
+#define MIXER_16MONO   2
+#define MIXER_16STEREO 3
+struct MIXER_Channel;
+
+#define MAX_AUDIO ((1<<(16-1))-1)
+#define MIN_AUDIO -(1<<(16-1))
+
+MIXER_Channel *(* MIXER_AddChannel)(MIXER_MixHandler handler,Bit32u freq,char * name);
+void (* MIXER_SetVolume)(MIXER_Channel * chan,Bit8u vol);
+void (* MIXER_SetFreq)(MIXER_Channel * chan,Bit32u freq);
+void (* MIXER_SetMode)(MIXER_Channel * chan,Bit8u mode);
+void (* MIXER_Enable)(MIXER_Channel * chan,bool enable);
+#endif
+
+typedef bool (* MODULE_FindHandler)(char * name,void * * function);
+typedef char *(* MODULE_StartHandler)(MODULE_FindHandler find_handler);
+
+#define MODULE_START_PROC "ModuleStart"
+
+#ifdef MODULE_START_FUNCTION
+#include <stdio.h>
+
+#define GET_FUNCTION(a)                                                                                                        \
+       if (!find_handler(#a ,(void * *) &a)) {                                                         \
+               return "Can't find requested function";                                                 \
+       };
+
+
+#if defined (WIN32)
+#include <windows.h>
+BOOL APIENTRY DllMain( HANDLE hModule, 
+                       DWORD  ul_reason_for_call, 
+                       LPVOID lpReserved
+                                        )
+{
+    return TRUE;
+}
+
+extern "C" {
+__declspec(dllexport) 
+#endif 
+char * ModuleStart (MODULE_FindHandler find_handler) {
+
+#ifdef MODULE_WANT_IRQ_EOI
+GET_FUNCTION(IRQ_RegisterEOIHandler);
+GET_FUNCTION(IRQ_FreeEOIHandler);
+#endif 
+
+#ifdef MODULE_WANT_IRQ 
+GET_FUNCTION(IRQ_Activate);
+GET_FUNCTION(IRQ_Deactivate);
+#endif
+
+#ifdef MODULE_WANT_IO_READ
+GET_FUNCTION(IO_RegisterReadHandler);
+GET_FUNCTION(IO_FreeReadHandler);
+#endif
+
+#ifdef MODULE_WANT_IO_WRITE
+GET_FUNCTION(IO_RegisterWriteHandler);
+GET_FUNCTION(IO_FreeWriteHandler);
+#endif
+
+#ifdef MODULE_WANT_TIMER
+GET_FUNCTION(TIMER_RegisterMicroHandler);
+#endif
+
+#ifdef MODULE_WANT_TIMER_TICKS
+GET_FUNCTION(TIMER_RegisterTickHandler);
+#endif
+
+#ifdef MODULE_WANT_DMA_READ
+GET_FUNCTION(DMA_8_Read);
+GET_FUNCTION(DMA_16_Read);
+#endif
+
+#ifdef MODULE_WANT_DMA_WRITE
+GET_FUNCTION(DMA_8_Write);
+GET_FUNCTION(DMA_16_Write);
+#endif
+
+#ifdef MODULE_WANT_MIXER
+GET_FUNCTION(MIXER_AddChannel);
+GET_FUNCTION(MIXER_SetVolume);
+GET_FUNCTION(MIXER_SetFreq);
+GET_FUNCTION(MIXER_SetMode);
+GET_FUNCTION(MIXER_Enable);
+#endif
+
+return MODULE_START_FUNCTION;
+
+}
+#if defined (WIN32)
+}
+#endif 
+
+
+
+#endif
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/mouse.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/mouse.h
new file mode 100644 (file)
index 0000000..8430394
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (C) 2002-2017  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Wengier: MOUSE CLIPBOARD support
+ */
+
+#ifndef DOSBOX_MOUSE_H
+#define DOSBOX_MOUSE_H
+
+
+void Mouse_ShowCursor(void);
+void Mouse_HideCursor(void);
+
+bool Mouse_SetPS2State(bool use);
+
+void Mouse_ChangePS2Callback(Bit16u pseg, Bit16u pofs);
+
+
+void Mouse_CursorMoved(float xrel,float yrel,float x,float y,bool emulate);
+#if C_CLIPBOARD
+const char* Mouse_GetSelected(int x1, int y1, int x2, int y2, int w, int h);
+void Mouse_Select(int x1, int y1, int x2, int y2, int w, int h);
+void Restore_Text(int x1, int y1, int x2, int y2, int w, int h);
+#endif
+void Mouse_CursorSet(float x,float y);
+void Mouse_ButtonPressed(Bit8u button);
+void Mouse_ButtonReleased(Bit8u button);
+
+void Mouse_AutoLock(bool enable);
+void Mouse_BeforeNewVideoMode(bool setmode);
+void Mouse_AfterNewVideoMode(bool setmode);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/paging.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/paging.h
new file mode 100644 (file)
index 0000000..bf01dfa
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_PAGING_H
+#define DOSBOX_PAGING_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+
+// disable this to reduce the size of the TLB
+// NOTE: does not work with the dynamic core (dynrec is fine)
+#define USE_FULL_TLB
+
+class PageDirectory;
+
+#define MEM_PAGE_SIZE  (4096)
+#define XMS_START              (0x110)
+
+#if defined(USE_FULL_TLB)
+#define TLB_SIZE               (1024*1024)
+#else
+#define TLB_SIZE               65536   // This must a power of 2 and greater then LINK_START
+#define BANK_SHIFT             28
+#define BANK_MASK              0xffff // always the same as TLB_SIZE-1?
+#define TLB_BANKS              ((1024*1024/TLB_SIZE)-1)
+#endif
+
+#define PFLAG_READABLE         0x1
+#define PFLAG_WRITEABLE                0x2
+#define PFLAG_HASROM           0x4
+#define PFLAG_HASCODE          0x8                             //Page contains dynamic code
+#define PFLAG_NOCODE           0x10                    //No dynamic code can be generated here
+#define PFLAG_INIT                     0x20                    //No dynamic code can be generated here
+
+#define LINK_START     ((1024+64)/4)                   //Start right after the HMA
+
+//Allow 128 mb of memory to be linked
+#define PAGING_LINKS (128*1024/4)
+
+class PageHandler {
+public:
+       virtual ~PageHandler(void) { }
+       virtual Bitu readb(PhysPt addr);
+       virtual Bitu readw(PhysPt addr);
+       virtual Bitu readd(PhysPt addr);
+       virtual void writeb(PhysPt addr,Bitu val);
+       virtual void writew(PhysPt addr,Bitu val);
+       virtual void writed(PhysPt addr,Bitu val);
+       virtual HostPt GetHostReadPt(Bitu phys_page);
+       virtual HostPt GetHostWritePt(Bitu phys_page);
+       virtual bool readb_checked(PhysPt addr,Bit8u * val);
+       virtual bool readw_checked(PhysPt addr,Bit16u * val);
+       virtual bool readd_checked(PhysPt addr,Bit32u * val);
+       virtual bool writeb_checked(PhysPt addr,Bitu val);
+       virtual bool writew_checked(PhysPt addr,Bitu val);
+       virtual bool writed_checked(PhysPt addr,Bitu val);
+       Bitu flags;
+};
+
+/* Some other functions */
+void PAGING_Enable(bool enabled);
+bool PAGING_Enabled(void);
+
+Bitu PAGING_GetDirBase(void);
+void PAGING_SetDirBase(Bitu cr3);
+void PAGING_InitTLB(void);
+void PAGING_ClearTLB(void);
+
+void PAGING_LinkPage(Bitu lin_page,Bitu phys_page);
+void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page);
+void PAGING_UnlinkPages(Bitu lin_page,Bitu pages);
+/* This maps the page directly, only use when paging is disabled */
+void PAGING_MapPage(Bitu lin_page,Bitu phys_page);
+bool PAGING_MakePhysPage(Bitu & page);
+bool PAGING_ForcePageInit(Bitu lin_addr);
+
+void MEM_SetLFB(Bitu page, Bitu pages, PageHandler *handler, PageHandler *mmiohandler);
+void MEM_SetPageHandler(Bitu phys_page, Bitu pages, PageHandler * handler);
+void MEM_ResetPageHandler(Bitu phys_page, Bitu pages);
+
+
+#ifdef _MSC_VER
+#pragma pack (1)
+#endif
+struct X86_PageEntryBlock{
+#ifdef WORDS_BIGENDIAN
+       Bit32u          base:20;
+       Bit32u          avl:3;
+       Bit32u          g:1;
+       Bit32u          pat:1;
+       Bit32u          d:1;
+       Bit32u          a:1;
+       Bit32u          pcd:1;
+       Bit32u          pwt:1;
+       Bit32u          us:1;
+       Bit32u          wr:1;
+       Bit32u          p:1;
+#else
+       Bit32u          p:1;
+       Bit32u          wr:1;
+       Bit32u          us:1;
+       Bit32u          pwt:1;
+       Bit32u          pcd:1;
+       Bit32u          a:1;
+       Bit32u          d:1;
+       Bit32u          pat:1;
+       Bit32u          g:1;
+       Bit32u          avl:3;
+       Bit32u          base:20;
+#endif
+} GCC_ATTRIBUTE(packed);
+#ifdef _MSC_VER
+#pragma pack ()
+#endif
+
+
+union X86PageEntry {
+       Bit32u load;
+       X86_PageEntryBlock block;
+};
+
+#if !defined(USE_FULL_TLB)
+typedef struct {
+       HostPt read;
+       HostPt write;
+       PageHandler * readhandler;
+       PageHandler * writehandler;
+       Bit32u phys_page;
+} tlb_entry;
+#endif
+
+struct PagingBlock {
+       Bitu                    cr3;
+       Bitu                    cr2;
+       struct {
+               Bitu page;
+               PhysPt addr;
+       } base;
+#if defined(USE_FULL_TLB)
+       struct {
+               HostPt read[TLB_SIZE];
+               HostPt write[TLB_SIZE];
+               PageHandler * readhandler[TLB_SIZE];
+               PageHandler * writehandler[TLB_SIZE];
+               Bit32u  phys_page[TLB_SIZE];
+       } tlb;
+#else
+       tlb_entry tlbh[TLB_SIZE];
+       tlb_entry *tlbh_banks[TLB_BANKS];
+#endif
+       struct {
+               Bitu used;
+               Bit32u entries[PAGING_LINKS];
+       } links;
+       Bit32u          firstmb[LINK_START];
+       bool            enabled;
+};
+
+extern PagingBlock paging; 
+
+/* Some support functions */
+
+PageHandler * MEM_GetPageHandler(Bitu phys_page);
+
+
+/* Unaligned address handlers */
+Bit16u mem_unalignedreadw(PhysPt address);
+Bit32u mem_unalignedreadd(PhysPt address);
+void mem_unalignedwritew(PhysPt address,Bit16u val);
+void mem_unalignedwrited(PhysPt address,Bit32u val);
+
+bool mem_unalignedreadw_checked(PhysPt address,Bit16u * val);
+bool mem_unalignedreadd_checked(PhysPt address,Bit32u * val);
+bool mem_unalignedwritew_checked(PhysPt address,Bit16u val);
+bool mem_unalignedwrited_checked(PhysPt address,Bit32u val);
+
+#if defined(USE_FULL_TLB)
+
+static INLINE HostPt get_tlb_read(PhysPt address) {
+       return paging.tlb.read[address>>12];
+}
+static INLINE HostPt get_tlb_write(PhysPt address) {
+       return paging.tlb.write[address>>12];
+}
+static INLINE PageHandler* get_tlb_readhandler(PhysPt address) {
+       return paging.tlb.readhandler[address>>12];
+}
+static INLINE PageHandler* get_tlb_writehandler(PhysPt address) {
+       return paging.tlb.writehandler[address>>12];
+}
+
+/* Use these helper functions to access linear addresses in readX/writeX functions */
+static INLINE PhysPt PAGING_GetPhysicalPage(PhysPt linePage) {
+       return (paging.tlb.phys_page[linePage>>12]<<12);
+}
+
+static INLINE PhysPt PAGING_GetPhysicalAddress(PhysPt linAddr) {
+       return (paging.tlb.phys_page[linAddr>>12]<<12)|(linAddr&0xfff);
+}
+
+#else
+
+void PAGING_InitTLBBank(tlb_entry **bank);
+
+static INLINE tlb_entry *get_tlb_entry(PhysPt address) {
+       Bitu index=(address>>12);
+       if (TLB_BANKS && (index > TLB_SIZE)) {
+               Bitu bank=(address>>BANK_SHIFT) - 1;
+               if (!paging.tlbh_banks[bank])
+                       PAGING_InitTLBBank(&paging.tlbh_banks[bank]);
+               return &paging.tlbh_banks[bank][index & BANK_MASK];
+       }
+       return &paging.tlbh[index];
+}
+
+static INLINE HostPt get_tlb_read(PhysPt address) {
+       return get_tlb_entry(address)->read;
+}
+static INLINE HostPt get_tlb_write(PhysPt address) {
+       return get_tlb_entry(address)->write;
+}
+static INLINE PageHandler* get_tlb_readhandler(PhysPt address) {
+       return get_tlb_entry(address)->readhandler;
+}
+static INLINE PageHandler* get_tlb_writehandler(PhysPt address) {
+       return get_tlb_entry(address)->writehandler;
+}
+
+/* Use these helper functions to access linear addresses in readX/writeX functions */
+static INLINE PhysPt PAGING_GetPhysicalPage(PhysPt linePage) {
+       tlb_entry *entry = get_tlb_entry(linePage);
+       return (entry->phys_page<<12);
+}
+
+static INLINE PhysPt PAGING_GetPhysicalAddress(PhysPt linAddr) {
+       tlb_entry *entry = get_tlb_entry(linAddr);
+       return (entry->phys_page<<12)|(linAddr&0xfff);
+}
+#endif
+
+/* Special inlined memory reading/writing */
+static INLINE Bit8u mem_readb_inline(PhysPt address) {
+       HostPt tlb_addr=get_tlb_read(address);
+       if (tlb_addr) return host_readb(tlb_addr+address);
+       else return (Bit8u)(get_tlb_readhandler(address))->readb(address);
+}
+
+static INLINE Bit16u mem_readw_inline(PhysPt address) {
+       if ((address & 0xfff)<0xfff) {
+               HostPt tlb_addr=get_tlb_read(address);
+               if (tlb_addr) return host_readw(tlb_addr+address);
+               else return (Bit16u)(get_tlb_readhandler(address))->readw(address);
+       } else return mem_unalignedreadw(address);
+}
+
+static INLINE Bit32u mem_readd_inline(PhysPt address) {
+       if ((address & 0xfff)<0xffd) {
+               HostPt tlb_addr=get_tlb_read(address);
+               if (tlb_addr) return host_readd(tlb_addr+address);
+               else return (get_tlb_readhandler(address))->readd(address);
+       } else return mem_unalignedreadd(address);
+}
+
+static INLINE void mem_writeb_inline(PhysPt address,Bit8u val) {
+       HostPt tlb_addr=get_tlb_write(address);
+       if (tlb_addr) host_writeb(tlb_addr + address, val);
+       else (get_tlb_writehandler(address))->writeb(address,val);
+}
+
+static INLINE void mem_writew_inline(PhysPt address,Bit16u val) {
+       if ((address & 0xfff)<0xfff) {
+               HostPt tlb_addr=get_tlb_write(address);
+               if (tlb_addr) host_writew(tlb_addr+address,val);
+               else (get_tlb_writehandler(address))->writew(address,val);
+       } else mem_unalignedwritew(address,val);
+}
+
+static INLINE void mem_writed_inline(PhysPt address,Bit32u val) {
+       if ((address & 0xfff)<0xffd) {
+               HostPt tlb_addr=get_tlb_write(address);
+               if (tlb_addr) host_writed(tlb_addr+address,val);
+               else (get_tlb_writehandler(address))->writed(address,val);
+       } else mem_unalignedwrited(address,val);
+}
+
+
+static INLINE bool mem_readb_checked(PhysPt address, Bit8u * val) {
+       HostPt tlb_addr=get_tlb_read(address);
+       if (tlb_addr) {
+               *val=host_readb(tlb_addr+address);
+               return false;
+       } else return (get_tlb_readhandler(address))->readb_checked(address, val);
+}
+
+static INLINE bool mem_readw_checked(PhysPt address, Bit16u * val) {
+       if ((address & 0xfff)<0xfff) {
+               HostPt tlb_addr=get_tlb_read(address);
+               if (tlb_addr) {
+                       *val=host_readw(tlb_addr+address);
+                       return false;
+               } else return (get_tlb_readhandler(address))->readw_checked(address, val);
+       } else return mem_unalignedreadw_checked(address, val);
+}
+
+static INLINE bool mem_readd_checked(PhysPt address, Bit32u * val) {
+       if ((address & 0xfff)<0xffd) {
+               HostPt tlb_addr=get_tlb_read(address);
+               if (tlb_addr) {
+                       *val=host_readd(tlb_addr+address);
+                       return false;
+               } else return (get_tlb_readhandler(address))->readd_checked(address, val);
+       } else return mem_unalignedreadd_checked(address, val);
+}
+
+static INLINE bool mem_writeb_checked(PhysPt address,Bit8u val) {
+       HostPt tlb_addr=get_tlb_write(address);
+       if (tlb_addr) {
+               host_writeb(tlb_addr+address,val);
+               return false;
+       } else return (get_tlb_writehandler(address))->writeb_checked(address,val);
+}
+
+static INLINE bool mem_writew_checked(PhysPt address,Bit16u val) {
+       if ((address & 0xfff)<0xfff) {
+               HostPt tlb_addr=get_tlb_write(address);
+               if (tlb_addr) {
+                       host_writew(tlb_addr+address,val);
+                       return false;
+               } else return (get_tlb_writehandler(address))->writew_checked(address,val);
+       } else return mem_unalignedwritew_checked(address,val);
+}
+
+static INLINE bool mem_writed_checked(PhysPt address,Bit32u val) {
+       if ((address & 0xfff)<0xffd) {
+               HostPt tlb_addr=get_tlb_write(address);
+               if (tlb_addr) {
+                       host_writed(tlb_addr+address,val);
+                       return false;
+               } else return (get_tlb_writehandler(address))->writed_checked(address,val);
+       } else return mem_unalignedwrited_checked(address,val);
+}
+
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/pci_bus.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/pci_bus.h
new file mode 100644 (file)
index 0000000..f8b729e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_PCI_H
+#define DOSBOX_PCI_H
+
+//#define PCI_FUNCTIONALITY_ENABLED 0
+
+#if defined PCI_FUNCTIONALITY_ENABLED
+
+#define PCI_MAX_PCIDEVICES             10
+#define PCI_MAX_PCIFUNCTIONS   8
+
+
+class PCI_Device {
+private:
+       Bits pci_id, pci_subfunction;
+       Bit16u vendor_id, device_id;
+
+       // subdevices declarations, they will respond to pci functions 1 to 7
+       // (main device is attached to function 0)
+       Bitu num_subdevices;
+       PCI_Device* subdevices[PCI_MAX_PCIFUNCTIONS-1];
+
+public:
+       PCI_Device(Bit16u vendor, Bit16u device);
+
+       Bits PCIId(void) {
+               return pci_id;
+       }
+       Bits PCISubfunction(void) {
+               return pci_subfunction;
+       }
+       Bit16u VendorID(void) {
+               return vendor_id;
+       }
+       Bit16u DeviceID(void) {
+               return device_id;
+       }
+
+       void SetPCIId(Bitu number, Bits subfct);
+
+       bool AddSubdevice(PCI_Device* dev);
+       void RemoveSubdevice(Bits subfct);
+
+       PCI_Device* GetSubdevice(Bits subfct);
+
+       Bit16u NumSubdevices(void) {
+               if (num_subdevices>PCI_MAX_PCIFUNCTIONS-1) return (Bit16u)(PCI_MAX_PCIFUNCTIONS-1);
+               return (Bit16u)num_subdevices;
+       }
+
+       Bits GetNextSubdeviceNumber(void) {
+               if (num_subdevices>=PCI_MAX_PCIFUNCTIONS-1) return -1;
+               return (Bits)num_subdevices+1;
+       }
+
+       virtual Bits ParseReadRegister(Bit8u regnum)=0;
+       virtual bool OverrideReadRegister(Bit8u regnum, Bit8u* rval, Bit8u* rval_mask)=0;
+       virtual Bits ParseWriteRegister(Bit8u regnum,Bit8u value)=0;
+       virtual bool InitializeRegisters(Bit8u registers[256])=0;
+
+};
+
+bool PCI_IsInitialized();
+
+RealPt PCI_GetPModeInterface(void);
+
+#endif
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/pic.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/pic.h
new file mode 100644 (file)
index 0000000..77691f2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_PIC_H
+#define DOSBOX_PIC_H
+
+
+/* CPU Cycle Timing */
+extern Bit32s CPU_Cycles;
+extern Bit32s CPU_CycleLeft;
+extern Bit32s CPU_CycleMax;
+
+typedef void (PIC_EOIHandler) (void);
+typedef void (* PIC_EventHandler)(Bitu val);
+
+
+extern Bitu PIC_IRQCheck;
+extern Bitu PIC_Ticks;
+
+static INLINE float PIC_TickIndex(void) {
+       return (CPU_CycleMax-CPU_CycleLeft-CPU_Cycles)/(float)CPU_CycleMax;
+}
+
+static INLINE Bits PIC_TickIndexND(void) {
+       return CPU_CycleMax-CPU_CycleLeft-CPU_Cycles;
+}
+
+static INLINE Bits PIC_MakeCycles(double amount) {
+       return (Bits)(CPU_CycleMax*amount);
+}
+
+static INLINE double PIC_FullIndex(void) {
+       return PIC_Ticks+(double)PIC_TickIndex();
+}
+
+void PIC_ActivateIRQ(Bitu irq);
+void PIC_DeActivateIRQ(Bitu irq);
+
+void PIC_runIRQs(void);
+bool PIC_RunQueue(void);
+
+//Delay in milliseconds
+void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val=0);
+void PIC_RemoveEvents(PIC_EventHandler handler);
+void PIC_RemoveSpecificEvents(PIC_EventHandler handler, Bitu val);
+
+void PIC_SetIRQMask(Bitu irq, bool masked);
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/programs.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/programs.h
new file mode 100644 (file)
index 0000000..04db83c
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_PROGRAMS_H
+#define DOSBOX_PROGRAMS_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+#ifndef DOSBOX_DOS_INC_H
+#include "dos_inc.h"
+#endif
+
+#ifndef CH_LIST
+#define CH_LIST
+#include <list>
+#endif
+
+#ifndef CH_STRING
+#define CH_STRING
+#include <string>
+#endif
+
+class CommandLine {
+public:
+       CommandLine(int argc,char const * const argv[]);
+       CommandLine(char const * const name,char const * const cmdline);
+       const char * GetFileName(){ return file_name.c_str();}
+
+       bool FindExist(char const * const name,bool remove=false);
+       bool FindHex(char const * const name,int & value,bool remove=false);
+       bool FindInt(char const * const name,int & value,bool remove=false);
+       bool FindString(char const * const name,std::string & value,bool remove=false);
+       bool FindCommand(unsigned int which,std::string & value);
+       bool FindStringBegin(char const * const begin,std::string & value, bool remove=false);
+       bool FindStringRemain(char const * const name,std::string & value);
+       bool FindStringRemainBegin(char const * const name,std::string & value);
+       bool GetStringRemain(std::string & value);
+       int GetParameterFromList(const char* const params[], std::vector<std::string> & output);
+       void FillVector(std::vector<std::string> & vector);
+       unsigned int GetCount(void);
+       void Shift(unsigned int amount=1);
+       Bit16u Get_arglength();
+
+private:
+       typedef std::list<std::string>::iterator cmd_it;
+       std::list<std::string> cmds;
+       std::string file_name;
+       bool FindEntry(char const * const name,cmd_it & it,bool neednext=false);
+};
+
+class Program {
+public:
+       Program();
+       virtual ~Program(){
+               delete cmd;
+               delete psp;
+       }
+       std::string temp_line;
+       CommandLine * cmd;
+       DOS_PSP * psp;
+       virtual void Run(void)=0;
+       bool GetEnvStr(const char * entry,std::string & result);
+       bool GetEnvNum(Bitu num,std::string & result);
+       Bitu GetEnvCount(void);
+       bool SetEnv(const char * entry,const char * new_string);
+       void WriteOut(const char * format,...);                         /* Write to standard output */
+       void WriteOut_NoParsing(const char * format);                           /* Write to standard output, no parsing */
+       void ChangeToLongCmd();
+
+};
+
+typedef void (PROGRAMS_Main)(Program * * make);
+void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/regs.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/regs.h
new file mode 100644 (file)
index 0000000..259ab69
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_REGS_H
+#define DOSBOX_REGS_H
+
+#ifndef DOSBOX_MEM_H
+#include "mem.h"
+#endif
+
+#define FLAG_CF                0x00000001
+#define FLAG_PF                0x00000004
+#define FLAG_AF                0x00000010
+#define FLAG_ZF                0x00000040
+#define FLAG_SF                0x00000080
+#define FLAG_OF                0x00000800
+
+#define FLAG_TF                0x00000100
+#define FLAG_IF                0x00000200
+#define FLAG_DF                0x00000400
+
+#define FLAG_IOPL      0x00003000
+#define FLAG_NT                0x00004000
+#define FLAG_VM                0x00020000
+#define FLAG_AC                0x00040000
+#define FLAG_ID                0x00200000
+
+#define FMASK_TEST             (FLAG_CF | FLAG_PF | FLAG_AF | FLAG_ZF | FLAG_SF | FLAG_OF)
+#define FMASK_NORMAL   (FMASK_TEST | FLAG_DF | FLAG_TF | FLAG_IF )     
+#define FMASK_ALL              (FMASK_NORMAL | FLAG_IOPL | FLAG_NT)
+
+#define SETFLAGBIT(TYPE,TEST) if (TEST) reg_flags|=FLAG_ ## TYPE; else reg_flags&=~FLAG_ ## TYPE
+
+#define GETFLAG(TYPE) (reg_flags & FLAG_ ## TYPE)
+#define GETFLAGBOOL(TYPE) ((reg_flags & FLAG_ ## TYPE) ? true : false )
+
+#define GETFLAG_IOPL ((reg_flags & FLAG_IOPL) >> 12)
+
+struct Segment {
+       Bit16u val;
+       PhysPt phys;                                                    /* The phyiscal address start in emulated machine */
+};
+
+enum SegNames { es=0,cs,ss,ds,fs,gs};
+
+struct Segments {
+       Bit16u val[8];
+       PhysPt phys[8];
+};
+
+union GenReg32 {
+       Bit32u dword[1];
+       Bit16u word[2];
+       Bit8u byte[4];
+};
+
+#ifdef WORDS_BIGENDIAN
+
+#define DW_INDEX 0
+#define W_INDEX 1
+#define BH_INDEX 2
+#define BL_INDEX 3
+
+#else
+
+#define DW_INDEX 0
+#define W_INDEX 0
+#define BH_INDEX 1
+#define BL_INDEX 0
+
+#endif
+
+struct CPU_Regs {
+       GenReg32 regs[8],ip;
+       Bitu flags;
+};
+
+extern Segments Segs;
+extern CPU_Regs cpu_regs;
+
+static INLINE PhysPt SegPhys(SegNames index) {
+       return Segs.phys[index];
+}
+
+static INLINE Bit16u SegValue(SegNames index) {
+       return (Bit16u)Segs.val[index];
+}
+       
+static INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) {
+       return RealMake(SegValue(index),off);   
+}
+
+
+static INLINE void SegSet16(Bitu index,Bit16u val) {
+       Segs.val[index]=val;
+       Segs.phys[index]=val << 4;
+}
+
+enum {
+       REGI_AX, REGI_CX, REGI_DX, REGI_BX,
+       REGI_SP, REGI_BP, REGI_SI, REGI_DI
+};
+
+enum {
+       REGI_AL, REGI_CL, REGI_DL, REGI_BL,
+       REGI_AH, REGI_CH, REGI_DH, REGI_BH
+};
+
+
+//macros to convert a 3-bit register index to the correct register
+#define reg_8l(reg) (cpu_regs.regs[(reg)].byte[BL_INDEX])
+#define reg_8h(reg) (cpu_regs.regs[(reg)].byte[BH_INDEX])
+#define reg_8(reg) ((reg) & 4 ? reg_8h((reg) & 3) : reg_8l((reg) & 3))
+#define reg_16(reg) (cpu_regs.regs[(reg)].word[W_INDEX])
+#define reg_32(reg) (cpu_regs.regs[(reg)].dword[DW_INDEX])
+
+#define reg_al cpu_regs.regs[REGI_AX].byte[BL_INDEX]
+#define reg_ah cpu_regs.regs[REGI_AX].byte[BH_INDEX]
+#define reg_ax cpu_regs.regs[REGI_AX].word[W_INDEX]
+#define reg_eax cpu_regs.regs[REGI_AX].dword[DW_INDEX]
+
+#define reg_bl cpu_regs.regs[REGI_BX].byte[BL_INDEX]
+#define reg_bh cpu_regs.regs[REGI_BX].byte[BH_INDEX]
+#define reg_bx cpu_regs.regs[REGI_BX].word[W_INDEX]
+#define reg_ebx cpu_regs.regs[REGI_BX].dword[DW_INDEX]
+
+#define reg_cl cpu_regs.regs[REGI_CX].byte[BL_INDEX]
+#define reg_ch cpu_regs.regs[REGI_CX].byte[BH_INDEX]
+#define reg_cx cpu_regs.regs[REGI_CX].word[W_INDEX]
+#define reg_ecx cpu_regs.regs[REGI_CX].dword[DW_INDEX]
+
+#define reg_dl cpu_regs.regs[REGI_DX].byte[BL_INDEX]
+#define reg_dh cpu_regs.regs[REGI_DX].byte[BH_INDEX]
+#define reg_dx cpu_regs.regs[REGI_DX].word[W_INDEX]
+#define reg_edx cpu_regs.regs[REGI_DX].dword[DW_INDEX]
+
+#define reg_si cpu_regs.regs[REGI_SI].word[W_INDEX]
+#define reg_esi cpu_regs.regs[REGI_SI].dword[DW_INDEX]
+
+#define reg_di cpu_regs.regs[REGI_DI].word[W_INDEX]
+#define reg_edi cpu_regs.regs[REGI_DI].dword[DW_INDEX]
+
+#define reg_sp cpu_regs.regs[REGI_SP].word[W_INDEX]
+#define reg_esp cpu_regs.regs[REGI_SP].dword[DW_INDEX]
+
+#define reg_bp cpu_regs.regs[REGI_BP].word[W_INDEX]
+#define reg_ebp cpu_regs.regs[REGI_BP].dword[DW_INDEX]
+
+#define reg_ip cpu_regs.ip.word[W_INDEX]
+#define reg_eip cpu_regs.ip.dword[DW_INDEX]
+
+#define reg_flags cpu_regs.flags
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/render.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/render.h
new file mode 100644 (file)
index 0000000..f2c5347
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_RENDER_H
+#define DOSBOX_RENDER_H
+
+// 0: complex scalers off, scaler cache off, some simple scalers off, memory requirements reduced
+// 1: complex scalers off, scaler cache off, all simple scalers on
+// 2: complex scalers off, scaler cache on
+// 3: complex scalers on
+#define RENDER_USE_ADVANCED_SCALERS 3
+
+#include "../src/gui/render_scalers.h"
+
+#define RENDER_SKIP_CACHE      16
+//Enable this for scalers to support 0 input for empty lines
+//#define RENDER_NULL_INPUT
+
+typedef struct {
+       struct { 
+               Bit8u red;
+               Bit8u green;
+               Bit8u blue;
+               Bit8u unused;
+       } rgb[256];
+       union {
+               Bit16u b16[256];
+               Bit32u b32[256];
+       } lut;
+       bool changed;
+       Bit8u modified[256];
+       Bitu first;
+       Bitu last;
+} RenderPal_t;
+
+typedef struct {
+       struct {
+               Bitu width, start;
+               Bitu height;
+               Bitu bpp;
+               bool dblw,dblh;
+               double ratio;
+               float fps;
+       } src;
+       struct {
+               Bitu count;
+               Bitu max;
+               Bitu index;
+               Bit8u hadSkip[RENDER_SKIP_CACHE];
+       } frameskip;
+       struct {
+               Bitu size;
+               scalerMode_t inMode;
+               scalerMode_t outMode;
+               scalerOperation_t op;
+               bool clearCache;
+               bool forced;
+               ScalerLineHandler_t lineHandler;
+               ScalerLineHandler_t linePalHandler;
+               ScalerComplexHandler_t complexHandler;
+               Bitu blocks, lastBlock;
+               Bitu outPitch;
+               Bit8u *outWrite;
+               Bitu cachePitch;
+               Bit8u *cacheRead;
+               Bitu inHeight, inLine, outLine;
+       } scale;
+       RenderPal_t pal;
+       bool updating;
+       bool active;
+       bool aspect;
+       bool fullFrame;
+} Render_t;
+
+extern Render_t render;
+extern ScalerLineHandler_t RENDER_DrawLine;
+void RENDER_SetSize(Bitu width,Bitu height,Bitu bpp,float fps,double ratio,bool dblw,bool dblh);
+bool RENDER_StartUpdate(void);
+void RENDER_EndUpdate(bool abort);
+void RENDER_SetPal(Bit8u entry,Bit8u red,Bit8u green,Bit8u blue);
+
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/serialport.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/serialport.h
new file mode 100644 (file)
index 0000000..b4641cc
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_SERIALPORT_H
+#define DOSBOX_SERIALPORT_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+#ifndef DOSBOX_INOUT_H
+#include "inout.h"
+#endif
+#ifndef DOSBOX_TIMER_H
+#include "timer.h"
+#endif
+#ifndef DOSBOX_DOS_INC_H
+#include "dos_inc.h"
+#endif
+#ifndef DOSBOX_PROGRAMS_H
+#include "programs.h"
+#endif
+
+// set this to 1 for serial debugging in release mode
+#define SERIAL_DBG_FORCED 0
+
+#if (C_DEBUG || SERIAL_DBG_FORCED)
+#define SERIAL_DEBUG 1
+#endif
+
+#if SERIAL_DEBUG
+#include "hardware.h"
+#endif
+
+// Serial port interface 
+
+class MyFifo {
+public:
+       MyFifo(Bitu maxsize_) {
+               maxsize=size=maxsize_;
+               pos=used=0;
+               data=new Bit8u[size];
+       }
+       ~MyFifo() {
+               delete[] data;
+       }
+       INLINE Bitu getFree(void) {
+               return size-used;
+       }
+       bool isEmpty() {
+               return used==0;
+       }
+       bool isFull() {
+               return (size-used)==0;
+       }
+
+       INLINE Bitu getUsage(void) {
+               return used;
+       }
+       void setSize(Bitu newsize)
+       {
+               size=newsize;
+               pos=used=0;
+       }
+       void clear(void) {
+               pos=used=0;
+               data[0]=0;
+       }
+
+       bool addb(Bit8u _val) {
+               Bitu where=pos+used;
+               if (where>=size) where-=size;
+               if(used>=size) {
+                       // overwrite last byte
+                       if(where==0) where=size-1;
+                       else where--;
+                       data[where]=_val;
+                       return false;
+               }
+               data[where]=_val;
+               used++;
+               return true;
+       }
+       Bit8u getb() {
+               if (!used) return data[pos];
+               Bitu where=pos;
+               used--;
+               if(used) pos++;
+               if (pos>=size) pos-=size;
+               return data[where];
+       }
+       Bit8u getTop() {
+               Bitu where=pos+used;
+               if (where>=size) where-=size;
+               if(used>=size) {
+                       if(where==0) where=size-1;
+                       else where--;
+               }
+               return data[where];
+       }
+
+       Bit8u probeByte() {
+               return data[pos];
+       }
+private:
+       Bit8u * data;
+       Bitu maxsize,size,pos,used;
+};
+
+class CSerial {
+public:
+
+#if SERIAL_DEBUG
+       FILE * debugfp;
+       bool dbg_modemcontrol; // RTS,CTS,DTR,DSR,RI,CD
+       bool dbg_serialtraffic;
+       bool dbg_register;
+       bool dbg_interrupt;
+       bool dbg_aux;
+       void log_ser(bool active, char const* format,...);
+#endif
+
+       static bool getBituSubstring(const char* name,Bitu* data, CommandLine* cmd);
+
+       bool InstallationSuccessful;// check after constructing. If
+                                                               // something was wrong, delete it right away.
+
+       // Constructor takes com port number (0-3)
+       CSerial(Bitu id, CommandLine* cmd);
+       
+       virtual ~CSerial();
+               
+       IO_ReadHandleObject ReadHandler[8];
+       IO_WriteHandleObject WriteHandler[8];
+
+       float bytetime; // how long a byte takes to transmit/receive in milliseconds
+       void changeLineProperties();
+       Bitu idnumber;
+
+       void setEvent(Bit16u type, float duration);
+       void removeEvent(Bit16u type);
+       void handleEvent(Bit16u type);
+       virtual void handleUpperEvent(Bit16u type)=0;
+       
+       // defines for event type
+#define SERIAL_TX_LOOPBACK_EVENT 0
+#define SERIAL_THR_LOOPBACK_EVENT 1
+#define SERIAL_ERRMSG_EVENT 2
+
+#define SERIAL_TX_EVENT 3
+#define SERIAL_RX_EVENT 4
+#define SERIAL_POLLING_EVENT 5
+#define SERIAL_THR_EVENT 6
+#define SERIAL_RX_TIMEOUT_EVENT 7
+
+#define        SERIAL_BASE_EVENT_COUNT 7
+
+#define COMNUMBER idnumber+1
+
+       Bitu irq;
+       
+       // CSerial requests an update of the input lines
+       virtual void updateMSR()=0;
+
+       // Control lines from prepherial to serial port
+       bool getDTR();
+       bool getRTS();
+
+       bool getRI();
+       bool getCD();
+       bool getDSR();
+       bool getCTS();
+
+       void setRI(bool value);
+       void setDSR(bool value);
+       void setCD(bool value);
+       void setCTS(bool value);
+
+       // From serial port to prepherial
+       // set output lines
+       virtual void setRTSDTR(bool rts, bool dtr)=0;
+       virtual void setRTS(bool val)=0;
+       virtual void setDTR(bool val)=0;
+
+       // Register access
+       void Write_THR(Bit8u data);
+       void Write_IER(Bit8u data);
+       void Write_FCR(Bit8u data);
+       void Write_LCR(Bit8u data);
+       void Write_MCR(Bit8u data);
+       // Really old hardware seems to have the delta part of this register writable
+       void Write_MSR(Bit8u data);
+       void Write_SPR(Bit8u data);
+       void Write_reserved(Bit8u data, Bit8u address);
+
+       Bitu Read_RHR();
+       Bitu Read_IER();
+       Bitu Read_ISR();
+       Bitu Read_LCR();
+       Bitu Read_MCR();
+       Bitu Read_LSR();
+       Bitu Read_MSR();
+       Bitu Read_SPR();
+       
+       // If a byte comes from loopback or prepherial, put it in here.
+       void receiveByte(Bit8u data);
+       void receiveByteEx(Bit8u data, Bit8u error);
+
+       // If an error was received, put it here (in LSR register format)
+       void receiveError(Bit8u errorword);
+
+       // depratched
+       // connected device checks, if port can receive data:
+       bool CanReceiveByte();
+       
+       // when THR was shifted to TX
+       void ByteTransmitting();
+       
+       // When done sending, notify here
+       void ByteTransmitted();
+
+       // Transmit byte to prepherial
+       virtual void transmitByte(Bit8u val, bool first)=0;
+
+       // switch break state to the passed value
+       virtual void setBreak(bool value)=0;
+       
+       // change baudrate, number of bits, parity, word length al at once
+       virtual void updatePortConfig(Bit16u divider, Bit8u lcr)=0;
+       
+       void Init_Registers();
+       
+       bool Putchar(Bit8u data, bool wait_dtr, bool wait_rts, Bitu timeout);
+       bool Getchar(Bit8u* data, Bit8u* lsr, bool wait_dsr, Bitu timeout);
+
+
+private:
+
+       DOS_Device* mydosdevice;
+
+       // I used this spec: st16c450v420.pdf
+
+       void ComputeInterrupts();
+       
+       // a sub-interrupt is triggered
+       void rise(Bit8u priority);
+
+       // clears the pending sub-interrupt
+       void clear(Bit8u priority);
+       
+       #define ERROR_PRIORITY 4        // overrun, parity error, frame error, break
+       #define RX_PRIORITY 1           // a byte has been received
+       #define TX_PRIORITY 2           // tx buffer has become empty
+       #define MSR_PRIORITY 8          // CRS, DSR, RI, DCD change 
+       #define TIMEOUT_PRIORITY 0x10
+       #define NONE_PRIORITY 0
+
+       Bit8u waiting_interrupts;       // these are on, but maybe not enabled
+       
+       // 16C550
+       //                              read/write              name
+
+       Bit16u baud_divider;
+       #define RHR_OFFSET 0    // r Receive Holding Register, also LSB of Divisor Latch (r/w)
+                                                       // Data: whole byte
+       #define THR_OFFSET 0    // w Transmit Holding Register
+                                                       // Data: whole byte
+       Bit8u IER;      //      r/w             Interrupt Enable Register, also MSB of Divisor Latch
+       #define IER_OFFSET 1
+
+       bool irq_active;
+                               
+       #define RHR_INT_Enable_MASK                             0x1
+       #define THR_INT_Enable_MASK                             0x2
+       #define Receive_Line_INT_Enable_MASK    0x4
+       #define Modem_Status_INT_Enable_MASK    0x8
+
+       Bit8u ISR;      //      r                               Interrupt Status Register
+       #define ISR_OFFSET 2
+
+       #define ISR_CLEAR_VAL 0x1
+       #define ISR_FIFOTIMEOUT_VAL 0xc
+       #define ISR_ERROR_VAL 0x6
+       #define ISR_RX_VAL 0x4
+       #define ISR_TX_VAL 0x2
+       #define ISR_MSR_VAL 0x0
+public:        
+       Bit8u LCR;      //      r/w                             Line Control Register
+private:
+       #define LCR_OFFSET 3
+                                               // bit0: word length bit0
+                                               // bit1: word length bit1
+                                               // bit2: stop bits
+                                               // bit3: parity enable
+                                               // bit4: even parity
+                                               // bit5: set parity
+                                               // bit6: set break
+                                               // bit7: divisor latch enable
+
+       
+       #define LCR_BREAK_MASK 0x40
+       #define LCR_DIVISOR_Enable_MASK 0x80
+       #define LCR_PORTCONFIG_MASK 0x3F
+       
+       #define LCR_PARITY_NONE         0x0
+       #define LCR_PARITY_ODD          0x8
+       #define LCR_PARITY_EVEN         0x18
+       #define LCR_PARITY_MARK         0x28
+       #define LCR_PARITY_SPACE        0x38
+
+       #define LCR_DATABITS_5          0x0
+       #define LCR_DATABITS_6          0x1
+       #define LCR_DATABITS_7          0x2
+       #define LCR_DATABITS_8          0x3
+
+       #define LCR_STOPBITS_1          0x0
+       #define LCR_STOPBITS_MORE_THAN_1 0x4
+
+       // Modem Control Register
+       // r/w                          
+       #define MCR_OFFSET 4
+       bool dtr;                       // bit0: DTR
+       bool rts;                       // bit1: RTS
+       bool op1;                       // bit2: OP1
+       bool op2;                       // bit3: OP2
+       bool loopback;          // bit4: loop back enable
+
+       #define MCR_DTR_MASK 0x1
+       #define MCR_RTS_MASK 0x2        
+       #define MCR_OP1_MASK 0x4        
+       #define MCR_OP2_MASK 0x8
+       #define MCR_LOOPBACK_Enable_MASK 0x10
+public:        
+       Bit8u LSR;      //      r                               Line Status Register
+private:
+
+       #define LSR_OFFSET 5
+
+       #define LSR_RX_DATA_READY_MASK 0x1
+       #define LSR_OVERRUN_ERROR_MASK 0x2
+       #define LSR_PARITY_ERROR_MASK 0x4
+       #define LSR_FRAMING_ERROR_MASK 0x8
+       #define LSR_RX_BREAK_MASK 0x10
+       #define LSR_TX_HOLDING_EMPTY_MASK 0x20
+       #define LSR_TX_EMPTY_MASK 0x40
+
+       #define LSR_ERROR_MASK 0x1e
+
+       // error printing
+       bool errormsg_pending;
+       Bitu framingErrors;
+       Bitu parityErrors;
+       Bitu overrunErrors;
+       Bitu txOverrunErrors;
+       Bitu overrunIF0;
+       Bitu breakErrors;
+
+
+       // Modem Status Register
+       //      r
+       #define MSR_OFFSET 6
+       bool d_cts;                     // bit0: deltaCTS
+       bool d_dsr;                     // bit1: deltaDSR
+       bool d_ri;                      // bit2: deltaRI
+       bool d_cd;                      // bit3: deltaCD
+       bool cts;                       // bit4: CTS
+       bool dsr;                       // bit5: DSR
+       bool ri;                        // bit6: RI
+       bool cd;                        // bit7: CD
+       
+       #define MSR_delta_MASK 0xf
+       #define MSR_LINE_MASK 0xf0
+
+       #define MSR_dCTS_MASK 0x1
+       #define MSR_dDSR_MASK 0x2
+       #define MSR_dRI_MASK 0x4
+       #define MSR_dCD_MASK 0x8
+       #define MSR_CTS_MASK 0x10
+       #define MSR_DSR_MASK 0x20
+       #define MSR_RI_MASK 0x40
+       #define MSR_CD_MASK 0x80
+
+       Bit8u SPR;      //      r/w                             Scratchpad Register
+       #define SPR_OFFSET 7
+
+
+       // For loopback purposes...
+       Bit8u loopback_data;
+       void transmitLoopbackByte(Bit8u val, bool value);
+
+       // 16C550 (FIFO)
+       public: // todo remove
+       MyFifo* rxfifo;
+       private:
+       MyFifo* txfifo;
+       MyFifo* errorfifo;
+       Bitu errors_in_fifo;
+       Bitu rx_interrupt_threshold;
+       Bitu fifosize;
+       Bit8u FCR;
+       bool sync_guardtime;
+       #define FIFO_STATUS_ACTIVE 0xc0 // FIFO is active AND works ;)
+       #define FIFO_ERROR 0x80
+       #define FCR_ACTIVATE 0x01
+       #define FCR_CLEAR_RX 0x02
+       #define FCR_CLEAR_TX 0x04
+       #define FCR_OFFSET 2
+       #define FIFO_FLOWCONTROL 0x20
+};
+
+extern CSerial* serialports[];
+const Bit8u serial_defaultirq[] = { 4, 3, 4, 3 };
+const Bit16u serial_baseaddr[] = {0x3f8,0x2f8,0x3e8,0x2e8};
+const char* const serial_comname[]={"COM1","COM2","COM3","COM4"};
+
+// the COM devices
+
+class device_COM : public DOS_Device {
+public:
+       // Creates a COM device that communicates with the num-th parallel port, i.e. is LPTnum
+       device_COM(class CSerial* sc);
+       ~device_COM();
+       bool Read(Bit8u * data,Bit16u * size);
+       bool Write(Bit8u * data,Bit16u * size);
+       bool Seek(Bit32u * pos,Bit32u type);
+       bool Close();
+       Bit16u GetInformation(void);
+private:
+       CSerial* sclass;
+};
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/setup.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/setup.h
new file mode 100644 (file)
index 0000000..7dc9f40
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_SETUP_H
+#define DOSBOX_SETUP_H
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4290 )
+#endif
+
+
+#ifndef CH_LIST
+#define CH_LIST
+#include <list>
+#endif
+
+#ifndef CH_VECTOR
+#define CH_VECTOR
+#include <vector>
+#endif
+
+#ifndef CH_STRING
+#define CH_STRING
+#include <string>
+#endif
+
+#ifndef CH_CSTDIO
+#define CH_CSTDIO
+#include <cstdio>
+#endif
+
+
+class Hex {
+private:
+       int _hex;
+public:
+       Hex(int in):_hex(in) { };
+       Hex():_hex(0) { };
+       bool operator==(Hex const& other) {return _hex == other._hex;}
+       operator int () const { return _hex; }
+   
+};
+
+class Value {
+/* 
+ * Multitype storage container that is aware of the currently stored type in it.
+ * Value st = "hello";
+ * Value in = 1;
+ * st = 12 //Exception
+ * in = 12 //works
+ */
+private:
+       Hex _hex;
+       bool _bool;
+       int _int;
+       std::string* _string;
+       double _double;
+public:
+       class WrongType { }; // Conversion error class
+       enum Etype { V_NONE, V_HEX, V_BOOL, V_INT, V_STRING, V_DOUBLE,V_CURRENT} type;
+       
+       /* Constructors */
+       Value()                      :_string(0),   type(V_NONE)                  { };
+       Value(Hex in)                :_hex(in),     type(V_HEX)                   { };
+       Value(int in)                :_int(in),     type(V_INT)                   { };
+       Value(bool in)               :_bool(in),    type(V_BOOL)                  { };
+       Value(double in)             :_double(in),  type(V_DOUBLE)                { };
+       Value(std::string const& in) :_string(new std::string(in)),type(V_STRING) { };
+       Value(char const * const in) :_string(new std::string(in)),type(V_STRING) { };
+       Value(Value const& in):_string(0) {plaincopy(in);}
+       ~Value() { destroy();};
+       Value(std::string const& in,Etype _t) :_hex(0),_bool(false),_int(0),_string(0),_double(0),type(V_NONE) {SetValue(in,_t);}
+       
+       /* Assigment operators */
+       Value& operator= (Hex in) throw(WrongType)                { return copy(Value(in));}
+       Value& operator= (int in) throw(WrongType)                { return copy(Value(in));}
+       Value& operator= (bool in) throw(WrongType)               { return copy(Value(in));}
+       Value& operator= (double in) throw(WrongType)             { return copy(Value(in));}
+       Value& operator= (std::string const& in) throw(WrongType) { return copy(Value(in));}
+       Value& operator= (char const * const in) throw(WrongType) { return copy(Value(in));}
+       Value& operator= (Value const& in) throw(WrongType)       { return copy(Value(in));}
+
+       bool operator== (Value const & other);
+       operator bool () const throw(WrongType);
+       operator Hex () const throw(WrongType);
+       operator int () const throw(WrongType);
+       operator double () const throw(WrongType);
+       operator char const* () const throw(WrongType);
+       bool SetValue(std::string const& in,Etype _type = V_CURRENT) throw(WrongType);
+       std::string ToString() const;
+
+private:
+       void destroy() throw();
+       Value& copy(Value const& in) throw(WrongType);
+       void plaincopy(Value const& in) throw();
+       bool set_hex(std::string const& in);
+       bool set_int(std::string const&in);
+       bool set_bool(std::string const& in);
+       void set_string(std::string const& in);
+       bool set_double(std::string const& in);
+};
+
+class Property {
+public:
+       struct Changeable { enum Value {Always, WhenIdle,OnlyAtStart};};
+       const std::string propname;
+
+       Property(std::string const& _propname, Changeable::Value when):propname(_propname),change(when) { }
+       void Set_values(const char * const * in);
+       void Set_help(std::string const& str);
+       char const* Get_help();
+       virtual bool SetValue(std::string const& str)=0;
+       Value const& GetValue() const { return value;}
+       Value const& Get_Default_Value() const { return default_value; }
+       //CheckValue returns true, if value is in suggested_values;
+       //Type specific properties are encouraged to override this and check for type
+       //specific features.
+       virtual bool CheckValue(Value const& in, bool warn);
+public:
+       virtual ~Property(){ } 
+       virtual const std::vector<Value>& GetValues() const;
+       Value::Etype Get_type(){return default_value.type;}
+       Changeable::Value getChange() {return change;}
+
+protected:
+       //Set interval value to in or default if in is invalid. force always sets the value.
+       //Can be overriden to set a different value if invalid.
+       virtual bool SetVal(Value const& in, bool forced,bool warn=true) {
+               if(forced || CheckValue(in,warn)) { 
+                       value = in; return true;
+               } else { 
+                       value = default_value; return false;
+               }
+       }
+       Value value;
+       std::vector<Value> suggested_values;
+       typedef std::vector<Value>::iterator iter;
+       Value default_value;
+       const Changeable::Value change;
+};
+
+class Prop_int:public Property {
+public:
+       Prop_int(std::string const& _propname,Changeable::Value when, int _value)
+               :Property(_propname,when) { 
+               default_value = value = _value;
+               min = max = -1;
+       }
+       Prop_int(std::string const&  _propname,Changeable::Value when, int _min,int _max,int _value)
+               :Property(_propname,when) { 
+               default_value = value = _value;
+               min = _min;
+               max = _max;
+       }
+       int getMin() { return min;}
+       int getMax() { return max;}
+       void SetMinMax(Value const& min,Value const& max) {this->min = min; this->max=max;}
+       bool SetValue(std::string const& in);
+       ~Prop_int(){ }
+       virtual bool CheckValue(Value const& in, bool warn);
+       // Override SetVal, so it takes min,max in account when there are no suggested values
+       virtual bool SetVal(Value const& in, bool forced,bool warn=true);
+       
+private:
+       Value min,max;
+};
+
+class Prop_double:public Property {
+public:
+       Prop_double(std::string const & _propname, Changeable::Value when, double _value)
+               :Property(_propname,when){
+               default_value = value = _value;
+       }
+       bool SetValue(std::string const& input);
+       ~Prop_double(){ }
+};
+
+class Prop_bool:public Property {
+public:
+       Prop_bool(std::string const& _propname, Changeable::Value when, bool _value)
+               :Property(_propname,when) { 
+               default_value = value = _value;
+       }
+       bool SetValue(std::string const& in);
+       ~Prop_bool(){ }
+};
+
+class Prop_string:public Property{
+public:
+       Prop_string(std::string const& _propname, Changeable::Value when, char const * const _value)
+               :Property(_propname,when) { 
+               default_value = value = _value;
+       }
+       bool SetValue(std::string const& in);
+       virtual bool CheckValue(Value const& in, bool warn);
+       ~Prop_string(){ }
+};
+class Prop_path:public Prop_string{
+public:
+       std::string realpath;
+       Prop_path(std::string const& _propname, Changeable::Value when, char const * const _value)
+               :Prop_string(_propname,when,_value) { 
+               default_value = value = _value;
+               realpath = _value;
+       }
+       bool SetValue(std::string const& in);
+       ~Prop_path(){ }
+};
+
+class Prop_hex:public Property {
+public:
+       Prop_hex(std::string const& _propname, Changeable::Value when, Hex _value)
+               :Property(_propname,when) { 
+               default_value = value = _value;
+       }
+       bool SetValue(std::string const& in);
+       ~Prop_hex(){ }
+};
+
+#define NO_SUCH_PROPERTY "PROP_NOT_EXIST"
+class Section {
+private:
+       typedef void (*SectionFunction)(Section*);
+       /* Wrapper class around startup and shutdown functions. the variable
+        * canchange indicates it can be called on configuration changes */
+       struct Function_wrapper {
+               SectionFunction function;
+               bool canchange;
+               Function_wrapper(SectionFunction const _fun,bool _ch){
+                       function=_fun;
+                       canchange=_ch;
+               }
+       };
+       std::list<Function_wrapper> initfunctions;
+       std::list<Function_wrapper> destroyfunctions;
+       std::string sectionname;
+public:
+       Section(std::string const& _sectionname):sectionname(_sectionname) {  }
+
+       void AddInitFunction(SectionFunction func,bool canchange=false);
+       void AddDestroyFunction(SectionFunction func,bool canchange=false);
+       void ExecuteInit(bool initall=true);
+       void ExecuteDestroy(bool destroyall=true);
+       const char* GetName() const {return sectionname.c_str();}
+
+       virtual std::string GetPropValue(std::string const& _property) const =0;
+       virtual bool HandleInputline(std::string const& _line)=0;
+       virtual void PrintData(FILE* outfile) const =0;
+       virtual ~Section() { /*Children must call executedestroy ! */}
+};
+
+class Prop_multival;
+class Prop_multival_remain;
+class Section_prop:public Section {
+private:
+       std::list<Property*> properties;
+       typedef std::list<Property*>::iterator it;
+       typedef std::list<Property*>::const_iterator const_it;
+
+public:
+       Section_prop(std::string const&  _sectionname):Section(_sectionname){}
+       Prop_int* Add_int(std::string const& _propname, Property::Changeable::Value when, int _value=0);
+       Prop_string* Add_string(std::string const& _propname, Property::Changeable::Value when, char const * const _value=NULL);
+       Prop_path* Add_path(std::string const& _propname, Property::Changeable::Value when, char const * const _value=NULL);
+       Prop_bool*  Add_bool(std::string const& _propname, Property::Changeable::Value when, bool _value=false);
+       Prop_hex* Add_hex(std::string const& _propname, Property::Changeable::Value when, Hex _value=0);
+//     void Add_double(char const * const _propname, double _value=0.0);   
+       Prop_multival *Add_multi(std::string const& _propname, Property::Changeable::Value when,std::string const& sep);
+       Prop_multival_remain *Add_multiremain(std::string const& _propname, Property::Changeable::Value when,std::string const& sep);
+
+       Property* Get_prop(int index);
+       int Get_int(std::string const& _propname) const;
+       const char* Get_string(std::string const& _propname) const;
+       bool Get_bool(std::string const& _propname) const;
+       Hex Get_hex(std::string const& _propname) const;
+       double Get_double(std::string const& _propname) const;
+       Prop_path* Get_path(std::string const& _propname) const;
+       Prop_multival* Get_multival(std::string const& _propname) const;
+       Prop_multival_remain* Get_multivalremain(std::string const& _propname) const;
+       bool HandleInputline(std::string const& gegevens);
+       void PrintData(FILE* outfile) const;
+       virtual std::string GetPropValue(std::string const& _property) const;
+       //ExecuteDestroy should be here else the destroy functions use destroyed properties
+       virtual ~Section_prop();
+};
+
+class Prop_multival:public Property{
+protected:
+       Section_prop* section;
+       std::string separator;
+       void make_default_value();
+public:
+       Prop_multival(std::string const& _propname, Changeable::Value when,std::string const& sep):Property(_propname,when), section(new Section_prop("")),separator(sep) {
+               default_value = value = "";
+       }
+       Section_prop *GetSection() { return section; }
+       const Section_prop *GetSection() const { return section; }
+       virtual bool SetValue(std::string const& input);
+       virtual const std::vector<Value>& GetValues() const;
+       ~Prop_multival() { delete section; }
+}; //value bevat totale string. setvalue zet elk van de sub properties en checked die.
+
+class Prop_multival_remain:public Prop_multival{
+public:
+       Prop_multival_remain(std::string const& _propname, Changeable::Value when,std::string const& sep):Prop_multival(_propname,when,sep){ }
+
+       virtual bool SetValue(std::string const& input);
+};
+
+   
+class Section_line: public Section{
+public:
+       Section_line(std::string const& _sectionname):Section(_sectionname){}
+       ~Section_line(){ExecuteDestroy(true);}
+       bool HandleInputline(std::string const& gegevens);
+       void PrintData(FILE* outfile) const;
+       virtual std::string GetPropValue(std::string const& _property) const;
+       std::string data;
+};
+
+class Module_base {
+       /* Base for all hardware and software "devices" */
+protected:
+       Section* m_configuration;
+public:
+       Module_base(Section* configuration){m_configuration=configuration;};
+//     Module_base(Section* configuration, SaveState* state) {};
+       virtual ~Module_base(){/*LOG_MSG("executed")*/;};//Destructors are required
+       /* Returns true if succesful.*/
+       virtual bool Change_Config(Section* /*newconfig*/) {return false;} ;
+};
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/shell.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/shell.h
new file mode 100644 (file)
index 0000000..25c984f
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ *  Copyright (C) 2002-2017  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_SHELL_H
+#define DOSBOX_SHELL_H
+
+#include <ctype.h>
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+#ifndef DOSBOX_PROGRAMS_H
+#include "programs.h"
+#endif
+
+#include <string>
+#include <list>
+
+#define CMD_MAXLINE 4096
+#define CMD_MAXCMDS 20
+#define CMD_OLDSIZE 4096
+extern Bitu call_shellstop;
+/* first_shell is used to add and delete stuff from the shell env 
+ * by "external" programs. (config) */
+extern Program * first_shell;
+
+class DOS_Shell;
+
+class BatchFile {
+public:
+       BatchFile(DOS_Shell * host,char const* const resolved_name,char const* const entered_name, char const * const cmd_line);
+       virtual ~BatchFile();
+       virtual bool ReadLine(char * line);
+       bool Goto(char * where);
+       void Shift(void);
+       Bit16u file_handle;
+       Bit32u location;
+       bool echo;
+       DOS_Shell * shell;
+       BatchFile * prev;
+       CommandLine * cmd;
+       std::string filename;
+};
+
+class AutoexecEditor;
+class DOS_Shell : public Program {
+private:
+       friend class AutoexecEditor;
+       std::list<std::string> l_history, l_completion;
+
+       char *completion_start;
+       Bit16u completion_index;
+
+public:
+
+       DOS_Shell();
+
+       void Run(void);
+       void RunInternal(void); //for command /C
+/* A load of subfunctions */
+       void ParseLine(char * line);
+       Bitu GetRedirection(char *s, char **ifn, char **ofn, char **toc, bool * append);
+       void InputCommand(char * line);
+       void ShowPrompt();
+       void DoCommand(char * cmd);
+       bool Execute(char * name,char * args);
+       /* Checks if it matches a hardware-property */
+       bool CheckConfig(char* cmd_in,char*line);
+/* Some internal used functions */
+       char * Which(char * name);
+/* Some supported commands */
+       void CMD_HELP(char * args);
+       void CMD_CHCP(char * args);
+       void CMD_CLS(char * args);
+       void CMD_COPY(char * args);
+       void CMD_DATE(char * args);
+       void CMD_TIME(char * args);
+       void CMD_DIR(char * args);
+       void CMD_DELETE(char * args);
+       void CMD_ECHO(char * args);
+       void CMD_EXIT(char * args);
+       void CMD_MKDIR(char * args);
+       void CMD_CHDIR(char * args);
+       void CMD_RMDIR(char * args);
+       void CMD_SET(char * args);
+       void CMD_IF(char * args);
+       void CMD_FOR(char * args);
+       void CMD_GOTO(char * args);
+       void CMD_TYPE(char * args);
+       void CMD_REM(char * args);
+       void CMD_RENAME(char * args);
+       void CMD_CALL(char * args);
+       void SyntaxError(void);
+       void CMD_PAUSE(char * args);
+       void CMD_SUBST(char* args);
+       void CMD_LOADHIGH(char* args);
+       void CMD_CHOICE(char * args);
+       void CMD_ATTRIB(char * args);
+       void CMD_PROMPT(char * args);
+       void CMD_PATH(char * args);
+       void CMD_SHIFT(char * args);
+       void CMD_VER(char * args);
+       void CMD_CHEV(char * args);
+       /* The shell's variables */
+       Bit16u input_handle;
+       BatchFile * bf;
+       bool echo;
+       bool exit;
+       bool call;
+};
+
+struct SHELL_Cmd {
+       const char * name;                                                              /* Command name*/
+       Bit32u flags;                                                                   /* Flags about the command */
+       void (DOS_Shell::*handler)(char * args);                /* Handler for this command */
+       const char * help;                                                              /* String with command help */
+};
+
+/* Object to manage lines in the autoexec.bat The lines get removed from
+ * the file if the object gets destroyed. The environment is updated
+ * as well if the line set a a variable */
+class AutoexecObject{
+private:
+       bool installed;
+       std::string buf;
+public:
+       AutoexecObject():installed(false){ };
+       void Install(std::string const &in);
+       void InstallBefore(std::string const &in);
+       ~AutoexecObject();
+private:
+       void CreateAutoexec(void);
+};
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/support.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/support.h
new file mode 100644 (file)
index 0000000..e02c3d3
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (C) 2002-2017  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *  Wengier: LFN support
+ */
+
+
+#ifndef DOSBOX_SUPPORT_H
+#define DOSBOX_SUPPORT_H
+
+#include <string.h>
+#include <string>
+#include <ctype.h>
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+
+#if defined (_MSC_VER)                                         /* MS Visual C++ */
+#define        strcasecmp(a,b) stricmp(a,b)
+#define strncasecmp(a,b,n) _strnicmp(a,b,n)
+#endif
+
+#define safe_strncpy(a,b,n) do { strncpy((a),(b),(n)-1); (a)[(n)-1] = 0; } while (0)
+
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
+void strreplace(char * str,char o,char n);
+char *ltrim(char *str);
+char *rtrim(char *str);
+char *trim(char * str);
+char * upcase(char * str);
+char * lowcase(char * str);
+
+bool ScanCMDBool(char * cmd,char const * const check);
+char * ScanCMDRemain(char * cmd);
+char * StripWord(char *&cmd);
+char * StripArg(char *&cmd);
+bool IsDecWord(char * word);
+bool IsHexWord(char * word);
+Bits ConvDecWord(char * word);
+Bits ConvHexWord(char * word);
+
+void upcase(std::string &str);
+void lowcase(std::string &str);
+
+#if defined(LINUX)
+void utf8_to_sjis_copy(char *dst, char *src, int len);
+void sjis_to_utf8_copy(char *dst, char *src, int len);
+void sjis_to_utf16_copy(char *dst, char *src, int len);
+void ChangeUtf8FileName(char *fullname);
+#endif
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/timer.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/timer.h
new file mode 100644 (file)
index 0000000..e8abf32
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_TIMER_H
+#define DOSBOX_TIMER_H
+
+/* underlying clock rate in HZ */
+#include <SDL.h>
+
+#define PIT_TICK_RATE 1193182
+
+#define GetTicks() SDL_GetTicks()
+
+typedef void (*TIMER_TickHandler)(void);
+
+/* Register a function that gets called everytime if 1 or more ticks pass */
+void TIMER_AddTickHandler(TIMER_TickHandler handler);
+void TIMER_DelTickHandler(TIMER_TickHandler handler);
+
+/* This will add 1 milliscond to all timers */
+void TIMER_AddTick(void);
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/vga.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/vga.h
new file mode 100644 (file)
index 0000000..69edc38
--- /dev/null
@@ -0,0 +1,535 @@
+ /*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_VGA_H
+#define DOSBOX_VGA_H
+
+#ifndef DOSBOX_DOSBOX_H
+#include "dosbox.h"
+#endif
+
+//Don't enable keeping changes and mapping lfb probably...
+#define VGA_LFB_MAPPED
+//#define VGA_KEEP_CHANGES
+#define VGA_CHANGE_SHIFT       9
+
+class PageHandler;
+
+
+enum VGAModes {
+       M_CGA2, M_CGA4,
+       M_EGA, M_VGA,
+       M_LIN4, M_LIN8, M_LIN15, M_LIN16, M_LIN32,
+       M_TEXT,
+       M_HERC_GFX, M_HERC_TEXT,
+       M_CGA16, M_TANDY2, M_TANDY4, M_TANDY16, M_TANDY_TEXT,
+       M_DCGA,
+       M_ERROR
+};
+
+
+#define CLK_25 25175
+#define CLK_28 28322
+
+#define MIN_VCO        180000
+#define MAX_VCO 360000
+
+#define S3_CLOCK_REF   14318   /* KHz */
+#define S3_CLOCK(_M,_N,_R)     ((S3_CLOCK_REF * ((_M) + 2)) / (((_N) + 2) * (1 << (_R))))
+#define S3_MAX_CLOCK   150000  /* KHz */
+
+#define S3_XGA_1024            0x00
+#define S3_XGA_1152            0x01
+#define S3_XGA_640             0x40
+#define S3_XGA_800             0x80
+#define S3_XGA_1280            0xc0
+#define S3_XGA_WMASK   (S3_XGA_640|S3_XGA_800|S3_XGA_1024|S3_XGA_1152|S3_XGA_1280)
+
+#define S3_XGA_8BPP  0x00
+#define S3_XGA_16BPP 0x10
+#define S3_XGA_32BPP 0x30
+#define S3_XGA_CMASK (S3_XGA_8BPP|S3_XGA_16BPP|S3_XGA_32BPP)
+
+typedef struct {
+       bool attrindex;
+} VGA_Internal;
+
+typedef struct {
+/* Memory handlers */
+       Bitu mh_mask;
+
+/* Video drawing */
+       Bitu display_start;
+       Bitu real_start;
+       bool retrace;                                   /* A retrace is active */
+       Bitu scan_len;
+       Bitu cursor_start;
+
+/* Some other screen related variables */
+       Bitu line_compare;
+       bool chained;                                   /* Enable or Disabled Chain 4 Mode */
+       bool compatible_chain4;
+
+       /* Pixel Scrolling */
+       Bit8u pel_panning;                              /* Amount of pixels to skip when starting horizontal line */
+       Bit8u hlines_skip;
+       Bit8u bytes_skip;
+       Bit8u addr_shift;
+
+/* Specific stuff memory write/read handling */
+       
+       Bit8u read_mode;
+       Bit8u write_mode;
+       Bit8u read_map_select;
+       Bit8u color_dont_care;
+       Bit8u color_compare;
+       Bit8u data_rotate;
+       Bit8u raster_op;
+
+       Bit32u full_bit_mask;
+       Bit32u full_map_mask;
+       Bit32u full_not_map_mask;
+       Bit32u full_set_reset;
+       Bit32u full_not_enable_set_reset;
+       Bit32u full_enable_set_reset;
+       Bit32u full_enable_and_set_reset;
+} VGA_Config;
+
+typedef enum {
+       PART,
+       DRAWLINE,
+       EGALINE
+} Drawmode;
+
+typedef struct {
+       bool resizing;
+       Bitu width;
+       Bitu height;
+       Bitu blocks;
+       Bitu address;
+       Bitu panning;
+       Bitu bytes_skip;
+       Bit8u *linear_base;
+       Bitu linear_mask;
+       Bitu address_add;
+       Bitu line_length;
+       Bitu address_line_total;
+       Bitu address_line;
+       Bitu lines_total;
+       Bitu vblank_skip;
+       Bitu lines_done;
+       Bitu lines_scaled;
+       Bitu split_line;
+       Bitu parts_total;
+       Bitu parts_lines;
+       Bitu parts_left;
+       Bitu byte_panning_shift;
+       struct {
+               double framestart;
+               double vrstart, vrend;          // V-retrace
+               double hrstart, hrend;          // H-retrace
+               double hblkstart, hblkend;      // H-blanking
+               double vblkstart, vblkend;      // V-Blanking
+               double vdend, vtotal;
+               double hdend, htotal;
+               double parts;
+       } delay;
+       Bitu bpp;
+       double aspect_ratio;
+       bool double_scan;
+       bool doublewidth,doubleheight;
+       Bit8u font[64*1024];
+       Bit8u * font_tables[2];
+       Bitu blinking;
+       bool blink;
+       bool char9dot;
+       struct {
+               Bitu address;
+               Bit8u sline,eline;
+               Bit8u count,delay;
+               Bit8u enabled;
+       } cursor;
+       Drawmode mode;
+       bool vret_triggered;
+       bool vga_override;
+} VGA_Draw;
+
+typedef struct {
+       Bit8u curmode;
+       Bit16u originx, originy;
+       Bit8u fstackpos, bstackpos;
+       Bit8u forestack[4];
+       Bit8u backstack[4];
+       Bit16u startaddr;
+       Bit8u posx, posy;
+       Bit8u mc[64][64];
+} VGA_HWCURSOR;
+
+typedef struct {
+       Bit8u reg_lock1;
+       Bit8u reg_lock2;
+       Bit8u reg_31;
+       Bit8u reg_35;
+       Bit8u reg_36; // RAM size
+       Bit8u reg_3a; // 4/8/doublepixel bit in there
+       Bit8u reg_40; // 8415/A functionality register
+       Bit8u reg_41; // BIOS flags 
+       Bit8u reg_43;
+       Bit8u reg_45; // Hardware graphics cursor
+       Bit8u reg_50;
+       Bit8u reg_51;
+       Bit8u reg_52;
+       Bit8u reg_55;
+       Bit8u reg_58;
+       Bit8u reg_6b; // LFB BIOS scratchpad
+       Bit8u ex_hor_overflow;
+       Bit8u ex_ver_overflow;
+       Bit16u la_window;
+       Bit8u misc_control_2;
+       Bit8u ext_mem_ctrl;
+       Bitu xga_screen_width;
+       VGAModes xga_color_mode;
+       struct {
+               Bit8u r;
+               Bit8u n;
+               Bit8u m;
+       } clk[4],mclk;
+       struct {
+               Bit8u lock;
+               Bit8u cmd;
+       } pll;
+       VGA_HWCURSOR hgc;
+} VGA_S3;
+
+typedef struct {
+       Bit8u mode_control;
+       Bit8u enable_bits;
+} VGA_HERC;
+
+typedef struct {
+       Bit8u index;
+       Bit8u htotal;
+       Bit8u hdend;
+       Bit8u hsyncp;
+       Bit8u hsyncw;
+       Bit8u vtotal;
+       Bit8u vdend;
+       Bit8u vadjust;
+       Bit8u vsyncp;
+       Bit8u vsyncw;
+       Bit8u max_scanline;
+       Bit16u lightpen;
+       bool lightpen_triggered;
+       Bit8u cursor_start;
+       Bit8u cursor_end;
+} VGA_OTHER;
+
+typedef struct {
+       Bit8u pcjr_flipflop;
+       Bit8u mode_control;
+       Bit8u color_select;
+       Bit8u disp_bank;
+       Bit8u reg_index;
+       Bit8u gfx_control;
+       Bit8u palette_mask;
+       Bit8u extended_ram;
+       Bit8u border_color;
+       Bit8u line_mask, line_shift;
+       Bit8u draw_bank, mem_bank;
+       Bit8u *draw_base, *mem_base;
+       Bitu addr_mask;
+} VGA_TANDY;
+
+typedef struct {
+       Bit8u index;
+       Bit8u reset;
+       Bit8u clocking_mode;
+       Bit8u map_mask;
+       Bit8u character_map_select;
+       Bit8u memory_mode;
+} VGA_Seq;
+
+typedef struct {
+       Bit8u palette[16];
+       Bit8u mode_control;
+       Bit8u horizontal_pel_panning;
+       Bit8u overscan_color;
+       Bit8u color_plane_enable;
+       Bit8u color_select;
+       Bit8u index;
+       Bit8u disabled; // Used for disabling the screen.
+                                       // Bit0: screen disabled by attribute controller index
+                                       // Bit1: screen disabled by sequencer index 1 bit 5
+                                       // These are put together in one variable for performance reasons:
+                                       // the line drawing function is called maybe 60*480=28800 times/s,
+                                       // and we only need to check one variable for zero this way.
+} VGA_Attr;
+
+typedef struct {
+       Bit8u horizontal_total;
+       Bit8u horizontal_display_end;
+       Bit8u start_horizontal_blanking;
+       Bit8u end_horizontal_blanking;
+       Bit8u start_horizontal_retrace;
+       Bit8u end_horizontal_retrace;
+       Bit8u vertical_total;
+       Bit8u overflow;
+       Bit8u preset_row_scan;
+       Bit8u maximum_scan_line;
+       Bit8u cursor_start;
+       Bit8u cursor_end;
+       Bit8u start_address_high;
+       Bit8u start_address_low;
+       Bit8u cursor_location_high;
+       Bit8u cursor_location_low;
+       Bit8u vertical_retrace_start;
+       Bit8u vertical_retrace_end;
+       Bit8u vertical_display_end;
+       Bit8u offset;
+       Bit8u underline_location;
+       Bit8u start_vertical_blanking;
+       Bit8u end_vertical_blanking;
+       Bit8u mode_control;
+       Bit8u line_compare;
+
+       Bit8u index;
+       bool read_only;
+} VGA_Crtc;
+
+typedef struct {
+       Bit8u index;
+       Bit8u set_reset;
+       Bit8u enable_set_reset;
+       Bit8u color_compare;
+       Bit8u data_rotate;
+       Bit8u read_map_select;
+       Bit8u mode;
+       Bit8u miscellaneous;
+       Bit8u color_dont_care;
+       Bit8u bit_mask;
+} VGA_Gfx;
+
+typedef struct  {
+       Bit8u red;
+       Bit8u green;
+       Bit8u blue;
+} RGBEntry;
+
+typedef struct {
+       Bit8u bits;                                             /* DAC bits, usually 6 or 8 */
+       Bit8u pel_mask;
+       Bit8u pel_index;        
+       Bit8u state;
+       Bit8u write_index;
+       Bit8u read_index;
+       Bitu first_changed;
+       Bit8u combine[16];
+       RGBEntry rgb[0x100];
+       Bit16u xlat16[256];
+} VGA_Dac;
+
+typedef struct {
+       Bitu    readStart, writeStart;
+       Bitu    bankMask;
+       Bitu    bank_read_full;
+       Bitu    bank_write_full;
+       Bit8u   bank_read;
+       Bit8u   bank_write;
+       Bitu    bank_size;
+} VGA_SVGA;
+
+typedef union {
+       Bit32u d;
+       Bit8u b[4];
+} VGA_Latch;
+
+typedef struct {
+       Bit8u* linear;
+       Bit8u* linear_orgptr;
+} VGA_Memory;
+
+typedef struct {
+       //Add a few more just to be safe
+       Bit8u*  map; /* allocated dynamically: [(VGA_MEMORY >> VGA_CHANGE_SHIFT) + 32] */
+       Bit8u   checkMask, frame, writeMask;
+       bool    active;
+       Bit32u  clearMask;
+       Bit32u  start, last;
+       Bit32u  lastAddress;
+} VGA_Changes;
+
+typedef struct {
+       Bit32u page;
+       Bit32u addr;
+       Bit32u mask;
+       PageHandler *handler;
+} VGA_LFB;
+
+typedef struct {
+       VGAModes mode;                                                          /* The mode the vga system is in */
+       Bit8u misc_output;
+       VGA_Draw draw;
+       VGA_Config config;
+       VGA_Internal internal;
+/* Internal module groups */
+       VGA_Seq seq;
+       VGA_Attr attr;
+       VGA_Crtc crtc;
+       VGA_Gfx gfx;
+       VGA_Dac dac;
+       VGA_Latch latch;
+       VGA_S3 s3;
+       VGA_SVGA svga;
+       VGA_HERC herc;
+       VGA_TANDY tandy;
+       VGA_OTHER other;
+       VGA_Memory mem;
+       Bit32u vmemwrap; /* this is assumed to be power of 2 */
+       Bit8u* fastmem;  /* memory for fast (usually 16-color) rendering, always twice as big as vmemsize */
+       Bit8u* fastmem_orgptr;
+       Bit32u vmemsize;
+#ifdef VGA_KEEP_CHANGES
+       VGA_Changes changes;
+#endif
+       VGA_LFB lfb;
+} VGA_Type;
+
+
+/* Hercules Palette function */
+void Herc_Palette(void);
+
+/* Functions for different resolutions */
+void VGA_SetMode(VGAModes mode);
+void VGA_DetermineMode(void);
+void VGA_SetupHandlers(void);
+void VGA_StartResize(Bitu delay=50);
+void VGA_SetupDrawing(Bitu val);
+void VGA_CheckScanLength(void);
+void VGA_ChangedBank(void);
+
+/* Some DAC/Attribute functions */
+void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal);
+void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue);
+void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
+
+typedef enum {CGA, EGA, MONO} EGAMonitorMode;
+
+void VGA_ATTR_SetEGAMonitorPalette(EGAMonitorMode m);
+
+/* The VGA Subfunction startups */
+void VGA_SetupAttr(void);
+void VGA_SetupMemory(Section* sec);
+void VGA_SetupDAC(void);
+void VGA_SetupCRTC(void);
+void VGA_SetupMisc(void);
+void VGA_SetupGFX(void);
+void VGA_SetupSEQ(void);
+void VGA_SetupOther(void);
+void VGA_SetupXGA(void);
+
+void JEGA_setupAX(void);
+
+/* Some Support Functions */
+void VGA_SetClock(Bitu which,Bitu target);
+void VGA_DACSetEntirePalette(void);
+void VGA_StartRetrace(void);
+void VGA_StartUpdateLFB(void);
+void VGA_SetBlinking(Bitu enabled);
+void VGA_SetCGA2Table(Bit8u val0,Bit8u val1);
+void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3);
+void VGA_ActivateHardwareCursor(void);
+void VGA_KillDrawing(void);
+
+void VGA_SetOverride(bool vga_override);
+
+extern VGA_Type vga;
+
+/* Support for modular SVGA implementation */
+/* Video mode extra data to be passed to FinishSetMode_SVGA().
+   This structure will be in flux until all drivers (including S3)
+   are properly separated. Right now it contains only three overflow
+   fields in S3 format and relies on drivers re-interpreting those.
+   For reference:
+   ver_overflow:X|line_comp10|X|vretrace10|X|vbstart10|vdispend10|vtotal10
+   hor_overflow:X|X|X|hretrace8|X|hblank8|hdispend8|htotal8
+   offset is not currently used by drivers (useful only for S3 itself)
+   It also contains basic int10 mode data - number, vtotal, htotal
+   */
+typedef struct {
+       Bit8u ver_overflow;
+       Bit8u hor_overflow;
+       Bitu offset;
+       Bitu modeNo;
+       Bitu htotal;
+       Bitu vtotal;
+} VGA_ModeExtraData;
+
+// Vector function prototypes
+typedef void (*tWritePort)(Bitu reg,Bitu val,Bitu iolen);
+typedef Bitu (*tReadPort)(Bitu reg,Bitu iolen);
+typedef void (*tFinishSetMode)(Bitu crtc_base, VGA_ModeExtraData* modeData);
+typedef void (*tDetermineMode)();
+typedef void (*tSetClock)(Bitu which,Bitu target);
+typedef Bitu (*tGetClock)();
+typedef bool (*tHWCursorActive)();
+typedef bool (*tAcceptsMode)(Bitu modeNo);
+
+struct SVGA_Driver {
+       tWritePort write_p3d5;
+       tReadPort read_p3d5;
+       tWritePort write_p3c5;
+       tReadPort read_p3c5;
+       tWritePort write_p3c0;
+       tReadPort read_p3c1;
+       tWritePort write_p3cf;
+       tReadPort read_p3cf;
+
+       tFinishSetMode set_video_mode;
+       tDetermineMode determine_mode;
+       tSetClock set_clock;
+       tGetClock get_clock;
+       tHWCursorActive hardware_cursor_active;
+       tAcceptsMode accepts_mode;
+};
+
+extern SVGA_Driver svga;
+
+void SVGA_Setup_S3Trio(void);
+void SVGA_Setup_TsengET4K(void);
+void SVGA_Setup_TsengET3K(void);
+void SVGA_Setup_ParadisePVGA1A(void);
+void SVGA_Setup_Driver(void);
+
+// Amount of video memory required for a mode, implemented in int10_modes.cpp
+Bitu VideoModeMemSize(Bitu mode);
+
+extern Bit32u ExpandTable[256];
+extern Bit32u FillTable[16];
+extern Bit32u CGA_2_Table[16];
+extern Bit32u CGA_4_Table[256];
+extern Bit32u CGA_4_HiRes_Table[256];
+extern Bit32u CGA_16_Table[256];
+extern Bit32u TXT_Font_Table[16];
+extern Bit32u TXT_FG_Table[16];
+extern Bit32u TXT_BG_Table[16];
+extern Bit32u Expand16Table[4][16];
+extern Bit32u Expand16BigTable[0x10000];
+
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/include/video.h b/source/src/vm/libcpu_newdev/dosbox-i386/include/video.h
new file mode 100644 (file)
index 0000000..11539ae
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef DOSBOX_VIDEO_H
+#define DOSBOX_VIDEO_H
+
+#define REDUCE_JOYSTICK_POLLING
+
+typedef enum {
+       GFX_CallBackReset,
+       GFX_CallBackStop,
+       GFX_CallBackRedraw
+} GFX_CallBackFunctions_t;
+
+typedef void (*GFX_CallBack_t)( GFX_CallBackFunctions_t function );
+
+struct GFX_PalEntry {
+       Bit8u r;
+       Bit8u g;
+       Bit8u b;
+       Bit8u unused;
+};
+
+#define GFX_CAN_8              0x0001
+#define GFX_CAN_15             0x0002
+#define GFX_CAN_16             0x0004
+#define GFX_CAN_32             0x0008
+
+#define GFX_LOVE_8             0x0010
+#define GFX_LOVE_15            0x0020
+#define GFX_LOVE_16            0x0040
+#define GFX_LOVE_32            0x0080
+
+#define GFX_RGBONLY            0x0100
+
+#define GFX_SCALING            0x1000
+#define GFX_HARDWARE   0x2000
+
+#define GFX_CAN_RANDOM 0x4000          //If the interface can also do random access surface
+
+void GFX_Events(void);
+void GFX_SetPalette(Bitu start,Bitu count,GFX_PalEntry * entries);
+Bitu GFX_GetBestMode(Bitu flags);
+Bitu GFX_GetRGB(Bit8u red,Bit8u green,Bit8u blue);
+Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,GFX_CallBack_t cb);
+
+void GFX_ResetScreen(void);
+void GFX_Start(void);
+void GFX_Stop(void);
+void GFX_SwitchFullScreen(void);
+bool GFX_StartUpdate(Bit8u * & pixels,Bitu & pitch);
+void GFX_EndUpdate( const Bit16u *changedLines );
+void GFX_GetSize(int &width, int &height, bool &fullscreen);
+void GFX_LosingFocus(void);
+
+#if defined (WIN32)
+bool GFX_SDLUsingWinDIB(void);
+#endif
+
+#if defined (REDUCE_JOYSTICK_POLLING)
+void MAPPER_UpdateJoysticks(void);
+#endif
+
+/* Mouse related */
+void GFX_CaptureMouse(void);
+extern bool mouselocked; //true if mouse is confined to window
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/instructions.h b/source/src/vm/libcpu_newdev/dosbox-i386/instructions.h
new file mode 100644 (file)
index 0000000..28af331
--- /dev/null
@@ -0,0 +1,963 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Jumps */
+
+/* All Byte general instructions */
+#define ADDB(op1,op2,load,save)                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b+lf_var2b;                                      \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_ADDb;
+
+#define ADCB(op1,op2,load,save)                                                                \
+       lflags.oldcf=get_CF()!=0;                                                               \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b+lf_var2b+lflags.oldcf;         \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_ADCb;
+
+#define SBBB(op1,op2,load,save)                                                                \
+       lflags.oldcf=get_CF()!=0;                                                                       \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b-(lf_var2b+lflags.oldcf);       \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_SBBb;
+
+#define SUBB(op1,op2,load,save)                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b-lf_var2b;                                      \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_SUBb;
+
+#define ORB(op1,op2,load,save)                                                         \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b | lf_var2b;                            \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_ORb;
+
+#define XORB(op1,op2,load,save)                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b ^ lf_var2b;                            \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_XORb;
+
+#define ANDB(op1,op2,load,save)                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b & lf_var2b;                            \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_ANDb;
+
+#define CMPB(op1,op2,load,save)                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b-lf_var2b;                                      \
+       lflags.type=t_CMPb;
+
+#define TESTB(op1,op2,load,save)                                                       \
+       lf_var1b=load(op1);lf_var2b=op2;                                        \
+       lf_resb=lf_var1b & lf_var2b;                            \
+       lflags.type=t_TESTb;
+
+/* All Word General instructions */
+
+#define ADDW(op1,op2,load,save)                                                                \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w+lf_var2w;                                      \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_ADDw;
+
+#define ADCW(op1,op2,load,save)                                                                \
+       lflags.oldcf=get_CF()!=0;                                                                       \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w+lf_var2w+lflags.oldcf;         \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_ADCw;
+
+#define SBBW(op1,op2,load,save)                                                                \
+       lflags.oldcf=get_CF()!=0;                                                                       \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w-(lf_var2w+lflags.oldcf);       \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_SBBw;
+
+#define SUBW(op1,op2,load,save)                                                                \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w-lf_var2w;                                      \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_SUBw;
+
+#define ORW(op1,op2,load,save)                                                         \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w | lf_var2w;                            \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_ORw;
+
+#define XORW(op1,op2,load,save)                                                                \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w ^ lf_var2w;                            \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_XORw;
+
+#define ANDW(op1,op2,load,save)                                                                \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w & lf_var2w;                            \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_ANDw;
+
+#define CMPW(op1,op2,load,save)                                                                \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w-lf_var2w;                                      \
+       lflags.type=t_CMPw;
+
+#define TESTW(op1,op2,load,save)                                                       \
+       lf_var1w=load(op1);lf_var2w=op2;                                        \
+       lf_resw=lf_var1w & lf_var2w;                            \
+       lflags.type=t_TESTw;
+
+/* All DWORD General Instructions */
+
+#define ADDD(op1,op2,load,save)                                                                \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d+lf_var2d;                                      \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_ADDd;
+
+#define ADCD(op1,op2,load,save)                                                                \
+       lflags.oldcf=get_CF()!=0;                                                                       \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d+lf_var2d+lflags.oldcf;         \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_ADCd;
+
+#define SBBD(op1,op2,load,save)                                                                \
+       lflags.oldcf=get_CF()!=0;                                                                       \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d-(lf_var2d+lflags.oldcf);       \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_SBBd;
+
+#define SUBD(op1,op2,load,save)                                                                \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d-lf_var2d;                                      \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_SUBd;
+
+#define ORD(op1,op2,load,save)                                                         \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d | lf_var2d;                            \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_ORd;
+
+#define XORD(op1,op2,load,save)                                                                \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d ^ lf_var2d;                            \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_XORd;
+
+#define ANDD(op1,op2,load,save)                                                                \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d & lf_var2d;                            \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_ANDd;
+
+#define CMPD(op1,op2,load,save)                                                                \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d-lf_var2d;                                      \
+       lflags.type=t_CMPd;
+
+
+#define TESTD(op1,op2,load,save)                                                       \
+       lf_var1d=load(op1);lf_var2d=op2;                                        \
+       lf_resd=lf_var1d & lf_var2d;                            \
+       lflags.type=t_TESTd;
+
+
+
+
+#define INCB(op1,load,save)                                                                    \
+       LoadCF;lf_var1b=load(op1);                                                              \
+       lf_resb=lf_var1b+1;                                                                             \
+       save(op1,lf_resb);                                                                              \
+       lflags.type=t_INCb;                                                                             \
+
+#define INCW(op1,load,save)                                                                    \
+       LoadCF;lf_var1w=load(op1);                                                              \
+       lf_resw=lf_var1w+1;                                                                             \
+       save(op1,lf_resw);                                                                              \
+       lflags.type=t_INCw;
+
+#define INCD(op1,load,save)                                                                    \
+       LoadCF;lf_var1d=load(op1);                                                              \
+       lf_resd=lf_var1d+1;                                                                             \
+       save(op1,lf_resd);                                                                              \
+       lflags.type=t_INCd;
+
+#define DECB(op1,load,save)                                                                    \
+       LoadCF;lf_var1b=load(op1);                                                              \
+       lf_resb=lf_var1b-1;                                                                             \
+       save(op1,lf_resb);                                                                              \
+       lflags.type=t_DECb;
+
+#define DECW(op1,load,save)                                                                    \
+       LoadCF;lf_var1w=load(op1);                                                              \
+       lf_resw=lf_var1w-1;                                                                             \
+       save(op1,lf_resw);                                                                              \
+       lflags.type=t_DECw;
+
+#define DECD(op1,load,save)                                                                    \
+       LoadCF;lf_var1d=load(op1);                                                              \
+       lf_resd=lf_var1d-1;                                                                             \
+       save(op1,lf_resd);                                                                              \
+       lflags.type=t_DECd;
+
+
+
+#define ROLB(op1,op2,load,save)                                                \
+       if (!(op2&0x7)) {                                                               \
+               if (op2&0x18) {                                                         \
+                       FillFlagsNoCFOF();                                              \
+                       SETFLAGBIT(CF,op1 & 1);                                 \
+                       SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7));  \
+               }                                                                                       \
+               break;                                                                          \
+       }                                                                                               \
+       FillFlagsNoCFOF();                                                              \
+       lf_var1b=load(op1);                                                             \
+       lf_var2b=op2&0x07;                                                              \
+       lf_resb=(lf_var1b << lf_var2b) |                                \
+                       (lf_var1b >> (8-lf_var2b));                             \
+       save(op1,lf_resb);                                                              \
+       SETFLAGBIT(CF,lf_resb & 1);                                             \
+       SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7));
+
+#define ROLW(op1,op2,load,save)                                                \
+       if (!(op2&0xf)) {                                                               \
+               if (op2&0x10) {                                                         \
+                       FillFlagsNoCFOF();                                              \
+                       SETFLAGBIT(CF,op1 & 1);                                 \
+                       SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); \
+               }                                                                                       \
+               break;                                                                          \
+       }                                                                                               \
+       FillFlagsNoCFOF();                                                              \
+       lf_var1w=load(op1);                                                             \
+       lf_var2b=op2&0xf;                                                               \
+       lf_resw=(lf_var1w << lf_var2b) |                                \
+                       (lf_var1w >> (16-lf_var2b));                    \
+       save(op1,lf_resw);                                                              \
+       SETFLAGBIT(CF,lf_resw & 1);                                             \
+       SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15));
+
+#define ROLD(op1,op2,load,save)                                                \
+       if (!op2) break;                                                                \
+       FillFlagsNoCFOF();                                                              \
+       lf_var1d=load(op1);                                                             \
+       lf_var2b=op2;                                                                   \
+       lf_resd=(lf_var1d << lf_var2b) |                                \
+                       (lf_var1d >> (32-lf_var2b));                    \
+       save(op1,lf_resd);                                                              \
+       SETFLAGBIT(CF,lf_resd & 1);                                             \
+       SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31));
+
+
+#define RORB(op1,op2,load,save)                                                \
+       if (!(op2&0x7)) {                                                               \
+               if (op2&0x18) {                                                         \
+                       FillFlagsNoCFOF();                                              \
+                       SETFLAGBIT(CF,op1>>7);                                  \
+                       SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1));                       \
+               }                                                                                       \
+               break;                                                                          \
+       }                                                                                               \
+       FillFlagsNoCFOF();                                                              \
+       lf_var1b=load(op1);                                                             \
+       lf_var2b=op2&0x07;                                                              \
+       lf_resb=(lf_var1b >> lf_var2b) |                                \
+                       (lf_var1b << (8-lf_var2b));                             \
+       save(op1,lf_resb);                                                              \
+       SETFLAGBIT(CF,lf_resb & 0x80);                                  \
+       SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80);
+
+#define RORW(op1,op2,load,save)                                        \
+       if (!(op2&0xf)) {                                                       \
+               if (op2&0x10) {                                                 \
+                       FillFlagsNoCFOF();                                      \
+                       SETFLAGBIT(CF,op1>>15);                         \
+                       SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1));                     \
+               }                                                                               \
+               break;                                                                  \
+       }                                                                                       \
+       FillFlagsNoCFOF();                                                      \
+       lf_var1w=load(op1);                                                     \
+       lf_var2b=op2&0xf;                                                       \
+       lf_resw=(lf_var1w >> lf_var2b) |                        \
+                       (lf_var1w << (16-lf_var2b));            \
+       save(op1,lf_resw);                                                      \
+       SETFLAGBIT(CF,lf_resw & 0x8000);                        \
+       SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000);
+
+#define RORD(op1,op2,load,save)                                        \
+       if (!op2) break;                                                        \
+       FillFlagsNoCFOF();                                                      \
+       lf_var1d=load(op1);                                                     \
+       lf_var2b=op2;                                                           \
+       lf_resd=(lf_var1d >> lf_var2b) |                        \
+                       (lf_var1d << (32-lf_var2b));            \
+       save(op1,lf_resd);                                                      \
+       SETFLAGBIT(CF,lf_resd & 0x80000000);            \
+       SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000);
+
+
+#define RCLB(op1,op2,load,save)                                                        \
+       if (!(op2%9)) break;                                                            \
+{      Bit8u cf=(Bit8u)FillFlags()&0x1;                                        \
+       lf_var1b=load(op1);                                                                     \
+       lf_var2b=op2%9;                                                                         \
+       lf_resb=(lf_var1b << lf_var2b) |                                        \
+                       (cf << (lf_var2b-1)) |                                          \
+                       (lf_var1b >> (9-lf_var2b));                                     \
+       save(op1,lf_resb);                                                                      \
+       SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1));        \
+       SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7));        \
+}
+
+#define RCLW(op1,op2,load,save)                                                        \
+       if (!(op2%17)) break;                                                           \
+{      Bit16u cf=(Bit16u)FillFlags()&0x1;                                      \
+       lf_var1w=load(op1);                                                                     \
+       lf_var2b=op2%17;                                                                        \
+       lf_resw=(lf_var1w << lf_var2b) |                                        \
+                       (cf << (lf_var2b-1)) |                                          \
+                       (lf_var1w >> (17-lf_var2b));                            \
+       save(op1,lf_resw);                                                                      \
+       SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1));       \
+       SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15));       \
+}
+
+#define RCLD(op1,op2,load,save)                                                        \
+       if (!op2) break;                                                                        \
+{      Bit32u cf=(Bit32u)FillFlags()&0x1;                                      \
+       lf_var1d=load(op1);                                                                     \
+       lf_var2b=op2;                                                                           \
+       if (lf_var2b==1)        {                                                               \
+               lf_resd=(lf_var1d << 1) | cf;                                   \
+       } else  {                                                                                       \
+               lf_resd=(lf_var1d << lf_var2b) |                                \
+               (cf << (lf_var2b-1)) |                                                  \
+               (lf_var1d >> (33-lf_var2b));                                    \
+       }                                                                                                       \
+       save(op1,lf_resd);                                                                      \
+       SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1));       \
+       SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resd >> 31));       \
+}
+
+
+
+#define RCRB(op1,op2,load,save)                                                                \
+       if (op2%9) {                                                                                    \
+               Bit8u cf=(Bit8u)FillFlags()&0x1;                                        \
+               lf_var1b=load(op1);                                                                     \
+               lf_var2b=op2%9;                                                                         \
+               lf_resb=(lf_var1b >> lf_var2b) |                                        \
+                               (cf << (8-lf_var2b)) |                                          \
+                               (lf_var1b << (9-lf_var2b));                                     \
+               save(op1,lf_resb);                                                                      \
+               SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1);        \
+               SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80);         \
+       }
+
+#define RCRW(op1,op2,load,save)                                                                \
+       if (op2%17) {                                                                                   \
+               Bit16u cf=(Bit16u)FillFlags()&0x1;                                      \
+               lf_var1w=load(op1);                                                                     \
+               lf_var2b=op2%17;                                                                        \
+               lf_resw=(lf_var1w >> lf_var2b) |                                        \
+                               (cf << (16-lf_var2b)) |                                         \
+                               (lf_var1w << (17-lf_var2b));                            \
+               save(op1,lf_resw);                                                                      \
+               SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1);        \
+               SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000);       \
+       }
+
+#define RCRD(op1,op2,load,save)                                                                \
+       if (op2) {                                                                                              \
+               Bit32u cf=(Bit32u)FillFlags()&0x1;                                      \
+               lf_var1d=load(op1);                                                                     \
+               lf_var2b=op2;                                                                           \
+               if (lf_var2b==1) {                                                                      \
+                       lf_resd=lf_var1d >> 1 | cf << 31;                               \
+               } else {                                                                                        \
+                       lf_resd=(lf_var1d >> lf_var2b) |                                \
+                               (cf << (32-lf_var2b)) |                                         \
+                               (lf_var1d << (33-lf_var2b));                            \
+               }                                                                                                       \
+               save(op1,lf_resd);                                                                      \
+               SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1);        \
+               SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000);   \
+       }
+
+
+#define SHLB(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                \
+       lf_resb=lf_var1b << lf_var2b;                   \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_SHLb;
+
+#define SHLW(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                                \
+       lf_var1w=load(op1);lf_var2b=op2 ;                               \
+       lf_resw=lf_var1w << lf_var2b;                   \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_SHLw;
+
+#define SHLD(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                                \
+       lf_var1d=load(op1);lf_var2b=op2;                                \
+       lf_resd=lf_var1d << lf_var2b;                   \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_SHLd;
+
+
+#define SHRB(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                \
+       lf_resb=lf_var1b >> lf_var2b;                   \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_SHRb;
+
+#define SHRW(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                                \
+       lf_var1w=load(op1);lf_var2b=op2;                                \
+       lf_resw=lf_var1w >> lf_var2b;                   \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_SHRw;
+
+#define SHRD(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                                \
+       lf_var1d=load(op1);lf_var2b=op2;                                \
+       lf_resd=lf_var1d >> lf_var2b;                   \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_SHRd;
+
+
+#define SARB(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                                \
+       lf_var1b=load(op1);lf_var2b=op2;                                \
+       if (lf_var2b>8) lf_var2b=8;                                             \
+    if (lf_var1b & 0x80) {                                                             \
+               lf_resb=(lf_var1b >> lf_var2b)|         \
+               (0xff << (8 - lf_var2b));                                               \
+       } else {                                                                                                \
+               lf_resb=lf_var1b >> lf_var2b;           \
+    }                                                                                                          \
+       save(op1,lf_resb);                                                              \
+       lflags.type=t_SARb;
+
+#define SARW(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                \
+       lf_var1w=load(op1);lf_var2b=op2;                        \
+       if (lf_var2b>16) lf_var2b=16;                                   \
+       if (lf_var1w & 0x8000) {                                                        \
+               lf_resw=(lf_var1w >> lf_var2b)|         \
+               (0xffff << (16 - lf_var2b));                                    \
+       } else {                                                                                                \
+               lf_resw=lf_var1w >> lf_var2b;           \
+    }                                                                                                          \
+       save(op1,lf_resw);                                                              \
+       lflags.type=t_SARw;
+
+#define SARD(op1,op2,load,save)                                                                \
+       if (!op2) break;                                                                \
+       lf_var2b=op2;lf_var1d=load(op1);                        \
+       if (lf_var1d & 0x80000000) {                                            \
+               lf_resd=(lf_var1d >> lf_var2b)|         \
+               (0xffffffff << (32 - lf_var2b));                                \
+       } else {                                                                                                \
+               lf_resd=lf_var1d >> lf_var2b;           \
+    }                                                                                                          \
+       save(op1,lf_resd);                                                              \
+       lflags.type=t_SARd;
+
+
+
+#define DAA()                                                                                          \
+       if (((reg_al & 0x0F)>0x09) || get_AF()) {                               \
+               if ((reg_al > 0x99) || get_CF()) {                                      \
+                       reg_al+=0x60;                                                                   \
+                       SETFLAGBIT(CF,true);                                                    \
+               } else {                                                                                        \
+                       SETFLAGBIT(CF,false);                                                   \
+               }                                                                                                       \
+               reg_al+=0x06;                                                                           \
+               SETFLAGBIT(AF,true);                                                            \
+       } else {                                                                                                \
+               if ((reg_al > 0x99) || get_CF()) {                                      \
+                       reg_al+=0x60;                                                                   \
+                       SETFLAGBIT(CF,true);                                                    \
+               } else {                                                                                        \
+                       SETFLAGBIT(CF,false);                                                   \
+               }                                                                                                       \
+               SETFLAGBIT(AF,false);                                                           \
+       }                                                                                                               \
+       SETFLAGBIT(SF,(reg_al&0x80));                                                   \
+       SETFLAGBIT(ZF,(reg_al==0));                                                             \
+       SETFLAGBIT(PF,parity_lookup[reg_al]);                                   \
+       lflags.type=t_UNKNOWN;
+
+
+#define DAS()                                                                                          \
+{                                                                                                                      \
+       Bit8u osigned=reg_al & 0x80;                                                    \
+       if (((reg_al & 0x0f) > 9) || get_AF()) {                                \
+               if ((reg_al>0x99) || get_CF()) {                                        \
+                       reg_al-=0x60;                                                                   \
+                       SETFLAGBIT(CF,true);                                                    \
+               } else {                                                                                        \
+                       SETFLAGBIT(CF,(reg_al<=0x05));                                  \
+               }                                                                                                       \
+               reg_al-=6;                                                                                      \
+               SETFLAGBIT(AF,true);                                                            \
+       } else {                                                                                                \
+               if ((reg_al>0x99) || get_CF()) {                                        \
+                       reg_al-=0x60;                                                                   \
+                       SETFLAGBIT(CF,true);                                                    \
+               } else {                                                                                        \
+                       SETFLAGBIT(CF,false);                                                   \
+               }                                                                                                       \
+               SETFLAGBIT(AF,false);                                                           \
+       }                                                                                                               \
+       SETFLAGBIT(OF,osigned && ((reg_al&0x80)==0));                   \
+       SETFLAGBIT(SF,(reg_al&0x80));                                                   \
+       SETFLAGBIT(ZF,(reg_al==0));                                                             \
+       SETFLAGBIT(PF,parity_lookup[reg_al]);                                   \
+       lflags.type=t_UNKNOWN;                                                                  \
+}
+
+
+#define AAA()                                                                                          \
+       SETFLAGBIT(SF,((reg_al>=0x7a) && (reg_al<=0xf9)));              \
+       if ((reg_al & 0xf) > 9) {                                                               \
+               SETFLAGBIT(OF,(reg_al&0xf0)==0x70);                                     \
+               reg_ax += 0x106;                                                                        \
+               SETFLAGBIT(CF,true);                                                            \
+               SETFLAGBIT(ZF,(reg_al == 0));                                           \
+               SETFLAGBIT(AF,true);                                                            \
+       } else if (get_AF()) {                                                                  \
+               reg_ax += 0x106;                                                                        \
+               SETFLAGBIT(OF,false);                                                           \
+               SETFLAGBIT(CF,true);                                                            \
+               SETFLAGBIT(ZF,false);                                                           \
+               SETFLAGBIT(AF,true);                                                            \
+       } else {                                                                                                \
+               SETFLAGBIT(OF,false);                                                           \
+               SETFLAGBIT(CF,false);                                                           \
+               SETFLAGBIT(ZF,(reg_al == 0));                                           \
+               SETFLAGBIT(AF,false);                                                           \
+       }                                                                                                               \
+       SETFLAGBIT(PF,parity_lookup[reg_al]);                                   \
+       reg_al &= 0x0F;                                                                                 \
+       lflags.type=t_UNKNOWN;
+
+#define AAS()                                                                                          \
+       if ((reg_al & 0x0f)>9) {                                                                \
+               SETFLAGBIT(SF,(reg_al>0x85));                                           \
+               reg_ax -= 0x106;                                                                        \
+               SETFLAGBIT(OF,false);                                                           \
+               SETFLAGBIT(CF,true);                                                            \
+               SETFLAGBIT(AF,true);                                                            \
+       } else if (get_AF()) {                                                                  \
+               SETFLAGBIT(OF,((reg_al>=0x80) && (reg_al<=0x85)));      \
+               SETFLAGBIT(SF,(reg_al<0x06) || (reg_al>0x85));          \
+               reg_ax -= 0x106;                                                                        \
+               SETFLAGBIT(CF,true);                                                            \
+               SETFLAGBIT(AF,true);                                                            \
+       } else {                                                                                                \
+               SETFLAGBIT(SF,(reg_al>=0x80));                                          \
+               SETFLAGBIT(OF,false);                                                           \
+               SETFLAGBIT(CF,false);                                                           \
+               SETFLAGBIT(AF,false);                                                           \
+       }                                                                                                               \
+       SETFLAGBIT(ZF,(reg_al == 0));                                                   \
+       SETFLAGBIT(PF,parity_lookup[reg_al]);                                   \
+       reg_al &= 0x0F;                                                                                 \
+       lflags.type=t_UNKNOWN;
+
+#define AAM(op1)                                                                                       \
+{                                                                                                                      \
+       Bit8u dv=op1;                                                                                   \
+       if (dv!=0) {                                                                                    \
+               reg_ah=reg_al / dv;                                                                     \
+               reg_al=reg_al % dv;                                                                     \
+               SETFLAGBIT(SF,(reg_al & 0x80));                                         \
+               SETFLAGBIT(ZF,(reg_al == 0));                                           \
+               SETFLAGBIT(PF,parity_lookup[reg_al]);                           \
+               SETFLAGBIT(CF,false);                                                           \
+               SETFLAGBIT(OF,false);                                                           \
+               SETFLAGBIT(AF,false);                                                           \
+               lflags.type=t_UNKNOWN;                                                          \
+       } else EXCEPTION(0);                                                                    \
+}
+
+
+//Took this from bochs, i seriously hate these weird bcd opcodes
+#define AAD(op1)                                                                                       \
+       {                                                                                                               \
+               Bit16u ax1 = reg_ah * op1;                                                      \
+               Bit16u ax2 = ax1 + reg_al;                                                      \
+               reg_al = (Bit8u) ax2;                                                           \
+               reg_ah = 0;                                                                                     \
+               SETFLAGBIT(CF,false);                                                           \
+               SETFLAGBIT(OF,false);                                                           \
+               SETFLAGBIT(AF,false);                                                           \
+               SETFLAGBIT(SF,reg_al >= 0x80);                                          \
+               SETFLAGBIT(ZF,reg_al == 0);                                                     \
+               SETFLAGBIT(PF,parity_lookup[reg_al]);                           \
+               lflags.type=t_UNKNOWN;                                                          \
+       }
+
+#define MULB(op1,load,save)                                                                    \
+       reg_ax=reg_al*load(op1);                                                                \
+       FillFlagsNoCFOF();                                                                              \
+       SETFLAGBIT(ZF,reg_al == 0);                                                             \
+       if (reg_ax & 0xff00) {                                                                  \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       }
+
+#define MULW(op1,load,save)                                                                    \
+{                                                                                                                      \
+       Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1));                              \
+       reg_ax=(Bit16u)(tempu);                                                                 \
+       reg_dx=(Bit16u)(tempu >> 16);                                                   \
+       FillFlagsNoCFOF();                                                                              \
+       SETFLAGBIT(ZF,reg_ax == 0);                                                             \
+       if (reg_dx) {                                                                                   \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       }                                                                                                               \
+}
+
+#define MULD(op1,load,save)                                                                    \
+{                                                                                                                      \
+       Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1));               \
+       reg_eax=(Bit32u)(tempu);                                                                \
+       reg_edx=(Bit32u)(tempu >> 32);                                                  \
+       FillFlagsNoCFOF();                                                                              \
+       SETFLAGBIT(ZF,reg_eax == 0);                                                    \
+       if (reg_edx) {                                                                                  \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       }                                                                                                               \
+}
+
+#define DIVB(op1,load,save)                                                                    \
+{                                                                                                                      \
+       Bitu val=load(op1);                                                                             \
+       if (val==0)     EXCEPTION(0);                                                           \
+       Bitu quo=reg_ax / val;                                                                  \
+       Bit8u rem=(Bit8u)(reg_ax % val);                                                \
+       Bit8u quo8=(Bit8u)(quo&0xff);                                                   \
+       if (quo>0xff) EXCEPTION(0);                                                             \
+       reg_ah=rem;                                                                                             \
+       reg_al=quo8;                                                                                    \
+}
+
+
+#define DIVW(op1,load,save)                                                                    \
+{                                                                                                                      \
+       Bitu val=load(op1);                                                                             \
+       if (val==0)     EXCEPTION(0);                                                           \
+       Bitu num=((Bit32u)reg_dx<<16)|reg_ax;                                                   \
+       Bitu quo=num/val;                                                                               \
+       Bit16u rem=(Bit16u)(num % val);                                                 \
+       Bit16u quo16=(Bit16u)(quo&0xffff);                                              \
+       if (quo!=(Bit32u)quo16) EXCEPTION(0);                                   \
+       reg_dx=rem;                                                                                             \
+       reg_ax=quo16;                                                                                   \
+}
+
+#define DIVD(op1,load,save)                                                                    \
+{                                                                                                                      \
+       Bitu val=load(op1);                                                                             \
+       if (val==0) EXCEPTION(0);                                                                       \
+       Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax;                             \
+       Bit64u quo=num/val;                                                                             \
+       Bit32u rem=(Bit32u)(num % val);                                                 \
+       Bit32u quo32=(Bit32u)(quo&0xffffffff);                                  \
+       if (quo!=(Bit64u)quo32) EXCEPTION(0);                                   \
+       reg_edx=rem;                                                                                    \
+       reg_eax=quo32;                                                                                  \
+}
+
+
+#define IDIVB(op1,load,save)                                                           \
+{                                                                                                                      \
+       Bits val=(Bit8s)(load(op1));                                                    \
+       if (val==0)     EXCEPTION(0);                                                           \
+       Bits quo=((Bit16s)reg_ax) / val;                                                \
+       Bit8s rem=(Bit8s)((Bit16s)reg_ax % val);                                \
+       Bit8s quo8s=(Bit8s)(quo&0xff);                                                  \
+       if (quo!=(Bit16s)quo8s) EXCEPTION(0);                                   \
+       reg_ah=rem;                                                                                             \
+       reg_al=quo8s;                                                                                   \
+}
+
+
+#define IDIVW(op1,load,save)                                                           \
+{                                                                                                                      \
+       Bits val=(Bit16s)(load(op1));                                                   \
+       if (val==0) EXCEPTION(0);                                                                       \
+       Bits num=(Bit32s)((reg_dx<<16)|reg_ax);                                 \
+       Bits quo=num/val;                                                                               \
+       Bit16s rem=(Bit16s)(num % val);                                                 \
+       Bit16s quo16s=(Bit16s)quo;                                                              \
+       if (quo!=(Bit32s)quo16s) EXCEPTION(0);                                  \
+       reg_dx=rem;                                                                                             \
+       reg_ax=quo16s;                                                                                  \
+}
+
+#define IDIVD(op1,load,save)                                                           \
+{                                                                                                                      \
+       Bits val=(Bit32s)(load(op1));                                                   \
+       if (val==0) EXCEPTION(0);                                                                       \
+       Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax;                             \
+       Bit64s quo=num/val;                                                                             \
+       Bit32s rem=(Bit32s)(num % val);                                                 \
+       Bit32s quo32s=(Bit32s)(quo&0xffffffff);                                 \
+       if (quo!=(Bit64s)quo32s) EXCEPTION(0);                                  \
+       reg_edx=rem;                                                                                    \
+       reg_eax=quo32s;                                                                                 \
+}
+
+#define IMULB(op1,load,save)                                                           \
+{                                                                                                                      \
+       reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1)));                  \
+       FillFlagsNoCFOF();                                                                              \
+       if ((reg_ax & 0xff80)==0xff80 ||                                                \
+               (reg_ax & 0xff80)==0x0000) {                                            \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       }                                                                                                               \
+}
+       
+
+#define IMULW(op1,load,save)                                                           \
+{                                                                                                                      \
+       Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1)));              \
+       reg_ax=(Bit16s)(temps);                                                                 \
+       reg_dx=(Bit16s)(temps >> 16);                                                   \
+       FillFlagsNoCFOF();                                                                              \
+       if (((temps & 0xffff8000)==0xffff8000 ||                                \
+               (temps & 0xffff8000)==0x0000)) {                                        \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       }                                                                                                               \
+}
+
+#define IMULD(op1,load,save)                                                           \
+{                                                                                                                      \
+       Bit64s temps=((Bit64s)((Bit32s)reg_eax))*                               \
+                                ((Bit64s)((Bit32s)(load(op1))));                       \
+       reg_eax=(Bit32u)(temps);                                                                \
+       reg_edx=(Bit32u)(temps >> 32);                                                  \
+       FillFlagsNoCFOF();                                                                              \
+       if ((reg_edx==0xffffffff) &&                                                    \
+               (reg_eax & 0x80000000) ) {                                                      \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       } else if ( (reg_edx==0x00000000) &&                                    \
+                               (reg_eax< 0x80000000) ) {                                       \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       }                                                                                                               \
+}
+
+#define DIMULW(op1,op2,op3,load,save)                                          \
+{                                                                                                                      \
+       Bits res=((Bit16s)op2) * ((Bit16s)op3);                                 \
+       save(op1,res & 0xffff);                                                                 \
+       FillFlagsNoCFOF();                                                                              \
+       if ((res>= -32768)  && (res<=32767)) {                                  \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       }                                                                                                               \
+}
+
+#define DIMULD(op1,op2,op3,load,save)                                          \
+{                                                                                                                      \
+       Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3));     \
+       save(op1,(Bit32s)res);                                                                  \
+       FillFlagsNoCFOF();                                                                              \
+       if ((res>=-((Bit64s)(2147483647)+1)) &&                                 \
+               (res<=(Bit64s)2147483647)) {                                            \
+               SETFLAGBIT(CF,false);SETFLAGBIT(OF,false);                      \
+       } else {                                                                                                \
+               SETFLAGBIT(CF,true);SETFLAGBIT(OF,true);                        \
+       }                                                                                                               \
+}
+
+#define GRP2B(blah)                                                                                    \
+{                                                                                                                      \
+       GetRM;Bitu which=(rm>>3)&7;                                                             \
+       if (rm >= 0xc0) {                                                                               \
+               GetEArb;                                                                                        \
+               Bit8u val=blah & 0x1f;                                                          \
+               switch (which)  {                                                                       \
+               case 0x00:ROLB(*earb,val,LoadRb,SaveRb);break;          \
+               case 0x01:RORB(*earb,val,LoadRb,SaveRb);break;          \
+               case 0x02:RCLB(*earb,val,LoadRb,SaveRb);break;          \
+               case 0x03:RCRB(*earb,val,LoadRb,SaveRb);break;          \
+               case 0x04:/* SHL and SAL are the same */                        \
+               case 0x06:SHLB(*earb,val,LoadRb,SaveRb);break;          \
+               case 0x05:SHRB(*earb,val,LoadRb,SaveRb);break;          \
+               case 0x07:SARB(*earb,val,LoadRb,SaveRb);break;          \
+               }                                                                                                       \
+       } else {                                                                                                \
+               GetEAa;                                                                                         \
+               Bit8u val=blah & 0x1f;                                                          \
+               switch (which) {                                                                        \
+               case 0x00:ROLB(eaa,val,LoadMb,SaveMb);break;            \
+               case 0x01:RORB(eaa,val,LoadMb,SaveMb);break;            \
+               case 0x02:RCLB(eaa,val,LoadMb,SaveMb);break;            \
+               case 0x03:RCRB(eaa,val,LoadMb,SaveMb);break;            \
+               case 0x04:/* SHL and SAL are the same */                        \
+               case 0x06:SHLB(eaa,val,LoadMb,SaveMb);break;            \
+               case 0x05:SHRB(eaa,val,LoadMb,SaveMb);break;            \
+               case 0x07:SARB(eaa,val,LoadMb,SaveMb);break;            \
+               }                                                                                                       \
+       }                                                                                                               \
+}
+
+
+
+#define GRP2W(blah)                                                                                    \
+{                                                                                                                      \
+       GetRM;Bitu which=(rm>>3)&7;                                                             \
+       if (rm >= 0xc0) {                                                                               \
+               GetEArw;                                                                                        \
+               Bit8u val=blah & 0x1f;                                                          \
+               switch (which)  {                                                                       \
+               case 0x00:ROLW(*earw,val,LoadRw,SaveRw);break;          \
+               case 0x01:RORW(*earw,val,LoadRw,SaveRw);break;          \
+               case 0x02:RCLW(*earw,val,LoadRw,SaveRw);break;          \
+               case 0x03:RCRW(*earw,val,LoadRw,SaveRw);break;          \
+               case 0x04:/* SHL and SAL are the same */                        \
+               case 0x06:SHLW(*earw,val,LoadRw,SaveRw);break;          \
+               case 0x05:SHRW(*earw,val,LoadRw,SaveRw);break;          \
+               case 0x07:SARW(*earw,val,LoadRw,SaveRw);break;          \
+               }                                                                                                       \
+       } else {                                                                                                \
+               GetEAa;                                                                                         \
+               Bit8u val=blah & 0x1f;                                                          \
+               switch (which) {                                                                        \
+               case 0x00:ROLW(eaa,val,LoadMw,SaveMw);break;            \
+               case 0x01:RORW(eaa,val,LoadMw,SaveMw);break;            \
+               case 0x02:RCLW(eaa,val,LoadMw,SaveMw);break;            \
+               case 0x03:RCRW(eaa,val,LoadMw,SaveMw);break;            \
+               case 0x04:/* SHL and SAL are the same */                        \
+               case 0x06:SHLW(eaa,val,LoadMw,SaveMw);break;            \
+               case 0x05:SHRW(eaa,val,LoadMw,SaveMw);break;            \
+               case 0x07:SARW(eaa,val,LoadMw,SaveMw);break;            \
+               }                                                                                                       \
+       }                                                                                                               \
+}
+
+
+#define GRP2D(blah)                                                                                    \
+{                                                                                                                      \
+       GetRM;Bitu which=(rm>>3)&7;                                                             \
+       if (rm >= 0xc0) {                                                                               \
+               GetEArd;                                                                                        \
+               Bit8u val=blah & 0x1f;                                                          \
+               switch (which)  {                                                                       \
+               case 0x00:ROLD(*eard,val,LoadRd,SaveRd);break;          \
+               case 0x01:RORD(*eard,val,LoadRd,SaveRd);break;          \
+               case 0x02:RCLD(*eard,val,LoadRd,SaveRd);break;          \
+               case 0x03:RCRD(*eard,val,LoadRd,SaveRd);break;          \
+               case 0x04:/* SHL and SAL are the same */                        \
+               case 0x06:SHLD(*eard,val,LoadRd,SaveRd);break;          \
+               case 0x05:SHRD(*eard,val,LoadRd,SaveRd);break;          \
+               case 0x07:SARD(*eard,val,LoadRd,SaveRd);break;          \
+               }                                                                                                       \
+       } else {                                                                                                \
+               GetEAa;                                                                                         \
+               Bit8u val=blah & 0x1f;                                                          \
+               switch (which) {                                                                        \
+               case 0x00:ROLD(eaa,val,LoadMd,SaveMd);break;            \
+               case 0x01:RORD(eaa,val,LoadMd,SaveMd);break;            \
+               case 0x02:RCLD(eaa,val,LoadMd,SaveMd);break;            \
+               case 0x03:RCRD(eaa,val,LoadMd,SaveMd);break;            \
+               case 0x04:/* SHL and SAL are the same */                        \
+               case 0x06:SHLD(eaa,val,LoadMd,SaveMd);break;            \
+               case 0x05:SHRD(eaa,val,LoadMd,SaveMd);break;            \
+               case 0x07:SARD(eaa,val,LoadMd,SaveMd);break;            \
+               }                                                                                                       \
+       }                                                                                                               \
+}
+
+/* let's hope bochs has it correct with the higher than 16 shifts */
+/* double-precision shift left has low bits in second argument */
+#define DSHLW(op1,op2,op3,load,save)                                                                   \
+       Bit8u val=op3 & 0x1F;                                                                                           \
+       if (!val) break;                                                                                                        \
+       lf_var2b=val;lf_var1d=(load(op1)<<16)|op2;                                      \
+       Bit32u tempd=lf_var1d << lf_var2b;                                                      \
+       if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16));                     \
+       lf_resw=(Bit16u)(tempd >> 16);                                                          \
+       save(op1,lf_resw);                                                                                      \
+       lflags.type=t_DSHLw;
+
+#define DSHLD(op1,op2,op3,load,save)                                                                   \
+       Bit8u val=op3 & 0x1F;                                                                                           \
+       if (!val) break;                                                                                                        \
+       lf_var2b=val;lf_var1d=load(op1);                                                        \
+       lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b));        \
+       save(op1,lf_resd);                                                                                      \
+       lflags.type=t_DSHLd;
+
+/* double-precision shift right has high bits in second argument */
+#define DSHRW(op1,op2,op3,load,save)                                                                   \
+       Bit8u val=op3 & 0x1F;                                                                                           \
+       if (!val) break;                                                                                                        \
+       lf_var2b=val;lf_var1d=(op2<<16)|load(op1);                                      \
+       Bit32u tempd=lf_var1d >> lf_var2b;                                                      \
+       if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b ));                      \
+       lf_resw=(Bit16u)(tempd);                                                                                \
+       save(op1,lf_resw);                                                                                      \
+       lflags.type=t_DSHRw;
+
+#define DSHRD(op1,op2,op3,load,save)                                                                   \
+       Bit8u val=op3 & 0x1F;                                                                                           \
+       if (!val) break;                                                                                                        \
+       lf_var2b=val;lf_var1d=load(op1);                                                        \
+       lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b));        \
+       save(op1,lf_resd);                                                                                      \
+       lflags.type=t_DSHRd;
+
+#define BSWAPW(op1)                                                                                                            \
+       op1 = 0;
+
+#define BSWAPD(op1)                                                                                                            \
+       op1 = (op1>>24)|((op1>>8)&0xFF00)|((op1<<8)&0xFF0000)|((op1<<24)&0xFF000000);
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/lazyflags.h b/source/src/vm/libcpu_newdev/dosbox-i386/lazyflags.h
new file mode 100644 (file)
index 0000000..c5e599f
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DOSBOX_LAZYFLAGS_H
+#define DOSBOX_LAZYFLAGS_H
+
+//Flag Handling
+Bit32u get_CF(void);
+Bit32u get_AF(void);
+Bit32u get_ZF(void);
+Bit32u get_SF(void);
+Bit32u get_OF(void);
+Bit32u get_PF(void);
+
+Bitu FillFlags(void);
+void FillFlagsNoCFOF(void);
+void DestroyConditionFlags(void);
+
+#ifndef DOSBOX_REGS_H
+#include "regs.h"
+#endif
+
+struct LazyFlags {
+    GenReg32 var1,var2,res;
+       Bitu type;
+       Bitu prev_type;
+       Bitu oldcf;
+};
+
+extern LazyFlags lfags;
+
+#define lf_var1b lflags.var1.byte[BL_INDEX]
+#define lf_var2b lflags.var2.byte[BL_INDEX]
+#define lf_resb lflags.res.byte[BL_INDEX]
+
+#define lf_var1w lflags.var1.word[W_INDEX]
+#define lf_var2w lflags.var2.word[W_INDEX]
+#define lf_resw lflags.res.word[W_INDEX]
+
+#define lf_var1d lflags.var1.dword[DW_INDEX]
+#define lf_var2d lflags.var2.dword[DW_INDEX]
+#define lf_resd lflags.res.dword[DW_INDEX]
+
+
+extern LazyFlags lflags;
+
+#define SETFLAGSb(FLAGB)                                                                                                       \
+{                                                                                                                                                      \
+       SETFLAGBIT(OF,get_OF());                                                                                                \
+       lflags.type=t_UNKNOWN;                                                                                                  \
+       CPU_SetFlags(FLAGB,FMASK_NORMAL & 0xff);                                                                \
+}
+
+#define SETFLAGSw(FLAGW)                                                                                                       \
+{                                                                                                                                                      \
+       lflags.type=t_UNKNOWN;                                                                                                  \
+       CPU_SetFlagsw(FLAGW);                                                                                                   \
+}
+
+#define SETFLAGSd(FLAGD)                                                                                                       \
+{                                                                                                                                                      \
+       lflags.type=t_UNKNOWN;                                                                                                  \
+       CPU_SetFlagsd(FLAGD);                                                                                                   \
+}
+
+#define LoadCF SETFLAGBIT(CF,get_CF());
+#define LoadZF SETFLAGBIT(ZF,get_ZF());
+#define LoadSF SETFLAGBIT(SF,get_SF());
+#define LoadOF SETFLAGBIT(OF,get_OF());
+#define LoadAF SETFLAGBIT(AF,get_AF());
+
+#define TFLG_O         (get_OF())
+#define TFLG_NO                (!get_OF())
+#define TFLG_B         (get_CF())
+#define TFLG_NB                (!get_CF())
+#define TFLG_Z         (get_ZF())
+#define TFLG_NZ                (!get_ZF())
+#define TFLG_BE                (get_CF() || get_ZF())
+#define TFLG_NBE       (!get_CF() && !get_ZF())
+#define TFLG_S         (get_SF())
+#define TFLG_NS                (!get_SF())
+#define TFLG_P         (get_PF())
+#define TFLG_NP                (!get_PF())
+#define TFLG_L         ((get_SF()!=0) != (get_OF()!=0))
+#define TFLG_NL                ((get_SF()!=0) == (get_OF()!=0))
+#define TFLG_LE                (get_ZF()  || ((get_SF()!=0) != (get_OF()!=0)))
+#define TFLG_NLE       (!get_ZF() && ((get_SF()!=0) == (get_OF()!=0)))
+
+//Types of Flag changing instructions
+enum {
+       t_UNKNOWN=0,
+       t_ADDb,t_ADDw,t_ADDd, 
+       t_ORb,t_ORw,t_ORd, 
+       t_ADCb,t_ADCw,t_ADCd,
+       t_SBBb,t_SBBw,t_SBBd,
+       t_ANDb,t_ANDw,t_ANDd,
+       t_SUBb,t_SUBw,t_SUBd,
+       t_XORb,t_XORw,t_XORd,
+       t_CMPb,t_CMPw,t_CMPd,
+       t_INCb,t_INCw,t_INCd,
+       t_DECb,t_DECw,t_DECd,
+       t_TESTb,t_TESTw,t_TESTd,
+       t_SHLb,t_SHLw,t_SHLd,
+       t_SHRb,t_SHRw,t_SHRd,
+       t_SARb,t_SARw,t_SARd,
+       t_ROLb,t_ROLw,t_ROLd,
+       t_RORb,t_RORw,t_RORd,
+       t_RCLb,t_RCLw,t_RCLd,
+       t_RCRb,t_RCRw,t_RCRd,
+       t_NEGb,t_NEGw,t_NEGd,
+       
+       t_DSHLw,t_DSHLd,
+       t_DSHRw,t_DSHRd,
+       t_MUL,t_DIV,
+       t_NOTDONE,
+       t_LASTFLAG
+};
+
+#endif
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/modrm.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/modrm.cpp
new file mode 100644 (file)
index 0000000..028e4d7
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "cpu.h"
+
+
+Bit8u * lookupRMregb[]=
+{
+       &reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
+       &reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
+       &reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
+       &reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
+       &reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
+       &reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
+       &reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
+       &reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,
+
+       &reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
+       &reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
+       &reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
+       &reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
+       &reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
+       &reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
+       &reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
+       &reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,
+
+       &reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
+       &reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
+       &reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
+       &reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
+       &reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
+       &reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
+       &reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
+       &reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,
+
+       &reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,&reg_al,
+       &reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,&reg_cl,
+       &reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,&reg_dl,
+       &reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,&reg_bl,
+       &reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,&reg_ah,
+       &reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,&reg_ch,
+       &reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,&reg_dh,
+       &reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh,&reg_bh
+};
+
+Bit16u * lookupRMregw[]={
+       &reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
+       &reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
+       &reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
+       &reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
+       &reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
+       &reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
+       &reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
+       &reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,
+
+       &reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
+       &reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
+       &reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
+       &reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
+       &reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
+       &reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
+       &reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
+       &reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,
+
+       &reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
+       &reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
+       &reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
+       &reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
+       &reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
+       &reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
+       &reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
+       &reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,
+
+       &reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,&reg_ax,
+       &reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,&reg_cx,
+       &reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,&reg_dx,
+       &reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,&reg_bx,
+       &reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,&reg_sp,
+       &reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,&reg_bp,
+       &reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,&reg_si,
+       &reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di,&reg_di
+};
+
+Bit32u * lookupRMregd[256]={
+       &reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
+       &reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
+       &reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
+       &reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
+       &reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
+       &reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
+       &reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
+       &reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,
+
+       &reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
+       &reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
+       &reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
+       &reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
+       &reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
+       &reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
+       &reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
+       &reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,
+
+       &reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
+       &reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
+       &reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
+       &reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
+       &reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
+       &reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
+       &reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
+       &reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,
+
+       &reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,&reg_eax,
+       &reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,&reg_ecx,
+       &reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,&reg_edx,
+       &reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,&reg_ebx,
+       &reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,&reg_esp,
+       &reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,&reg_ebp,
+       &reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,&reg_esi,
+       &reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi,&reg_edi
+};
+
+
+Bit8u * lookupRMEAregb[256]={
+/* 12 lines of 16*0 should give nice errors when used */
+       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,
+       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,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh,
+       &reg_al,&reg_cl,&reg_dl,&reg_bl,&reg_ah,&reg_ch,&reg_dh,&reg_bh
+};
+
+Bit16u * lookupRMEAregw[256]={
+/* 12 lines of 16*0 should give nice errors when used */
+       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,
+       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,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di,
+       &reg_ax,&reg_cx,&reg_dx,&reg_bx,&reg_sp,&reg_bp,&reg_si,&reg_di
+};
+
+Bit32u * lookupRMEAregd[256]={
+/* 12 lines of 16*0 should give nice errors when used */
+       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,
+       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,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi,
+       &reg_eax,&reg_ecx,&reg_edx,&reg_ebx,&reg_esp,&reg_ebp,&reg_esi,&reg_edi
+};
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/modrm.h b/source/src/vm/libcpu_newdev/dosbox-i386/modrm.h
new file mode 100644 (file)
index 0000000..29656bf
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+extern Bit8u  * lookupRMregb[];
+extern Bit16u * lookupRMregw[];
+extern Bit32u * lookupRMregd[];
+extern Bit8u  * lookupRMEAregb[256];
+extern Bit16u * lookupRMEAregw[256];
+extern Bit32u * lookupRMEAregd[256];
+
+#define GetRM                                                                                          \
+       Bit8u rm=Fetchb();
+
+#define Getrb                                                                                          \
+       Bit8u * rmrb;                                                                                   \
+       rmrb=lookupRMregb[rm];                  
+       
+#define Getrw                                                                                          \
+       Bit16u * rmrw;                                                                                  \
+       rmrw=lookupRMregw[rm];                  
+
+#define Getrd                                                                                          \
+       Bit32u * rmrd;                                                                                  \
+       rmrd=lookupRMregd[rm];                  
+
+
+#define GetRMrb                                                                                                \
+       GetRM;                                                                                                  \
+       Getrb;                                                                                                  
+
+#define GetRMrw                                                                                                \
+       GetRM;                                                                                                  \
+       Getrw;                                                                                                  
+
+#define GetRMrd                                                                                                \
+       GetRM;                                                                                                  \
+       Getrd;                                                                                                  
+
+
+#define GetEArb                                                                                                \
+       Bit8u * earb=lookupRMEAregb[rm];
+
+#define GetEArw                                                                                                \
+       Bit16u * earw=lookupRMEAregw[rm];
+
+#define GetEArd                                                                                                \
+       Bit32u * eard=lookupRMEAregd[rm];
+
+
diff --git a/source/src/vm/libcpu_newdev/dosbox-i386/paging.cpp b/source/src/vm/libcpu_newdev/dosbox-i386/paging.cpp
new file mode 100644 (file)
index 0000000..7be15e1
--- /dev/null
@@ -0,0 +1,890 @@
+/*
+ *  Copyright (C) 2002-2015  The DOSBox Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "dosbox.h"
+#include "mem.h"
+#include "paging.h"
+#include "regs.h"
+#include "lazyflags.h"
+#include "cpu.h"
+#include "debug.h"
+#include "setup.h"
+
+#define LINK_TOTAL             (64*1024)
+
+#define USERWRITE_PROHIBITED                   ((cpu.cpl&cpu.mpl)==3)
+
+
+PagingBlock paging;
+
+
+Bitu PageHandler::readb(PhysPt addr) {
+       E_Exit("No byte handler for read from %d",addr);        
+       return 0;
+}
+Bitu PageHandler::readw(PhysPt addr) {
+       Bitu ret = (readb(addr+0) << 0);
+       ret     |= (readb(addr+1) << 8);
+       return ret;
+}
+Bitu PageHandler::readd(PhysPt addr) {
+       Bitu ret = (readb(addr+0) << 0);
+       ret     |= (readb(addr+1) << 8);
+       ret     |= (readb(addr+2) << 16);
+       ret     |= (readb(addr+3) << 24);
+       return ret;
+}
+
+void PageHandler::writeb(PhysPt addr,Bitu /*val*/) {
+       E_Exit("No byte handler for write to %d",addr); 
+}
+
+void PageHandler::writew(PhysPt addr,Bitu val) {
+       writeb(addr+0,(Bit8u) (val >> 0));
+       writeb(addr+1,(Bit8u) (val >> 8));
+}
+void PageHandler::writed(PhysPt addr,Bitu val) {
+       writeb(addr+0,(Bit8u) (val >> 0));
+       writeb(addr+1,(Bit8u) (val >> 8));
+       writeb(addr+2,(Bit8u) (val >> 16));
+       writeb(addr+3,(Bit8u) (val >> 24));
+}
+
+HostPt PageHandler::GetHostReadPt(Bitu /*phys_page*/) {
+       return 0;
+}
+
+HostPt PageHandler::GetHostWritePt(Bitu /*phys_page*/) {
+       return 0;
+}
+
+bool PageHandler::readb_checked(PhysPt addr, Bit8u * val) {
+       *val=(Bit8u)readb(addr);        return false;
+}
+bool PageHandler::readw_checked(PhysPt addr, Bit16u * val) {
+       *val=(Bit16u)readw(addr);       return false;
+}
+bool PageHandler::readd_checked(PhysPt addr, Bit32u * val) {
+       *val=(Bit32u)readd(addr);       return false;
+}
+bool PageHandler::writeb_checked(PhysPt addr,Bitu val) {
+       writeb(addr,val);       return false;
+}
+bool PageHandler::writew_checked(PhysPt addr,Bitu val) {
+       writew(addr,val);       return false;
+}
+bool PageHandler::writed_checked(PhysPt addr,Bitu val) {
+       writed(addr,val);       return false;
+}
+
+
+
+struct PF_Entry {
+       Bitu cs;
+       Bitu eip;
+       Bitu page_addr;
+       Bitu mpl;
+};
+
+#define PF_QUEUESIZE 16
+static struct {
+       Bitu used;
+       PF_Entry entries[PF_QUEUESIZE];
+} pf_queue;
+
+static Bits PageFaultCore(void) {
+       CPU_CycleLeft+=CPU_Cycles;
+       CPU_Cycles=1;
+       Bits ret=CPU_Core_Full_Run();
+       CPU_CycleLeft+=CPU_Cycles;
+       if (ret<0) E_Exit("Got a dosbox close machine in pagefault core?");
+       if (ret) 
+               return ret;
+       if (!pf_queue.used) E_Exit("PF Core without PF");
+       PF_Entry * entry=&pf_queue.entries[pf_queue.used-1];
+       X86PageEntry pentry;
+       pentry.load=phys_readd(entry->page_addr);
+       if (pentry.block.p && entry->cs == SegValue(cs) && entry->eip==reg_eip) {
+               cpu.mpl=entry->mpl;
+               return -1;
+       }
+       return 0;
+}
+#if C_DEBUG
+Bitu DEBUG_EnableDebugger(void);
+#endif
+
+bool first=false;
+
+void PAGING_PageFault(PhysPt lin_addr,Bitu page_addr,Bitu faultcode) {
+       /* Save the state of the cpu cores */
+       LazyFlags old_lflags;
+       memcpy(&old_lflags,&lflags,sizeof(LazyFlags));
+       CPU_Decoder * old_cpudecoder;
+       old_cpudecoder=cpudecoder;
+       cpudecoder=&PageFaultCore;
+       paging.cr2=lin_addr;
+       PF_Entry * entry=&pf_queue.entries[pf_queue.used++];
+       LOG(LOG_PAGING,LOG_NORMAL)("PageFault at %X type [%x] queue %d",lin_addr,faultcode,pf_queue.used);
+//     LOG_MSG("EAX:%04X ECX:%04X EDX:%04X EBX:%04X",reg_eax,reg_ecx,reg_edx,reg_ebx);
+//     LOG_MSG("CS:%04X EIP:%08X SS:%04x SP:%08X",SegValue(cs),reg_eip,SegValue(ss),reg_esp);
+       entry->cs=SegValue(cs);
+       entry->eip=reg_eip;
+       entry->page_addr=page_addr;
+       entry->mpl=cpu.mpl;
+       cpu.mpl=3;
+
+       CPU_Exception(EXCEPTION_PF,faultcode);
+#if C_DEBUG
+//     DEBUG_EnableDebugger();
+#endif
+       DOSBOX_RunMachine();
+       pf_queue.used--;
+       LOG(LOG_PAGING,LOG_NORMAL)("Left PageFault for %x queue %d",lin_addr,pf_queue.used);
+       memcpy(&lflags,&old_lflags,sizeof(LazyFlags));
+       cpudecoder=old_cpudecoder;
+//     LOG_MSG("SS:%04x SP:%08X",SegValue(ss),reg_esp);
+}
+
+static INLINE void InitPageUpdateLink(Bitu relink,PhysPt addr) {
+       if (relink==0) return;
+       if (paging.links.used) {
+               if (paging.links.entries[paging.links.used-1]==(addr>>12)) {
+                       paging.links.used--;
+                       PAGING_UnlinkPages(addr>>12,1);
+               }
+       }
+       if (relink>1) PAGING_LinkPage_ReadOnly(addr>>12,relink);
+}
+
+static INLINE void InitPageCheckPresence(PhysPt lin_addr,bool writing,X86PageEntry& table,X86PageEntry& entry) {
+       Bitu lin_page=lin_addr >> 12;
+       Bitu d_index=lin_page >> 10;
+       Bitu t_index=lin_page & 0x3ff;
+       Bitu table_addr=(paging.base.page<<12)+d_index*4;
+       table.load=phys_readd(table_addr);
+       if (!table.block.p) {
+               LOG(LOG_PAGING,LOG_NORMAL)("NP Table");
+               PAGING_PageFault(lin_addr,table_addr,
+                       (writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04));
+               table.load=phys_readd(table_addr);
+               if (GCC_UNLIKELY(!table.block.p))
+                       E_Exit("Pagefault didn't correct table");
+       }
+       Bitu entry_addr=(table.block.base<<12)+t_index*4;
+       entry.load=phys_readd(entry_addr);
+       if (!entry.block.p) {
+//             LOG(LOG_PAGING,LOG_NORMAL)("NP Page");
+               PAGING_PageFault(lin_addr,entry_addr,
+                       (writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04));
+               entry.load=phys_readd(entry_addr);
+               if (GCC_UNLIKELY(!entry.block.p))
+                       E_Exit("Pagefault didn't correct page");
+       }
+}
+                       
+static INLINE bool InitPageCheckPresence_CheckOnly(PhysPt lin_addr,bool writing,X86PageEntry& table,X86PageEntry& entry) {
+       Bitu lin_page=lin_addr >> 12;
+       Bitu d_index=lin_page >> 10;
+       Bitu t_index=lin_page & 0x3ff;
+       Bitu table_addr=(paging.base.page<<12)+d_index*4;
+       table.load=phys_readd(table_addr);
+       if (!table.block.p) {
+               paging.cr2=lin_addr;
+               cpu.exception.which=EXCEPTION_PF;
+               cpu.exception.error=(writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04);
+               return false;
+       }
+       Bitu entry_addr=(table.block.base<<12)+t_index*4;
+       entry.load=phys_readd(entry_addr);
+       if (!entry.block.p) {
+               paging.cr2=lin_addr;
+               cpu.exception.which=EXCEPTION_PF;
+               cpu.exception.error=(writing?0x02:0x00) | (((cpu.cpl&cpu.mpl)==0)?0x00:0x04);
+               return false;
+       }
+       return true;
+}
+
+// check if a user-level memory access would trigger a privilege page fault
+static INLINE bool InitPage_CheckUseraccess(Bitu u1,Bitu u2) {
+       switch (CPU_ArchitectureType) {
+       case CPU_ARCHTYPE_MIXED:
+       case CPU_ARCHTYPE_386SLOW:
+       case CPU_ARCHTYPE_386FAST:
+       default:
+               return ((u1)==0) && ((u2)==0);
+       case CPU_ARCHTYPE_486OLDSLOW:
+       case CPU_ARCHTYPE_486NEWSLOW:
+       case CPU_ARCHTYPE_PENTIUMSLOW:
+               return ((u1)==0) || ((u2)==0);
+       }
+}
+
+
+class InitPageHandler : public PageHandler {
+public:
+       InitPageHandler() {
+               flags=PFLAG_INIT|PFLAG_NOCODE;
+       }
+       Bitu readb(PhysPt addr) {
+               Bitu needs_reset=InitPage(addr,false);
+               Bit8u val=mem_readb(addr);
+               InitPageUpdateLink(needs_reset,addr);
+               return val;
+       }
+       Bitu readw(PhysPt addr) {
+               Bitu needs_reset=InitPage(addr,false);
+               Bit16u val=mem_readw(addr);
+               InitPageUpdateLink(needs_reset,addr);
+               return val;
+       }
+       Bitu readd(PhysPt addr) {
+               Bitu needs_reset=InitPage(addr,false);
+               Bit32u val=mem_readd(addr);
+               InitPageUpdateLink(needs_reset,addr);
+               return val;
+       }
+       void writeb(PhysPt addr,Bitu val) {
+               Bitu needs_reset=InitPage(addr,true);
+               mem_writeb(addr,val);
+               InitPageUpdateLink(needs_reset,addr);
+       }
+       void writew(PhysPt addr,Bitu val) {
+               Bitu needs_reset=InitPage(addr,true);
+               mem_writew(addr,val);
+               InitPageUpdateLink(needs_reset,addr);
+       }
+       void writed(PhysPt addr,Bitu val) {
+               Bitu needs_reset=InitPage(addr,true);
+               mem_writed(addr,val);
+               InitPageUpdateLink(needs_reset,addr);
+       }
+       bool readb_checked(PhysPt addr, Bit8u * val) {
+               if (InitPageCheckOnly(addr,false)) {
+                       *val=mem_readb(addr);
+                       return false;
+               } else return true;
+       }
+       bool readw_checked(PhysPt addr, Bit16u * val) {
+               if (InitPageCheckOnly(addr,false)){
+                       *val=mem_readw(addr);
+                       return false;
+               } else return true;
+       }
+       bool readd_checked(PhysPt addr, Bit32u * val) {
+               if (InitPageCheckOnly(addr,false)) {
+                       *val=mem_readd(addr);
+                       return false;
+               } else return true;
+       }
+       bool writeb_checked(PhysPt addr,Bitu val) {
+               if (InitPageCheckOnly(addr,true)) {
+                       mem_writeb(addr,val);
+                       return false;
+               } else return true;
+       }
+       bool writew_checked(PhysPt addr,Bitu val) {
+               if (InitPageCheckOnly(addr,true)) {
+                       mem_writew(addr,val);
+                       return false;
+               } else return true;
+       }
+       bool writed_checked(PhysPt addr,Bitu val) {
+               if (InitPageCheckOnly(addr,true)) {
+                       mem_writed(addr,val);
+                       return false;
+               } else return true;
+       }
+       Bitu InitPage(Bitu lin_addr,bool writing) {
+               Bitu lin_page=lin_addr >> 12;
+               Bitu phys_page;
+               if (paging.enabled) {
+                       X86PageEntry table;
+                       X86PageEntry entry;
+                       InitPageCheckPresence(lin_addr,writing,table,entry);
+
+                       // 0: no action
+                       // 1: can (but currently does not) fail a user-level access privilege check
+                       // 2: can (but currently does not) fail a write privilege check
+                       // 3: fails a privilege check
+                       Bitu priv_check=0;
+                       if (InitPage_CheckUseraccess(entry.block.us,table.block.us)) {
+                               if ((cpu.cpl&cpu.mpl)==3) priv_check=3;
+                               else {
+                                       switch (CPU_ArchitectureType) {
+                                       case CPU_ARCHTYPE_MIXED:
+                                       case CPU_ARCHTYPE_386FAST:
+                                       default:
+//                                             priv_check=0;   // default
+                                               break;
+                                       case CPU_ARCHTYPE_386SLOW:
+                                       case CPU_ARCHTYPE_486OLDSLOW:
+                                       case CPU_ARCHTYPE_486NEWSLOW:
+                                       case CPU_ARCHTYPE_PENTIUMSLOW:
+                                               priv_check=1;
+                                               break;
+                                       }
+                               }
+                       }
+                       if ((entry.block.wr==0) || (table.block.wr==0)) {
+                               // page is write-protected for user mode
+                               if (priv_check==0) {
+                                       switch (CPU_ArchitectureType) {
+                                       case CPU_ARCHTYPE_MIXED:
+                                       case CPU_ARCHTYPE_386FAST:
+                                       default:
+//                                             priv_check=0;   // default
+                                               break;
+                                       case CPU_ARCHTYPE_386SLOW:
+                                       case CPU_ARCHTYPE_486OLDSLOW:
+                                       case CPU_ARCHTYPE_486NEWSLOW:
+                                       case CPU_ARCHTYPE_PENTIUMSLOW:
+                                               priv_check=2;
+                                               break;
+                                       }
+                               }
+                               // check if actually failing the write-protected check
+                               if (writing && USERWRITE_PROHIBITED) priv_check=3;
+                       }
+                       if (priv_check==3) {
+                               LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",
+                                       cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr);
+                               PAGING_PageFault(lin_addr,(table.block.base<<12)+(lin_page & 0x3ff)*4,0x05 | (writing?0x02:0x00));
+                               priv_check=0;
+                       }
+
+                       if (!table.block.a) {
+                               table.block.a=1;                // set page table accessed
+                               phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load);
+                       }
+                       if ((!entry.block.a) || (!entry.block.d)) {
+                               entry.block.a=1;                // set page accessed
+
+                               // page is dirty if we're writing to it, or if we're reading but the
+                               // page will be fully linked so we can't track later writes
+                               if (writing || (priv_check==0)) entry.block.d=1;                // mark page as dirty
+
+                               phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load);
+                       }
+
+                       phys_page=entry.block.base;
+                       
+                       // now see how the page should be linked best, if we need to catch privilege
+                       // checks later on it should be linked as read-only page
+                       if (priv_check==0) {
+                               // if reading we could link the page as read-only to later cacth writes,
+                               // will slow down pretty much but allows catching all dirty events
+                               PAGING_LinkPage(lin_page,phys_page);
+                       } else {
+                               if (priv_check==1) {
+                                       PAGING_LinkPage(lin_page,phys_page);
+                                       return 1;
+                               } else if (writing) {
+                                       PageHandler * handler=MEM_GetPageHandler(phys_page);
+                                       PAGING_LinkPage(lin_page,phys_page);
+                                       if (!(handler->flags & PFLAG_READABLE)) return 1;
+                                       if (!(handler->flags & PFLAG_WRITEABLE)) return 1;
+                                       if (get_tlb_read(lin_addr)!=get_tlb_write(lin_addr)) return 1;
+                                       if (phys_page>1) return phys_page;
+                                       else return 1;
+                               } else {
+                                       PAGING_LinkPage_ReadOnly(lin_page,phys_page);
+                               }
+                       }
+               } else {
+                       if (lin_page<LINK_START) phys_page=paging.firstmb[lin_page];
+                       else phys_page=lin_page;
+                       PAGING_LinkPage(lin_page,phys_page);
+               }
+               return 0;
+       }
+       bool InitPageCheckOnly(Bitu lin_addr,bool writing) {
+               Bitu lin_page=lin_addr >> 12;
+               if (paging.enabled) {
+                       X86PageEntry table;
+                       X86PageEntry entry;
+                       if (!InitPageCheckPresence_CheckOnly(lin_addr,writing,table,entry)) return false;
+
+                       if (!USERWRITE_PROHIBITED) return true;
+
+                       if (InitPage_CheckUseraccess(entry.block.us,table.block.us) ||
+                                       (((entry.block.wr==0) || (table.block.wr==0)) && writing)) {
+                               LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",
+                                       cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr);
+                               paging.cr2=lin_addr;
+                               cpu.exception.which=EXCEPTION_PF;
+                               cpu.exception.error=0x05 | (writing?0x02:0x00);
+                               return false;
+                       }
+               } else {
+                       Bitu phys_page;
+                       if (lin_page<LINK_START) phys_page=paging.firstmb[lin_page];
+                       else phys_page=lin_page;
+                       PAGING_LinkPage(lin_page,phys_page);
+               }
+               return true;
+       }
+       void InitPageForced(Bitu lin_addr) {
+               Bitu lin_page=lin_addr >> 12;
+               Bitu phys_page;
+               if (paging.enabled) {
+                       X86PageEntry table;
+                       X86PageEntry entry;
+                       InitPageCheckPresence(lin_addr,false,table,entry);
+
+                       if (!table.block.a) {
+                               table.block.a=1;                //Set access
+                               phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load);
+                       }
+                       if (!entry.block.a) {
+                               entry.block.a=1;                                        //Set access
+                               phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load);
+                       }
+                       phys_page=entry.block.base;
+                       // maybe use read-only page here if possible
+               } else {
+                       if (lin_page<LINK_START) phys_page=paging.firstmb[lin_page];
+                       else phys_page=lin_page;
+               }
+               PAGING_LinkPage(lin_page,phys_page);
+       }
+};
+
+class InitPageUserROHandler : public PageHandler {
+public:
+       InitPageUserROHandler() {
+               flags=PFLAG_INIT|PFLAG_NOCODE;
+       }
+       void writeb(PhysPt addr,Bitu val) {
+               InitPage(addr,(Bit8u)(val&0xff));
+               host_writeb(get_tlb_read(addr)+addr,(Bit8u)(val&0xff));
+       }
+       void writew(PhysPt addr,Bitu val) {
+               InitPage(addr,(Bit16u)(val&0xffff));
+               host_writew(get_tlb_read(addr)+addr,(Bit16u)(val&0xffff));
+       }
+       void writed(PhysPt addr,Bitu val) {
+               InitPage(addr,(Bit32u)val);
+               host_writed(get_tlb_read(addr)+addr,(Bit32u)val);
+       }
+       bool writeb_checked(PhysPt addr,Bitu val) {
+               Bitu writecode=InitPageCheckOnly(addr,(Bit8u)(val&0xff));
+               if (writecode) {
+                       HostPt tlb_addr;
+                       if (writecode>1) tlb_addr=get_tlb_read(addr);
+                       else tlb_addr=get_tlb_write(addr);
+                       host_writeb(tlb_addr+addr,(Bit8u)(val&0xff));
+                       return false;
+               }
+               return true;
+       }
+       bool writew_checked(PhysPt addr,Bitu val) {
+               Bitu writecode=InitPageCheckOnly(addr,(Bit16u)(val&0xffff));
+               if (writecode) {
+                       HostPt tlb_addr;
+                       if (writecode>1) tlb_addr=get_tlb_read(addr);
+                       else tlb_addr=get_tlb_write(addr);
+                       host_writew(tlb_addr+addr,(Bit16u)(val&0xffff));
+                       return false;
+               }
+               return true;
+       }
+       bool writed_checked(PhysPt addr,Bitu val) {
+               Bitu writecode=InitPageCheckOnly(addr,(Bit32u)val);
+               if (writecode) {
+                       HostPt tlb_addr;
+                       if (writecode>1) tlb_addr=get_tlb_read(addr);
+                       else tlb_addr=get_tlb_write(addr);
+                       host_writed(tlb_addr+addr,(Bit32u)val);
+                       return false;
+               }
+               return true;
+       }
+       void InitPage(Bitu lin_addr,Bitu val) {
+               Bitu lin_page=lin_addr >> 12;
+               Bitu phys_page;
+               if (paging.enabled) {
+                       if (!USERWRITE_PROHIBITED) return;
+
+                       X86PageEntry table;
+                       X86PageEntry entry;
+                       InitPageCheckPresence(lin_addr,true,table,entry);
+
+                       LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",
+                               cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr);
+                       PAGING_PageFault(lin_addr,(table.block.base<<12)+(lin_page & 0x3ff)*4,0x07);
+
+                       if (!table.block.a) {
+                               table.block.a=1;                //Set access
+                               phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load);
+                       }
+                       if ((!entry.block.a) || (!entry.block.d)) {
+                               entry.block.a=1;        //Set access
+                               entry.block.d=1;        //Set dirty
+                               phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load);
+                       }
+                       phys_page=entry.block.base;
+                       PAGING_LinkPage(lin_page,phys_page);
+               } else {
+                       if (lin_page<LINK_START) phys_page=paging.firstmb[lin_page];
+                       else phys_page=lin_page;
+                       PAGING_LinkPage(lin_page,phys_page);
+               }
+       }
+       Bitu InitPageCheckOnly(Bitu lin_addr,Bitu val) {
+               Bitu lin_page=lin_addr >> 12;
+               if (paging.enabled) {
+                       if (!USERWRITE_PROHIBITED) return 2;
+
+                       X86PageEntry table;
+                       X86PageEntry entry;
+                       if (!InitPageCheckPresence_CheckOnly(lin_addr,true,table,entry)) return 0;
+
+                       if (InitPage_CheckUseraccess(entry.block.us,table.block.us) || (((entry.block.wr==0) || (table.block.wr==0)))) {
+                               LOG(LOG_PAGING,LOG_NORMAL)("Page access denied: cpl=%i, %x:%x:%x:%x",
+                                       cpu.cpl,entry.block.us,table.block.us,entry.block.wr,table.block.wr);
+                               paging.cr2=lin_addr;
+                               cpu.exception.which=EXCEPTION_PF;
+                               cpu.exception.error=0x07;
+                               return 0;
+                       }
+                       PAGING_LinkPage(lin_page,entry.block.base);
+               } else {
+                       Bitu phys_page;
+                       if (lin_page<LINK_START) phys_page=paging.firstmb[lin_page];
+                       else phys_page=lin_page;
+                       PAGING_LinkPage(lin_page,phys_page);
+               }
+               return 1;
+       }
+       void InitPageForced(Bitu lin_addr) {
+               Bitu lin_page=lin_addr >> 12;
+               Bitu phys_page;
+               if (paging.enabled) {
+                       X86PageEntry table;
+                       X86PageEntry entry;
+                       InitPageCheckPresence(lin_addr,true,table,entry);
+
+                       if (!table.block.a) {
+                               table.block.a=1;                //Set access
+                               phys_writed((paging.base.page<<12)+(lin_page >> 10)*4,table.load);
+                       }
+                       if (!entry.block.a) {
+                               entry.block.a=1;        //Set access
+                               phys_writed((table.block.base<<12)+(lin_page & 0x3ff)*4,entry.load);
+                       }
+                       phys_page=entry.block.base;
+               } else {
+                       if (lin_page<LINK_START) phys_page=paging.firstmb[lin_page];
+                       else phys_page=lin_page;
+               }
+               PAGING_LinkPage(lin_page,phys_page);
+       }
+};
+
+
+bool PAGING_MakePhysPage(Bitu & page) {
+       if (paging.enabled) {
+               Bitu d_index=page >> 10;
+               Bitu t_index=page & 0x3ff;
+               X86PageEntry table;
+               table.load=phys_readd((paging.base.page<<12)+d_index*4);
+               if (!table.block.p) return false;
+               X86PageEntry entry;
+               entry.load=phys_readd((table.block.base<<12)+t_index*4);
+               if (!entry.block.p) return false;
+               page=entry.block.base;
+       } else {
+               if (page<LINK_START) page=paging.firstmb[page];
+               //Else keep it the same
+       }
+       return true;
+}
+
+static InitPageHandler init_page_handler;
+static InitPageUserROHandler init_page_handler_userro;
+
+
+Bitu PAGING_GetDirBase(void) {
+       return paging.cr3;
+}
+
+bool PAGING_ForcePageInit(Bitu lin_addr) {
+       PageHandler * handler=get_tlb_readhandler(lin_addr);
+       if (handler==&init_page_handler) {
+               init_page_handler.InitPageForced(lin_addr);
+               return true;
+       } else if (handler==&init_page_handler_userro) {
+               PAGING_UnlinkPages(lin_addr>>12,1);
+               init_page_handler_userro.InitPageForced(lin_addr);
+               return true;
+       }
+       return false;
+}
+
+#if defined(USE_FULL_TLB)
+void PAGING_InitTLB(void) {
+       for (Bitu i=0;i<TLB_SIZE;i++) {
+               paging.tlb.read[i]=0;
+               paging.tlb.write[i]=0;
+               paging.tlb.readhandler[i]=&init_page_handler;
+               paging.tlb.writehandler[i]=&init_page_handler;
+       }
+       paging.links.used=0;
+}
+
+void PAGING_ClearTLB(void) {
+       Bit32u * entries=&paging.links.entries[0];
+       for (;paging.links.used>0;paging.links.used--) {
+               Bitu page=*entries++;
+               paging.tlb.read[page]=0;
+               paging.tlb.write[page]=0;
+               paging.tlb.readhandler[page]=&init_page_handler;
+               paging.tlb.writehandler[page]=&init_page_handler;
+       }
+       paging.links.used=0;
+}
+
+void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) {
+       for (;pages>0;pages--) {
+               paging.tlb.read[lin_page]=0;
+               paging.tlb.write[lin_page]=0;
+               paging.tlb.readhandler[lin_page]=&init_page_handler;
+               paging.tlb.writehandler[lin_page]=&init_page_handler;
+               lin_page++;
+       }
+}
+
+void PAGING_MapPage(Bitu lin_page,Bitu phys_page) {
+       if (lin_page<LINK_START) {
+               paging.firstmb[lin_page]=phys_page;
+               paging.tlb.read[lin_page]=0;
+               paging.tlb.write[lin_page]=0;
+               paging.tlb.readhandler[lin_page]=&init_page_handler;
+               paging.tlb.writehandler[lin_page]=&init_page_handler;
+       } else {
+               PAGING_LinkPage(lin_page,phys_page);
+       }
+}
+
+void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) {
+       PageHandler * handler=MEM_GetPageHandler(phys_page);
+       Bitu lin_base=lin_page << 12;
+       if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE) 
+               E_Exit("Illegal page");
+
+       if (paging.links.used>=PAGING_LINKS) {
+               LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache");
+               PAGING_ClearTLB();
+       }
+
+       paging.tlb.phys_page[lin_page]=phys_page;
+       if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=handler->GetHostReadPt(phys_page)-lin_base;
+       else paging.tlb.read[lin_page]=0;
+       if (handler->flags & PFLAG_WRITEABLE) paging.tlb.write[lin_page]=handler->GetHostWritePt(phys_page)-lin_base;
+       else paging.tlb.write[lin_page]=0;
+
+       paging.links.entries[paging.links.used++]=lin_page;
+       paging.tlb.readhandler[lin_page]=handler;
+       paging.tlb.writehandler[lin_page]=handler;
+}
+
+void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page) {
+       PageHandler * handler=MEM_GetPageHandler(phys_page);
+       Bitu lin_base=lin_page << 12;
+       if (lin_page>=TLB_SIZE || phys_page>=TLB_SIZE) 
+               E_Exit("Illegal page");
+
+       if (paging.links.used>=PAGING_LINKS) {
+               LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache");
+               PAGING_ClearTLB();
+       }
+
+       paging.tlb.phys_page[lin_page]=phys_page;
+       if (handler->flags & PFLAG_READABLE) paging.tlb.read[lin_page]=handler->GetHostReadPt(phys_page)-lin_base;
+       else paging.tlb.read[lin_page]=0;
+       paging.tlb.write[lin_page]=0;
+
+       paging.links.entries[paging.links.used++]=lin_page;
+       paging.tlb.readhandler[lin_page]=handler;
+       paging.tlb.writehandler[lin_page]=&init_page_handler_userro;
+}
+
+#else
+
+static INLINE void InitTLBInt(tlb_entry *bank) {
+       for (Bitu i=0;i<TLB_SIZE;i++) {
+               bank[i].read=0;
+               bank[i].write=0;
+               bank[i].readhandler=&init_page_handler;
+               bank[i].writehandler=&init_page_handler;
+       }
+}
+
+void PAGING_InitTLBBank(tlb_entry **bank) {
+       *bank = (tlb_entry *)malloc(sizeof(tlb_entry)*TLB_SIZE);
+       if(!*bank) E_Exit("Out of Memory");
+       InitTLBInt(*bank);
+}
+
+void PAGING_InitTLB(void) {
+       InitTLBInt(paging.tlbh);
+       paging.links.used=0;
+}
+
+void PAGING_ClearTLB(void) {
+       Bit32u * entries=&paging.links.entries[0];
+       for (;paging.links.used>0;paging.links.used--) {
+               Bitu page=*entries++;
+               tlb_entry *entry = get_tlb_entry(page<<12);
+               entry->read=0;
+               entry->write=0;
+               entry->readhandler=&init_page_handler;
+               entry->writehandler=&init_page_handler;
+       }
+       paging.links.used=0;
+}
+
+void PAGING_UnlinkPages(Bitu lin_page,Bitu pages) {
+       for (;pages>0;pages--) {
+               tlb_entry *entry = get_tlb_entry(lin_page<<12);
+               entry->read=0;
+               entry->write=0;
+               entry->readhandler=&init_page_handler;
+               entry->writehandler=&init_page_handler;
+               lin_page++;
+       }
+}
+
+void PAGING_MapPage(Bitu lin_page,Bitu phys_page) {
+       if (lin_page<LINK_START) {
+               paging.firstmb[lin_page]=phys_page;
+               paging.tlbh[lin_page].read=0;
+               paging.tlbh[lin_page].write=0;
+               paging.tlbh[lin_page].readhandler=&init_page_handler;
+               paging.tlbh[lin_page].writehandler=&init_page_handler;
+       } else {
+               PAGING_LinkPage(lin_page,phys_page);
+       }
+}
+
+void PAGING_LinkPage(Bitu lin_page,Bitu phys_page) {
+       PageHandler * handler=MEM_GetPageHandler(phys_page);
+       Bitu lin_base=lin_page << 12;
+       if (lin_page>=(TLB_SIZE*(TLB_BANKS+1)) || phys_page>=(TLB_SIZE*(TLB_BANKS+1))) 
+               E_Exit("Illegal page");
+
+       if (paging.links.used>=PAGING_LINKS) {
+               LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache");
+               PAGING_ClearTLB();
+       }
+
+       tlb_entry *entry = get_tlb_entry(lin_base);
+       entry->phys_page=phys_page;
+       if (handler->flags & PFLAG_READABLE) entry->read=handler->GetHostReadPt(phys_page)-lin_base;
+       else entry->read=0;
+       if (handler->flags & PFLAG_WRITEABLE) entry->write=handler->GetHostWritePt(phys_page)-lin_base;
+       else entry->write=0;
+
+       paging.links.entries[paging.links.used++]=lin_page;
+       entry->readhandler=handler;
+       entry->writehandler=handler;
+}
+
+void PAGING_LinkPage_ReadOnly(Bitu lin_page,Bitu phys_page) {
+       PageHandler * handler=MEM_GetPageHandler(phys_page);
+       Bitu lin_base=lin_page << 12;
+       if (lin_page>=(TLB_SIZE*(TLB_BANKS+1)) || phys_page>=(TLB_SIZE*(TLB_BANKS+1))) 
+               E_Exit("Illegal page");
+
+       if (paging.links.used>=PAGING_LINKS) {
+               LOG(LOG_PAGING,LOG_NORMAL)("Not enough paging links, resetting cache");
+               PAGING_ClearTLB();
+       }
+
+       tlb_entry *entry = get_tlb_entry(lin_base);
+       entry->phys_page=phys_page;
+       if (handler->flags & PFLAG_READABLE) entry->read=handler->GetHostReadPt(phys_page)-lin_base;
+       else entry->read=0;
+       entry->write=0;
+
+       paging.links.entries[paging.links.used++]=lin_page;
+       entry->readhandler=handler;
+       entry->writehandler=&init_page_handler_userro;
+}
+
+#endif
+
+
+void PAGING_SetDirBase(Bitu cr3) {
+       paging.cr3=cr3;
+       
+       paging.base.page=cr3 >> 12;
+       paging.base.addr=cr3 & ~4095;
+//     LOG(LOG_PAGING,LOG_NORMAL)("CR3:%X Base %X",cr3,paging.base.page);
+       if (paging.enabled) {
+               PAGING_ClearTLB();
+       }
+}
+
+void PAGING_Enable(bool enabled) {
+       /* If paging is disabled, we work from a default paging table */
+       if (paging.enabled==enabled) return;
+       paging.enabled=enabled;
+       if (enabled) {
+               if (GCC_UNLIKELY(cpudecoder==CPU_Core_Simple_Run)) {
+//                     LOG_MSG("CPU core simple won't run this game,switching to normal");
+                       cpudecoder=CPU_Core_Normal_Run;
+                       CPU_CycleLeft+=CPU_Cycles;
+                       CPU_Cycles=0;
+               }
+//             LOG(LOG_PAGING,LOG_NORMAL)("Enabled");
+               PAGING_SetDirBase(paging.cr3);
+       }
+       PAGING_ClearTLB();
+}
+
+bool PAGING_Enabled(void) {
+       return paging.enabled;
+}
+
+class PAGING:public Module_base{
+public:
+       PAGING(Section* configuration):Module_base(configuration){
+               /* Setup default Page Directory, force it to update */
+               paging.enabled=false;
+               PAGING_InitTLB();
+               Bitu i;
+               for (i=0;i<LINK_START;i++) {
+                       paging.firstmb[i]=i;
+               }
+               pf_queue.used=0;
+       }
+       ~PAGING(){}
+};
+
+static PAGING* test;
+void PAGING_Init(Section * sec) {
+       test = new PAGING(sec);
+}